首页 > 解决方案 > 创建适用于所有图像的阈值函数

问题描述

我正在寻找一个限定形状的外圆、形状的边缘和形状内的圆。

为此,我将此代码用于阈值:

def adjustImage(img):
    src_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # src_gray = cv.fastNlMeansDenoising(src_gray, None, 10, 7, 21)
    _, thresh = cv.threshold(src_gray, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
    thresh = cv.morphologyEx(thresh, cv.MORPH_CLOSE, np.ones((5, 5)))
    return thresh

但是,此代码并不总是根据图像起作用。如何编辑阈值函数adjustImage(img)使其适用于所有图像?

工作示例: 例 1 Ex2 Ex3

非工作示例: 防爆4 Ex5 防爆6

标签: pythonopencv

解决方案


免责声明:我在Matlab而非 Python 下对此进行了测试,但是,pseudo-code您可以使用一些方法将其移植到 Python。

我的建议:尝试使用adaptive thresholding而不是简单的阈值或 Otsu 的阈值。当然,有一些参数需要摆弄,但是,你可以获得很好的结果。

这是应用adaptive thresholding图像的直接结果:

其中Python,应该相当简单。像这样的东西:

grayImg = cv.imread( inputImage.png, 0 )
adaptiveBinary = cv2.adaptiveThreshold( grayImg, 255, cv.ADAPTIVE_THRESH_MEAN_C,\
                                        cv.THRESH_BINARY, blockSize, C )

根据需要微调blockSizeC参数。在 Matlab 中,实现的默认自适应方法是Mean.

二值图像非常嘈杂,但是,您可以使用区域过滤器过滤小斑点。过滤低于 a 的每个 blob threshold value(我使用了 的值50)。这是输出,显示了最大的 blob:

你会得到这样的东西:

在 Matlab 中,这个操作只是一行代码。在 Python 中,区域过滤器可以这样实现:

# Create a clone image to show the result
filteredImage = adaptiveBinary.copy()

# Find the bimary image contours: 
contours, hierarchy = cv2.findContours( adaptiveBinary, cv2.RETR_EXTERNAL, 
                                        cv2.CHAIN_APPROX_SIMPLE )

# Perform contour filtering:
for cnt in contours:
    # Filter if the contour area is small
    area = cv2.contourArea( cnt )
    if area < 50:
        continue
    # Draw the contour onto target image:
    cv2.drawContours( filteredImage [cnt], -1, (255, 255, 255), 2 )

    # Whatever additional processing you need to do

# Write output image:
cv2.imwrite( "filterResult.png", filteredImage )

同样,这是未经测试的 Python 代码,因此,您可能需要调整/修改一些东西,但这是一般的想法。


推荐阅读