Tom*_*Tom 3 python opencv computer-vision
我正在寻找一种使用OpenCV从二进制图像中删除孤立的白色像素的方法。一个类似的问题(OpenCV摆脱了孤立的像素)也有很多“答案”,但似乎没有一个对我有用。我也尝试过打开和关闭的各种组合,但都没有成功。
这里的文章:
https://homepages.inf.ed.ac.uk/rbf/HIPR2/hitmiss.htm
建议我可以完全出于此目的使用“命中或失败”操作:
1用于定位二进制图像中的孤立点
这就是为什么0的解释与直接与侵蚀/膨胀配合使用时的解释不同(其中0解释为“不在乎”而不是“不是白色”,这基本上就是我所追求的)。但是,使用此内核仅渲染原始图像。
我的输入图像是这样的:
您会注意到,在图像的左侧附近有一些白色像素,我想将其消除。
这是代码:
kernel = np.array([ [0, 0, 0],
[0, 1, 0],
[0, 0, 0]],np.uint8)
hitormiss = cv2.morphologyEx(input_image, cv2.MORPH_HITMISS, kernel)
cv2.imshow('hitormiss', hitormiss)
Run Code Online (Sandbox Code Playgroud)
删除像这样的孤立像素的正确方法是什么?
更新:亚历山大的答案就像一个魅力,是最快的解决方案。另一个答案也提供了一个解决方案,即使用cv2.connectedComponents函数,但是它占用大量处理器资源。这是使用此方法的函数:
def remove_isolated_pixels(self, image):
connectivity = 8
output = cv2.connectedComponentsWithStats(image, connectivity, cv2.CV_32S)
num_stats = output[0]
labels = output[1]
stats = output[2]
new_image = image.copy()
for label in range(num_stats):
if stats[label,cv2.CC_STAT_AREA] == 1:
new_image[labels == label] = 0
return new_image
Run Code Online (Sandbox Code Playgroud)
我相信OpenCV的实现已被破坏。OpenCV的GitHub上存在一个相关问题,该问题似乎合并了一个pull请求进行修复;我认为它已作为pull请求中的参考添加到OpenCV 3.3-rc中,因此希望在下次更新OpenCV时可以解决。我不确定问题是否是由同一件事引起的。
所选答案中的创造性解决方案很棒,但我同意您的意见:尽管实施失败,但必须有更好的方法。
在OpenCV命中或失败教程中,他们指出:
因此,命中或失败操作包括三个步骤:
- 侵蚀图像阿与结构元素B1。
- 用结构元素B2 腐蚀图像A(A_c)的补数。
- AND是步骤1和步骤2的结果。
然后继续说,这可以通过“命中或失败”转换中的单个内核来完成,但是众所周知,它是坏的。因此,让我们执行这些步骤。
import cv2
import numpy as np
# load image, ensure binary, remove bar on the left
input_image = cv2.imread('calc.png', 0)
input_image = cv2.threshold(input_image, 254, 255, cv2.THRESH_BINARY)[1]
input_image_comp = cv2.bitwise_not(input_image) # could just use 255-img
kernel1 = np.array([[0, 0, 0],
[0, 1, 0],
[0, 0, 0]], np.uint8)
kernel2 = np.array([[1, 1, 1],
[1, 0, 1],
[1, 1, 1]], np.uint8)
hitormiss1 = cv2.morphologyEx(input_image, cv2.MORPH_ERODE, kernel1)
hitormiss2 = cv2.morphologyEx(input_image_comp, cv2.MORPH_ERODE, kernel2)
hitormiss = cv2.bitwise_and(hitormiss1, hitormiss2)
cv2.imshow('isolated.png', hitormiss)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)
然后去掉,它的那样简单颠倒hitormiss
,并将它作为一个mask
在cv2.bitwise_and()
用input_image
。
hitormiss_comp = cv2.bitwise_not(hitormiss) # could just use 255-img
del_isolated = cv2.bitwise_and(input_image, input_image, mask=hitormiss_comp)
cv2.imshow('removed.png', del_isolated)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)
注意:如评论中所述,kernel1
在这种特定情况下的腐蚀与输入二进制图像相同,因此无需进行此计算,并且在此特定情况下也引入了一些其他不必要的步骤。但是,您可能有不同的内核,而中间没有一个内核,因此我将按原样保留代码,以使其对所有内核通用。
归档时间: |
|
查看次数: |
6261 次 |
最近记录: |