Reputation: 583
I was looking at the documentation of the OpenCV and found something which I couldn't understand. I've tried to find it on the web but couldn't find anything satisfying. Can you please help me in a line of code? Here is the code:
# Load two images
img1 = cv.imread('messi5.jpg')
img2 = cv.imread('opencv-logo-white.png')
# I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
# Now create a mask of logo and create its inverse mask also
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)
# Now black-out the area of logo in ROI
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
# Take only region of logo from logo image.
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
# Put logo in ROI and modify the main image
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst
cv.imshow('res',img1)
cv.waitKey(0)
cv.destroyAllWindows()
What I actually don't understand are these two lines
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
What these lines actually do and how the masking will be applied?
If anyone can explain the masking being applied in the bitwise_and operation that would be really helpful.Thanks
Upvotes: 1
Views: 2318
Reputation: 1380
If you look at the tutorial.
The mask is the black and white image of the OpenCV logo, it was created from applying a threshold to the OpenCV logo.
The bitwise_and
operation is a logical and operation
In this case, it is taking two 8 bit numbers representing a pixel and applying the and operation on those numbers.
Documentation describes what this function does.
Since the first two parameters are the same (both roi
or img2
) the result would be the same image if a mask wasn't being used. Places, where the mask is black, are left the same as the destination image.
In this case, no destination image is provided, so OpenCV allocates a black image (zeros) for the destination image used in the function (this is generally how OpenCV works when a function is not provided with a Matrix).
Specifically img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
will create a black matrix used in the function which later becomes the output img1_bg
. Only the parts of this black image that match up with white pixels in mask_inv
are filled with the pixels from roi
.This means that in the mask_inv where there are white pixels. the roi value will be copied in the pure black image generated by the function in the corresponding coordinate.
Similarly img2_fg = cv.bitwise_and(img2,img2,mask = mask)
will create a black matrix used in the function which later becomes the output img2_fg
. Only the parts of this black image that match up with white pixels in mask
are filled with the pixels from img2
.
This makes it so when you add img1_bg
and img2_fg
the result is only the part of each image that is masked.
Personally, I think this is a confusing use of bitwise_and
. I think to demonstrate the function of bitwise_and
it would be clearer to remove the mask parameter as follows: img1_bg = cv.bitwise_and(roi, mask_inv)
. This would give the same result, zeros where the mask is black, and the ROI values where it is not since the mask has pixels that are all ones or all zeroes.
If you don't care to demonstrate bitwise_and
usage, in python I think it would be clearer to use logical indexing as follows:
output = np.zeros(img1.shape, np.uint8)
output[mask_inv] = img1_bg[mask_inv]
output[mask] = img2_fg[mask]
Upvotes: 1