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