基于二进制掩码如何裁剪图像

6
我正在使用torch和一些语义分割算法来生成分割图像的二进制掩膜。然后,我想根据该掩膜裁剪图像。需要明确的是,我需要基于每个像素进行裁剪。这似乎是一个简单的问题,但我能想到的唯一解决方案要么是反转类似于Coco API中的draw mask函数,要么是迭代数组中的每个像素并在不需要时将像素设为黑色。我觉得有更好的方法来解决这个问题。对我来说,Lua、Python、Go或C++库都可以。有什么想法吗?

使用findContours或手动提取所有掩模点,并使用minBoundingRect函数。然后使用subimage获取裁剪后的图像。 - Micka
6个回答

7

假设你已经有了输入图像和掩码,我将使用Python实现这一过程。

假设src1是你的图像,src1_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)

现在,mask_out包含了图像src1中位于您定义的二进制掩模内部的部分。

7

这里有一个仅依赖于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))]

现在执行get_segment_crop(rgb, mask=segment_mask),其中rgb是形状为(w,h,c)的ndarray,而segment_mask是一个布尔值ndarray(即包含True/False条目),其形状为(w,h),假设w=宽度,h=高度。


2

2

如果有其他人遇到这个问题,我发现将火炬二进制掩码张量转换为Double类型,并使用火炬的cmul函数简单地乘以每个RGB通道是很有效的。基本上,因为二进制掩码在分割像素的位置上有一个1,那么值就会保持不变。而如果它在分割之外,则具有0,当跨越通道相乘时产生黑色。Saransh的答案也很好,对于open cv也很有效。


0

掩码在黑色背景上包含白色补丁

src1=cv2.imread('image.png',0)
mask=cv2.imread('label.png',0)
ret, thresh1 = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY)
src1 [thresh1==0] = 0

-1
你可以使用OpenCV中的boundingRect函数来获取感兴趣区域的矩形,然后你可以将图像裁剪到该矩形。一个Python实现看起来会像这样:
import numpy as np
import cv2

mask = np.zeros([600,600], dtype=np.uint8)
mask[200:500,200:500] = 255                 # set some values to 255 to represent an actual mask
rect = cv2.boundingRect(mask)               # function that computes the rectangle of interest
print(rect)

img = np.ones([600,600, 3], dtype=np.uint8) # arbitrary image
cropped_img = img[rect[1]:(rect[1]+rect[3]), rect[0]:(rect[0]+rect[2])] # crop the image to the desired rectangle 

用你自己的图片替换 maskimg


很不幸,我需要一个基于像素的裁剪解决方案。 - patrickbarker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接