【问题标题】:Cut mask out of image with certain pixel margin numpy opencv从具有一定像素边距的图像中剪切蒙版 numpy opencv
【发布时间】:2020-06-14 20:51:46
【问题描述】:

我正在玩在 COCO 数据集上训练的 Mask RCNN (https://github.com/matterport/Mask_RCNN) 分割程序。它检测图像中的人(以及我进一步忽略的许多其他对象)并返回一个或多个人掩码,即布尔 Numpy 数组,其中包含归类为“人”的所有像素的 True 值和所有其他像素的 False 值:

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

现在我可以使用这个蒙版通过一些简单的 Numpy 数组索引将人从图像中删除:

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

这将返回以下图像:

由于 Mask_RCNN 程序返回的掩码非常紧凑,我想添加几个像素的边距(比如说 15px),这样我就会得到这样的结果:

我可以利用哪些 Numpy/OpenCV 函数从原始图像中切出遮罩(类似于 np.where),在遮罩周围添加 15 像素的边距?

【问题讨论】:

  • 您正在寻找cv2.dilate。这个想法是先扩大掩码,然后按位 - 并使用原始输入图像

标签: python image numpy opencv image-processing


【解决方案1】:

一种方法是使用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()
    

    掩码:

    new_mask:

    【讨论】:

      【解决方案3】:

      您正在寻找的功能是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()
      

      希望对你有帮助。

      【讨论】:

      • 什么是array 987654328 @?猜猜你的意思是kernel这里? span>
      • 什么是padding 987654331 @? span>
      • @ dirkschiller感谢您的评论。我更新了帖子,希望它更好地理解。您的问题应该由帖子知道。 span>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-01
      • 2020-10-24
      • 1970-01-01
      • 2017-10-02
      • 2019-12-25
      • 2015-11-04
      相关资源
      最近更新 更多