如何在Python中使用OpenCV的connectedComponentsWithStats?

79

我正在寻找一个使用OpenCV的connectedComponentsWithStats()函数的Python示例。请注意,此功能仅适用于OpenCV 3或更新版本。官方文档仅显示了C++的API,即使在为Python编译时也存在该函数。我无法在任何地方在线找到它。


有关如何使用标签来遮盖图像等方面的见解,请参见Python OpenCV - 连通组件标记和分析 - GeeksforGeeks - nealmcb
4个回答

143

该函数的工作方式如下:

# Import the cv2 library
import cv2
# Read the image you want connected components of
src = cv2.imread('/directorypath/image.bmp')
# Threshold it so it becomes binary
ret, thresh = cv2.threshold(src,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# You need to choose 4 or 8 for connectivity type
connectivity = 4  
# Perform the operation
output = cv2.connectedComponentsWithStats(thresh, connectivity, cv2.CV_32S)
# Get the results
# The first cell is the number of labels
num_labels = output[0]
# The second cell is the label matrix
labels = output[1]
# The third cell is the stat matrix
stats = output[2]
# The fourth cell is the centroid matrix
centroids = output[3]

标签是一个矩阵,其大小与输入图像相同,其中每个元素的值等于其标签。

统计信息是函数计算出的统计信息的矩阵。它的长度等于标签数量,宽度等于统计信息的数量。可以与OpenCV文档一起使用:

每个标签的统计输出,包括背景标签,请参见下面提供的可用统计信息。可以通过stats[label, COLUMN]访问统计信息,其中列的名称在下面定义。

  • cv2.CC_STAT_LEFT 包围框在水平方向上的最左(x)坐标,其中包括开始位置。
  • cv2.CC_STAT_TOP 包围框在垂直方向上的最顶(y)坐标,其中包括开始位置。
  • cv2.CC_STAT_WIDTH 包围盒的水平大小
  • cv2.CC_STAT_HEIGHT 包围盒的垂直大小
  • cv2.CC_STAT_AREA 连通组件的总面积(以像素为单位)

质心是一个矩阵,其中包含每个质心的x和y位置。该矩阵中的行对应于标签编号。


1
@ypnos,您不需要使用stats来获取已连接组件的信息,但对于没有stats的已连接组件需要使用。我认为那部分只是剩下来的,因为我之前是另一种方法。现在我已经修复了。干杯! - Zack Knopp
2
有人能解释一下如何使用标签吗?如何检查质心是否匹配标签? - recurf
3
图像中的每个组件都会得到一个数字标签。背景的标签为0,其他附加对象的标签从1到“num_labels-1”进行编号。质心也按照相同的数字标签进行索引。centroids[0]并不是特别有用——它只代表背景。你需要的是 centroids[1:num_labels] - krs013
@ZackKnopp 这是不正确的,你也可以像这样使用函数而不需要统计信息:_, labels = cv2.connectedComponents(segmentation) :) - smcs
3
你可以使用组件区域创建一个数组:areas=output[2][:,4],然后创建一个包含组件数字的数组:nr=np.arange(output[0])。然后按区域大小对它们进行排序:ranked=sorted(zip(areas,nr))。参考这里的帮助: https://dev59.com/PGw15IYBdhLWcg3wbbNx - smcs
显示剩余7条评论

21

我来这里几次是为了回忆它的工作方式,每次都要把上面的代码简化成:

_, thresh = cv2.threshold(src,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
connectivity = 4  # You need to choose 4 or 8 for connectivity type
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh , connectivity , cv2.CV_32S)

希望对每个人都有用:)


11

Zack Knopp 的回答中,补充一点: 如果你正在使用灰度图像,你可以简单地使用以下方法:

import cv2
import numpy as np

src = cv2.imread("path\\to\\image.png", 0)
binary_map = (src > 0).astype(np.uint8)
connectivity = 4 # or whatever you prefer

output = cv2.connectedComponentsWithStats(binary_map, connectivity, cv2.CV_32S)

当我尝试使用 Zack Knopp 的答案来处理灰度图像时,它没有起作用,以下是我的解决方案。


0

输入图像需要是单通道的。因此,首先要转换为灰度图像,否则在opencv 4.x中会导致错误。您需要将其转换为灰度图像,然后再使用Zack的答案。

src = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

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