选择正确的结构元素

Choosing right structuring element

我正在创建一个程序来自动将太阳能电池与 pv 模块分离,我首先使用自适应阈值对图像进行阈值处理以获得以下图像

之后,我打算通过使用大小为 (10,10) 的椭圆结构元素的扩张来移除单元格边界内的黑色像素,并获得了以下图像

如您所见,仍然有一些黑色像素,现在如果我增加结构元素的大小,我就会失去单元格边界

我已经尝试了其他可用的结构元素,例如十字形和矩形,但没有任何成功,因此我需要定义一个自定义内核,但不知道如何定义一个。

import numpy as np
import cv2
img=cv2.imread('result2.jpg',0)
th1 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
cv2.THRESH_BINARY,25,-2)
kernel=cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(15,15))
closing = cv2.morphologyEx(th1, cv2.MORPH_CLOSE, kernel)
cv2.imwrite('closing.jpg',closing)
cv2.imwrite('threshold.jpg',th1)
cv2.waitKey(0)
cv2.destroyAllWindows()

Original image before thresholding

我的第一条建议是不要马上进入门槛。阈值是你最后想做的事情。阈值处理会丢弃有价值的信息。形态学操作也适用于 grey-value 图像!

选择正确的形态学运算符以仅保留您感兴趣的形状实际上是非常直观的。在这种情况下,您希望同时保留水平线和垂直线。让我们使用线结构元素。线条是深色的,所以我们使用关闭来删除看起来不像我们线条的东西。

以垂直线结束将删除所有水平线,以水平线结束将删除所有垂直线。那么如何将这两者结合起来呢?事实证明,两次关闭的下限(pixel-wise 最小值)也是一个关闭。因此,以垂直线和水平线结束的下限是同时以两条线结束,您将保留这两条线中任何一条适合的形状。

这是一个例子。我正在使用 PyDIP(我没有 OpenCV)。

import diplib as dip
img = dip.ImageRead('/Users/cris/Downloads/ZrF7k.tif')
img = img.TensorElement(1) # keep only green channel
img = img[0:-2,1:-1]       # let's remove the artifacts at the right and top edges
f1 = dip.Closing(img, dip.SE([50,1],'rectangular'))
f2 = dip.Closing(img, dip.SE([1,50],'rectangular'))
out = dip.Infimum(f1, f2)
out.Show('lin')

您可以尝试稍微调整一下,添加一些额外的处理,并在末尾添加自适应阈值以获得 PV 电池的边缘。但实际上有更好的方法找到这些。

我在这里利用了面板非常直的事实 w.r.t。图像,并且它覆盖了整个图像。我们可以简单地沿行和列进行平均投影:

x = dip.Mean(out, process=[1, 0]).Squeeze()
y = dip.Mean(out, process=[0, 1]).Squeeze()
import matplotlib.pyplot as pp
pp.subplot(2,1,1)
pp.plot(x)
pp.subplot(2,1,2)
pp.plot(y)
pp.show()

从这些投影中检测单元格的边缘应该是相当 straight-forward。