2

I'm trying to apply a color mask to a color image. The color mask is an outline that I want to apply to the color image. The mask is all black except for the outline which is pink ( BGR = [180, 105,255]). Oddly, I am able to apply an outline that is cyan [227,230,49] using the following method:

Let the color image be imgColor and the cyan outline be maskCyan. Again, this mask is all black [0,0,0] except for the pixels that are part of the outline which are [227,230,49]. Then I can apply this over the image by just doing imgColor_with_cyan_outline = cv2.bitwise_or(imgColor, maskCyan). When I do this same this with maskPink which has pink pixels instead of cyan using imgColor_with_pink_outline = cv2.bitwise_or(imgColor, maskPink) then I am returned the original image without any mask or outline applied to it. I think I'm just misunderstanding how cv2.bitwise_or() works, but I'm not sure.

Is there any other way to apply a color mask to a color image?

TheStrangeQuark
  • 2,257
  • 5
  • 31
  • 58
  • 1
    Possible duplicate of [Copying values from one numpy matrix to another dependent on boolean mask](https://stackoverflow.com/questions/22255368/copying-values-from-one-numpy-matrix-to-another-dependent-on-boolean-mask) – Dan Mašek Oct 24 '17 at 17:02
  • 1
    bitwise or -> takes each bit and do OR with the same bit in the other image. for instance if you pixel 63 in one image and 255 in the other one it will result in 255. If you have 63 and 72, will give 127 (63 is 00111111 adn 72 is 01001000 in binary). You can do and with the inverse of the mask as binary (white and black) to "remove" the pixel, or turn them black from the image. Then add it with the cyan one and you get the cyan one in the image, or use numpy to substitute as @DanMašek link – api55 Oct 25 '17 at 11:22

2 Answers2

3

I think you misunderstood the properties of bitwise OR operation. The cv2.bitwise_or takes two source images plus an optional mask.

cv2.bitwise_or(src1, src2, dst, mask)

So if src1 has a pixel with value 1 and src2 has a pixel with value 2, then src1 | src2 is:

0001 = src1
0010 = src2
0011 = src1 | src2

which makes the resultant pixel value 3. For 8-bit unsigned char images, the maximum resultant pixel value will be 255 (135 | 235 is 255).

zindarod
  • 6,328
  • 3
  • 30
  • 58
  • That makes more sense. I thought it meant that it would take the second value if it wasn't 0. So if you had `cv2.bitwise_or([255,255,255],[0,0,0]) = [255,255,255]` and `cv2.bitwise_or([255,255,255],[126,122,0]) = [126,122,0]`. That's what I really need is some function that will replace any pixels in the first image with non-zero pixels from the second argument. – TheStrangeQuark Oct 24 '17 at 14:30
  • @greenthumbtack What you want is to copy one image to another based on mask. For that see this excellent post: https://stackoverflow.com/questions/41572887/equivalent-of-copyto-in-python-opencv-bindings – zindarod Oct 24 '17 at 17:17
0

You can use cv2.inrange function for masking if you have a baundary for filtering. Modify following code as your values. Check for syntax according to your opencv version

Pink=cv2.inrange(pink baundary)
Black=cv2.inrange(black baundary)
Mask= Pink+Black

For more information you can read

https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_colorspaces/py_colorspaces.html

onur aslan
  • 283
  • 3
  • 8
  • How would I use this? The mask has only 2 colors on it, black and pink. I thought `inrange` is for looking for a color in an image, not applying a mask. – TheStrangeQuark Oct 24 '17 at 14:38