在OpenCV中,Matlab的Bwareaopen等效函数是什么?

5

我正在尝试在OpenCV中寻找与Matlab的Bwareaopen函数类似或等效的功能。

在MatLab中,Bwareaopen(image,P)从二进制图像中删除所有连接组件(对象),这些对象少于P个像素。

在我的单通道图像中,我想简单地删除不属于更大区域的小区域。有没有什么简单的方法来解决这个问题?

4个回答

4
请看cvBlobsLib,它有能够实现你想要的功能的函数。事实上,那个链接首页的代码示例恰好可以实现你的需求。 基本上,你可以使用CBlobResult对二值图像进行连通区域标记,然后调用Filter按照你的条件排除斑块。

感谢tzaman的快速回答,你说得对,cvBlobsLib正是我需要的。但现在的问题是,我不确定能否将这些cvBlobsLib导入我的Xcode项目(iPhone)库中,即使是导入opencv库,我已经做了很多工作。你认为我可以只复制我需要的库中的代码部分吗? - Miha
我自己并没有使用过cvBlobsLib(或Xcode!),但它以源代码的形式分发,所以您应该能够将所有.cpp.h文件添加到您的项目中,#include相应的头文件,然后就可以从那里开始了。 - tzaman
另外,如果答案有帮助,请不要忘记接受/点赞! :) - tzaman
不能只将.cpp和.h文件包含到项目中 :( 我想我需要适用于Mac的版本! - Miha

3

虽然没有这样的功能,但您可以按照以下步骤进行操作: 1)查找轮廓 2)查找轮廓面积 3)过滤所有面积小于阈值的外部轮廓 4)创建新的黑色图像 5)在其上绘制剩余轮廓 6)使用原始图像进行遮罩处理


我不建议使用轮廓进行工作,因为OpenCV在定义轮廓方面并不是非常准确。连接组件(带有统计信息和一些掩膜)可以更好地完成相同的任务。 - Christoph Rackwitz

1

我曾经遇到同样的问题,并编写了一个使用connectedComponentsWithStats()函数的功能:

    def bwareaopen(img, min_size, connectivity=8):
        """Remove small objects from binary image (approximation of 
        bwareaopen in Matlab for 2D images).
    
        Args:
            img: a binary image (dtype=uint8) to remove small objects from
            min_size: minimum size (in pixels) for an object to remain in the image
            connectivity: Pixel connectivity; either 4 (connected via edges) or 8 (connected via edges and corners).
    
        Returns:
            the binary image with small objects removed
        """
    
        # Find all connected components (called here "labels")
        num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(
            img, connectivity=connectivity)
        
        # check size of all connected components (area in pixels)
        for i in range(num_labels):
            label_size = stats[i, cv2.CC_STAT_AREA]
            
            # remove connected components smaller than min_size
            if label_size < min_size:
                img[labels == i] = 0
                
        return img

关于connectedComponentsWithStats()的澄清,请参见:

如何使用OpenCV删除小的连接对象
https://www.programcreek.com/python/example/89340/cv2.connectedComponentsWithStats https://python.hotexamples.com/de/examples/cv2/-/connectedComponentsWithStats/python-connectedcomponentswithstats-function-examples.html


0

与您的问题最接近的OpenCV解决方案是形态学闭合或开放

假设您的图像中有需要去除的白色区域。您可以使用形态学开放。开放是侵蚀+膨胀,按顺序执行。侵蚀是指缩小图像中的白色区域。膨胀是(相反的)其中图像中的白色区域被扩大。当您执行开放操作时,您的小白色区域会被侵蚀直到消失。较大的白色特征不会消失,但将从边界侵蚀。随后的膨胀步骤恢复它们的原始大小。然而,由于在侵蚀步骤中消失了小元素,因此它们在膨胀后的最终图像中不会出现。

例如,考虑这个image,我们想要删除小的白色区域,但保留3个大的白色椭圆形。运行以下代码可删除白色区域并显示干净的图像

import cv2
im = cv2.imread('sample.png')
clean = cv2.morphologyEx(im, cv2.MORPH_OPEN, np.ones((10, 10)))
cv2.imshwo("Clean image", clean)

干净的图像输出应该是 像这样

上面的命令使用了大小为10的方形块作为内核。 您可以修改此以满足您的要求。 您甚至可以使用函数getStructuringElement()生成更高级的内核。

请注意,如果您的图像是反转的,即背景为白色噪声的黑色,您只需要使用形态学闭运算(cv2.MORPH_CLOSE方法)而不是开运算。 这将颠倒操作顺序-首先侵蚀图像,然后扩张。


注意:开/闭形态学可以并且将改变斑点的形状,即使它没有被移除。最好使用连通组件进行处理。我不建议使用轮廓,因为OpenCV在定义轮廓方面并不是非常准确。 - Christoph Rackwitz

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