pythonnumpyopencv

Any efficient way to create a multidimensional mask with numpy?


I am trying to replace a specific color like below

mask=img==color
img[mask]=newcolor

but obviously the mask is a 2D 3 color array so the following error will be raised

TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions

Creating for loop like below can be a solution but it is not efficient

mask=np.zeros(img.shape[:2]).reshape(-1).astype(np.bool_)
for i,m in enumerate((img==np.array(color)).reshape(-1,len(img[0,0]))):
        mask[i]=np.sum(m)==len(img[0,0])

I do know that opencv do have a function to create mask like

mask=cv2.inRange(img, np.array(color), np.array(color))

but I want to know how can I make it with numpy only


Solution

  • Use logical and to reduce (ndarray.all() method) the last axis of mask:

    >>> img.shape
    (438, 313, 3)
    >>> color.shape
    (3,)
    >>> mask = (img == color).all(-1)
    >>> mask.shape
    (438, 313)
    >>> newcolor.shape
    (3,)
    >>> img[mask] = newcolor
    >>>