I'm using numpy to build pixel arrays. An 800x600 image is an 3-dimensional array of uint8, 800x600x3. I also have a similar array with a fixed pattern (a checkerboard, see here). I have another array, 800x600 of mask values. Where the mask is zero, I want to copy the pattern pixel to the image pixel. Where the mask is not zero, I want to leave the image pixel alone.
>>> image.shape (800, 600, 3) >>> chex.shape (800, 600, 3) >>> mask.shape (800, 600)
This feels like it should work:
image[mask == 0,...] = chex
but gives "ValueError: array is not broadcastable to correct shape".
What do I use to copy chex pixels to image pixels where mask is zero?
import numpy as np arr = np. arange(27). reshape(3,3,3) #3 channel image mask = np. zeros(shape=(3,3)) mask[1,1] = 1 # binary mask mask_3d = np.
A masked array is the combination of a standard numpy. ndarray and a mask. A mask is either nomask , indicating that no value of the associated array is invalid, or an array of booleans that determines for each element of the associated array whether the value is valid or not.
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 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)
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)
I should also note that PIL.Image
(from the Pillow
library) has the ability to paste an image onto another image with fewer steps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With