4

In OpenCV python, say we read an image with cv2.imread and get a BGR numpy array. We next generate a mask with the cv2.inRange command. The mask has the same width/height and each mask pixel is either black or white.

I want to copy a region from the mask (taken as an image of black and white pixels) onto a region of the color image.

How do I do that? This does not work

img[10:20,10:20] = mask[10:20,10:20]

Must I convert the mask to BGR image first? If so how?

Edit: I do not want to apply the whole mask to the image as in apply mask to color image. Another way to say what I want: see the mask as a black and white image. I want to copy a region of that image (as a set of black or white pixels) onto another image. The resulting image will be a color image except for one smaller rectangular region that contains only black or white pixels. The result will be similar to if I in photoshop copy a rectangular area of a black/white image and past that rectangle onto an area of a color image.

(I'm new to OpenCV)

Community
  • 1
  • 1
cv2asker
  • 43
  • 1
  • 4
  • What do you mean by "copy a region from the mask"? Can you show it using an image? – Håken Lid Jun 01 '16 at 16:23
  • The mask is binary. I want to copy each black or white pixel in the mask region (coordinates) onto (replacing) the same pixel region in the image. Similar to if I in photoshop select and copy a rectangular region on one image and paste it onto another image. – cv2asker Jun 01 '16 at 16:26
  • 1
    Possible duplicate of [apply mask to color image](http://stackoverflow.com/questions/10469235/apply-mask-to-color-image) – Håken Lid Jun 01 '16 at 16:32
  • If I understand the linked "apply mask to color image" page correctly it applies the whole mask to the image. I do not want that. Another way to say what I want: see the mask as a black and white image. I want to copy a region of that image (as a set of black or white pixels) onto another image. The resulting image will be a color image except for one smaller rectangular region that contains only black or white pixels (in the same pattern as in the mask image). – cv2asker Jun 01 '16 at 16:38
  • Ok. In that case you have to treat the mask as a image, and convert it to the same colorspace as `img` before merging them. Have you tried that? – Håken Lid Jun 01 '16 at 16:45
  • which in the list [ColorConversionCodes](http://docs.opencv.org/3.1.0/d7/d1b/group__imgproc__misc.html) should I use? I find no mask2bgr or similarly named code. – cv2asker Jun 01 '16 at 16:50
  • I've google "opencv mask to color", "opencv convert uint8 mask to color", etc but I can only find how to convert between color images or from images to mask. I've been stuck with this (seemingly small) problem for 2 hours and it is not pleasant. – cv2asker Jun 01 '16 at 16:58
  • I think `COLOR_GRAY2BGR` should work, assuming that the mask is a standard single channel image. – Håken Lid Jun 01 '16 at 16:59
  • I tried `mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)` but does not work. The mask is the output form `cv2.inRange` on the image. – cv2asker Jun 01 '16 at 17:17
  • Do you get an error message? I tested it myself and I didn't get any errors. Can you try the code I posted in my answer? – Håken Lid Jun 01 '16 at 17:30
  • Your answer works. Thank you. Turns out I ran into another (unrelated) error once past the colorconversion step. – cv2asker Jun 01 '16 at 20:49
  • Good to hear. You can mark my answer as accepted if your question has been answered. – Håken Lid Jun 01 '16 at 20:53

1 Answers1

0

If you try to do it with a single channel (grayscale) mask directly, the shapes of the array slices will not be the same, and the operation will fail.

>>> img[10:20,10:20] = mask[10:20,10:20]

ValueError: could not broadcast input array from shape (10,10) into shape (10,10,3)

You have to convert the mask to BGR, which will make it 3 channels, like the original image.

>>> bgr_mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
>>> img[10:20,10:20] = bgr_mask[10:20,10:20]
Håken Lid
  • 22,318
  • 9
  • 52
  • 67