Ter*_*tin 4 python opencv image-processing noise-reduction connected-components
所以我有一个单通道图像,它主要是 0(背景),以及一些前景像素的值,如 20、21、22。非零前景像素大多与具有相同值的其他前景像素聚集在一起。但是,图像中有一些噪点。为了消除噪音,我想使用连通分量分析,并且对于每个值(在本例中为 20、21、22),将除最大连通分量之外的所有内容归零。所以最后,我将有 3 个大的连接组件并且没有噪音。我将如何使用 cv2.connectedComponentsWithStats 来完成此操作?它似乎没有很好的记录,甚至在看过这篇文章之后,我不完全明白如何解析函数的返回值。有没有办法指定我只想要连接组件匹配特定灰度值的函数?
这是一般方法:
connectedComponentsWithStats()在面具上奔跑这里令人讨厌的是第 5 步,因为 0 的值通常但不总是最大的组件。所以我们需要按面积得到最大的非零分量。
这是一些我认为可以实现所有功能的代码(可以肯定一些示例图像会很好):
import cv2
import numpy as np
img = np.array([
[1, 0, 1, 1, 2],
[1, 0, 1, 1, 2],
[1, 0, 1, 1, 2],
[1, 0, 1, 1, 2],
[1, 0, 1, 1, 2]], dtype=np.uint8)
new_img = np.zeros_like(img) # step 1
for val in np.unique(img)[1:]: # step 2
mask = np.uint8(img == val) # step 3
labels, stats = cv2.connectedComponentsWithStats(mask, 4)[1:3] # step 4
largest_label = 1 + np.argmax(stats[1:, cv2.CC_STAT_AREA]) # step 5
new_img[labels == largest_label] = val # step 6
print(new_img)
Run Code Online (Sandbox Code Playgroud)
显示所需的输出:
[[0 0 1 1 2]
[0 0 1 1 2]
[0 0 1 1 2]
[0 0 1 1 2]
[0 0 1 1 2]]
Run Code Online (Sandbox Code Playgroud)
要完成代码,首先我们创建新的标记图像,毫无想象力地称为new_img,填充零,稍后由正确的标签填充。然后,np.unique()找到图像中的唯一值,除第一个值外,我将获取所有值;请注意,它np.unique()返回一个已排序的数组,因此 0 将是第一个值,我们不需要找到零的组件。对于每个唯一的 val,创建一个填充有 0 和 1 的掩码,并在此掩码上运行连接的组件。这将用不同的标签标记每个不同的区域。然后我们可以获取最大的非零标记组件**,为其创建一个掩码,然后将该 val 添加到该位置的新图像中。
** 这是代码中看起来很奇怪的令人讨厌的部分。
largest_label = 1 + np.argmax(stats[1:, cv2.CC_STAT_AREA])
Run Code Online (Sandbox Code Playgroud)
首先,您可以查看为stats数组形状链接的答案,但每行对应一个标签(因此标签 0 将对应第一行等),并且该列由整数 cv2.CC_STAT_AREA 定义(这只是 4)。我们需要确保我们正在查看最大的非零标签,所以我只查看第一个之后的行。然后,抓取最大区域对应的索引。由于我们去掉了零行,索引现在对应于label-1,因此加 1 以获得正确的标签。然后我们可以像往常一样屏蔽并插入值。