Suppose I have a greyscale image here:
And a binary masked image here:
With the same dimensions and shape. How do I generate something like this:
Where the values indicated by the 1 in the binary mask are the real values, and values that are 0 in the mask are null in the final image.
A binary mask defines a region of interest (ROI) of an image. Mask pixel values of 1 indicate image pixels that belong to the ROI. Mask pixel values of 0 indicate image pixels that are part of the background. Depending on the application, an ROI can consist of contiguous or discontiguous groups of pixels.
use findContours or extract all mask points (manually) and use the minBoundingRect function. Afterwards use subimage to get the cropped image.
Use cv2.bitwise_and
to mask an image with a binary mask. Any white pixels on the mask (values with 1) will be kept while black pixels (value with 0) will be ignored. Here's a example:
Input image (left), Mask (right)
Result after masking
Code
import cv2
import numpy as np
# Load image, create mask, and draw white circle on mask
image = cv2.imread('1.jpeg')
mask = np.zeros(image.shape, dtype=np.uint8)
mask = cv2.circle(mask, (260, 300), 225, (255,255,255), -1)
# Mask input image with binary mask
result = cv2.bitwise_and(image, mask)
# Color background white
result[mask==0] = 255 # Optional
cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.waitKey()
Here are two other ways using Python Opencv. The first is similar to that of @nathancy. The second uses multiplication to do the masking. I use the same images as provided by @nathancy:
import cv2
import numpy as np
# read image
img = cv2.imread('pink_flower.png')
#mask it - method 1:
# read mask as grayscale in range 0 to 255
mask1 = cv2.imread('pink_flower_mask.png',0)
result1 = img.copy()
result1[mask1 == 0] = 0
result1[mask1 != 0] = img[mask1 != 0]
# mask it - method 2:
# read mask normally, but divide by 255.0, so range is 0 to 1 as float
mask2 = cv2.imread('pink_flower_mask.png') / 255.0
# mask by multiplication, clip to range 0 to 255 and make integer
result2 = (img * mask2).clip(0, 255).astype(np.uint8)
cv2.imshow('image', img)
cv2.imshow('mask1', mask1)
cv2.imshow('masked image1', result1)
cv2.imshow('masked image2', result2)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save results
cv2.imwrite('pink_flower_masked1.png', result1)
cv2.imwrite('pink_flower_masked2.png', result2)
Results are the same for both methods:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With