I am using torch with some semantic segmentation algorithms to produce a binary mask of the segmented images. I would then like to crop the images based on that mask. To be clear I need to crop it on a per pixel basis. It seems like a simple problem but the only solution I can conjure up is to either invert a draw mask
function like in the Coco API, or iterate over each pixel in the array and mask together setting the pixel to black if not needed. I feel like there is a better way of doing this. Libraries in Lua, Python, Go, or C++ will work for me. Any ideas?
I've implemented this in Python, assuming that you have your input image and mask available as Mat Objects. Given that src1 is your image and src1_mask is your binary mask:
src1_mask=cv2.cvtColor(src1_mask,cv2.COLOR_GRAY2BGR)#change mask to a 3 channel image
mask_out=cv2.subtract(src1_mask,src1)
mask_out=cv2.subtract(src1_mask,mask_out)
Now mask_out contains the part of the image src1 located inside the binary mask you defined.
Here is a solution relying only on numpy:
def get_segment_crop(img,tol=0, mask=None):
if mask is None:
mask = img > tol
return img[np.ix_(mask.any(1), mask.any(0))]
now execute get_segment_crop(rgb, mask=segment_mask)
where rgb
is an ndarray of shape (w,h,c) and segment_mask
is a boolean ndarray (i.e. containing True/False entries) of shape (w,h), given that w=width, h=height.
For anyone else running into this. I found good luck with converting the torch binary mask tensor into type Double
, and then simply multiplying it using torch's cmul
function against each of the RGB channels. Basically, because the binary mask has a 1
in place of a segmented pixel, then the value will just remain. Whereas if it is outside the segmentation it has a 0
which when multiplied across the channels produces black. Saransh's answer is also good, and works well for open cv.
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