What does bitwise_and operator exactly do in openC

2020-06-03 10:46发布

问题:

I did not exactly understand what the "bitwise_and" operator does when used in openCV. I would also like to know about it's parameters.

回答1:

bitwise_and

Calculates the per-element bit-wise conjunction of two arrays or an array and a scalar.

Parameters:

  • src1 – first input array or a scalar.
  • src2 – second input array or a scalar.
  • src – single input array.
  • value – scalar value.
  • dst – output array that has the same size and type as the input arrays.
  • mask – optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.

Here is an example found on the web: http://docs.opencv.org/trunk/d0/d86/tutorial_py_image_arithmetics.html



回答2:

The general usage is that you want to get a subset of an image defined by another image, typically referred to as a "mask".

So suppose you want to "grab" the top left quadrant of an 8x8 image. You could form a mask that looks like:

1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

You could produce the above image with Python with:

import numpy as np

mask = np.zeros(shape=(8,8), dtype=bool)
mask[0:4,0:4] = True

Then suppose you had an image like:

1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

For concreteness, imagine that the above image is a simplified representation of the U.S.A. flag: stars in the top left, bars everywhere else. Suppose you wanted to form the above image. You could use the mask, and bitwise_and and bitwise_or to help you.

imageStars = np.ones(shape=(8,8), dtype=bool)
for r, row in enumerate(imageStars):
    for c, col in enumerate(row):
        if r % 2 != c % 2: # even row, odd column, or odd row, even column
            imageStars[r,c] = False

imageBars = np.zeros(shape=(8,8), dtype=bool)
for r, row in enumerate(imageStars):
    if r % 2 == 0:
        imageBars[r,:] = True

Now you have an image of stars:

1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1    
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1    
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1    
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1

And an image of bars:

1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

And you want to combine them in a particular way, to form the flag, with the stars in the upper left quadrant and the bars everywhere else.

imageStarsCropped = cv2.bitwise_and(imageStars, mask)

imageStarsCropped will look like:

1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0    
1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0  
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Do you see how it was formed? The bitwise_and returns 1 at every pixel where imageStars is 1 AND mask is 1; else, it returns 0.

Now let's get imageBarsCropped. First, let's reverse the mask:

maskReversed = cv2.bitwise_not(mask)

bitwise_not turns 1's into 0's and 0's into 1's. It "flips the bits". maskReversed will look like:

0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

Now, we will use maskReversed to "grab" the portion of imageBars that we want.

imageBarsCropped = cv2.bitwise_and(imageBars, maskReversed)

imageBarsCropped will look like:

0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

Now, let's combined the two "cropped" images to form the flag!

imageFlag = cv2.bitwise_or(imageStarsCropped, imageBarsCropped)

imageFlag will look like:

1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

Do you see why? bitwise_or returns 1 whenever imageStarsCropped[r,c]==1 OR imageBarsCropped[r,c]==1.

Well, I hope this helps you to understand bitwise operations in OpenCV. These properties have a one-to-one correspondences with bitwise operations with binary numbers that the computer does to do arithmetic.



回答3:

The answer by @mannyglover with the US flag example is a great one! I would also just quickly add that for actual images, any pixel value above 0 would translate to 'true' (or 1 in @mannyglover's example), and '0' (pitch black) would be 'false'.

This means after doing bitwise_and, any pitch black pixel of the mask would turn that respective pixel in the original image black. (since 0 & anything = 0)

Here is an example, done in OpenCV:

Original image: stack.jpg

Mask: mask.jpg

After applying result = cv2.bitwise_and(stack, stack, mask=mask) : result.jpg