Use numpy to mask an image with a pattern?

Try:

image[mask[:] == 0,...] = chex[mask[:] == 0,...]

idx=(mask==0)
image[idx]=chex[idx]

Note that image has shape (800,600,3), while idx has shape (800,600). The rules for indexing state

if the selection tuple is smaller than n, then as many : objects as needed are added to the end of the selection tuple so that the modified selection tuple has length N.

Thus indexing arrays have a sort of broadcasting ability of their own. idx's shape gets promoted to (800,600,:)


I found it easiest to create a mask wherein 1 = "pixel to keep" and 0 = "pixel to remove".

Then I multiplied my image by that mask to remove the unwanted pixels. Example to retain only the frame (outside) of a portrait:

from scipy.misc import imread
import matplotlib.pyplot as plt
import numpy as np

im = imread('portrait.jpg', mode='L') # read in image
plt.imshow(im) # show the original image

enter image description here

mask = np.ones(im.shape) # create a mask with the image's shape
bw = 0.1 # identify border width and height as fraction of image size
bx = int(im.shape[1] * bw) # get the x dimension border width
by = int(im.shape[0] * bw) # get the y dimension border height
mask[bx:-bx,by:-by] = 0 # create a mask with 1 for border and 0 for inside

masked = im * mask # multiply `im` by the mask to zero out non-border pixels
plt.imshow(masked) # show the result of the masking operation

enter image description here


I wanted to illustrate an example using @unutbu answer. In this scenario, I have an image of a cat that I rotate. This rotation causes some black edges that look ugly especially when pasted on a non-black background.

import matplotlib.pyplot as plt
from scipy.ndimage import rotate


cat = plt.imread('cat.jpeg')
bg = plt.imread('background.jpeg')


rotcat = rotate(cat, angle=8, reshape=True) ## rotating creates some black edges
height, width, _ = rotcat.shape

bgcopy = bg.copy() ## create a copy of the background; paste on copy

x, y = 40, 50 
bgcopy[x:x+height, y:y+width] = rotcat
plt.imsave('cat-on-bg-mask.jpg', bgcopy)

bad pasting

So, I find the areas of the mask and replace those values with the original background values

mask_ind = (bgcopy == 0)
bgcopy[mask_ind] = bg[mask_ind]
plt.imsave('cat-on-bg.jpg', bgcopy)

good pasting

I should also note that PIL.Image (from the Pillow library) has the ability to paste an image onto another image with fewer steps.