从图像中裁剪带有特定像素边距的掩码 numpy opencv

4

我正在尝试使用Mask RCNN ( https://github.com/matterport/Mask_RCNN )分割程序,该程序经过COCO数据集的训练。它可以检测图像中的人物(以及我进一步忽略的许多其他对象),并返回一个或多个人体掩膜,即布尔Numpy数组。所有被分类为“人类”的像素都包含True值,而其他像素则包含False值:

Overlay Image

因此,输入的图像(uint8,形状为(3900,2922,3)的数组)变成了一个掩膜(形状为(3900,2922)的布尔数组),或者在图像中检测到多个人体时变成多个掩膜。

现在我可以使用这个掩膜通过简单的Numpy数组索引将人物从图像中剪切出来:

mask3d = np.dstack([mask]*3)
cut_out_mask = np.invert(mask3d)
res = np.where(cut_out_mask, 0, image)

这将返回以下图像:Cut_out Image 由于Mask_RCNN程序返回的掩码非常紧密,因此我想添加几个像素的边距(比如15px),以便获得以下结果:manual 我应该使用哪些Numpy / OpenCV函数来从原始图像中剪切掩码(类似于np.where),并在掩码周围添加15像素的边距?

3
您需要使用cv2.dilate函数。其思路是先对掩模进行膨胀操作,然后与原始输入图像进行按位与运算。 - nathancy
3个回答

4
一种方法是使用cv2.dilate来增加掩膜的表面积。根据掩膜的形状,您可以使用cv2.getStructuringElement创建不同的结构元素形状和大小。
例如,如果掩膜的形状是矩形,则可能要使用cv2.MORPH_RECT,如果掩膜的形状是圆形,则可以使用cv2.MORPH_ELLIPSE。此外,您可以更改内核大小和扩张的迭代次数。扩张掩膜后,您可以使用cv2.bitwise_and获取结果。以下是最小可重现示例:
原始图像 掩膜 扩张 按位与获取结果
import cv2

# Load image and mask
image = cv2.imread('1.png')
mask = cv2.imread('mask.png')

# Create structuring element, dilate and bitwise-and
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,25))
dilate = cv2.dilate(mask, kernel, iterations=3)
result = cv2.bitwise_and(image, dilate)

cv2.imshow('dilate', dilate)
cv2.imshow('result', result)
cv2.waitKey()

2
您可以使用形态学操作cv2.dilate来扩大掩膜:
new_mask = cv2.dilate(mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (50,50)))

加载蒙版并扩大蒙版的示例代码:
import cv2

# Read the mask from a file (for testing).
mask = cv2.imread("sample_mask.png", cv2.IMREAD_GRAYSCALE);

new_mask = cv2.dilate(mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (50,50)))

# Display mask and new_mask
cv2.imshow('mask', mask)
cv2.imshow('new_mask', new_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

口罩:
输入图像描述 新口罩:
输入图像描述

1
您要查找的函数是cv2.filter2D()
我为您编写了一个简短的演示:
import numpy as np
import cv2

首先,我们创建一个演示遮罩,其中包含中间的一个正方形:
mask = np.zeros((300, 300))
mask[100:200, 100:200] = 1

然后我们为filter2D函数创建核心:
kernel = np.ones((32, 32))

我使用了32号字体大小,以获得所需的15像素填充。

paddedMask = cv2.filter2D(mask, 1, kernel)

为了演示,我使用以下代码显示图像:

image = cv2.threshold(np.array(paddedMask, dtype=np.uint8), 1, 255, 1)[1]
cv2.imshow("Test", image)
cv2.imshow("Org", mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

希望它有所帮助。

paddedMask = cv2.filter2D(mask, 1, array)中,array是什么?你是不是指的是kernel - Dirk Schiller
image = cv2.threshold(np.array(padding, type=np.uint8), 1, 255, 1)[1] 中,padding 是什么意思? - Dirk Schiller
1
@DirkSchiller 感谢您的评论。我更新了帖子,希望更易理解。您的问题应该已经在帖子中得到了回答。 - MunsMan

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