如何使用OpenCV和Python提取最大的连通组件?

6

我正在使用Python中的OpenCV来识别图像上呈现的叶子。我已经能够分割图像,但现在我卡在了“如何在检测到所有组件后裁剪最大组件”的问题上。以下是代码,请查看。

  1. Using scipy.ndimage, I was unable to advance after find the components:

    def undesired_objects ( image ):
        components, n = ndimage.label( image )
        components = skimage.morphology.remove_small_objects( components, min_size = 50 )
        components, n = ndimage.label( components )
        plot.imshow( components )
        plot.show()
    
  2. Using OpenCV connectedComponentsWithStats:

    def undesired_objects ( image ):
        image = image.astype( 'uint8' )
        nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=4)
        sizes = stats[1:, -1]; nb_components = nb_components - 1
        min_size = 150
        img2 = np.zeros(( output.shape ))
        for i in range(0, nb_components):
            if sizes[i] >= min_size:
                img2[output == i + 1] = 255
                plot.imshow( img2 )
                plot.show()
    
然而,在这两种方法中,我仍然得到了一个以上的组件作为结果。下面是二进制图像:

Binary Image


你能上传你试图找到最大连通组件的二进制图像吗? - ZdaR
@ZdaR 已更新二进制图像! - Tarcisiofl
你的结果出了什么问题?你的代码不能保证只输出一个组件。它会选择所有大于你的 min_size 参数的组件。而且,由于你没有在不同的组件之间清除你的 img2,它们最终都会被绘制在同一张图像上。 - Sunreef
是的,@Sunreef。我想删除min_size参数,只选择更大的那个;但是,我卡在这里了。 - Tarcisiofl
2个回答

8
我会用以下代码替换你的代码:

我会使用以下代码替换你的代码:

def undesired_objects (image):
    image = image.astype('uint8')
    nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=4)
    sizes = stats[:, -1]

    max_label = 1
    max_size = sizes[1]
    for i in range(2, nb_components):
        if sizes[i] > max_size:
            max_label = i
            max_size = sizes[i]

    img2 = np.zeros(output.shape)
    img2[output == max_label] = 255
    cv2.imshow("Biggest component", img2)
    cv2.waitKey()

循环现在会找到面积最大的组件,并将其显示在循环结束时。如果这个方法可行,请告诉我,因为我自己还没有测试过它。

谢谢,@Sunreef。它运行良好;然而,我的结果仍然很差,我需要找到另一种方法来解决我的问题。 - Tarcisiofl

2

使用 cv2.CC_STAT_AREA 以提高可读性:

# Connected components with stats.
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=4)

# Find the largest non background component.
# Note: range() starts from 1 since 0 is the background label.
max_label, max_size = max([(i, stats[i, cv2.CC_STAT_AREA]) for i in range(1, nb_components)], key=lambda x: x[1])

更多信息请参见:https://dev59.com/UFsV5IYBdhLWcg3wuw-M#35854198

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