【问题标题】:Filling contours in opencv在opencv中填充轮廓
【发布时间】:2014-11-26 13:20:18
【问题描述】:

我正在尝试使用 openCV 中的 Canny 过滤器识别轮廓并填充轮廓,以创建蒙版。我有这种起始图像:

我正在尝试识别图像中的所有特征,绘制轮廓并填充它们。我正在尝试在 openCV 中使用此代码来实现它:

img = cv2.imread(os.path.join(fName,f), 0)  
img = cv2.GaussianBlur(img,(5,5),0)
cv2.bilateralFilter(img, 9, 150,450)
edge = np.zeros((img.shape[0] + 2, img.shape[1] + 2), np.uint8)
edge = cv2.Canny(img, 500, 300, apertureSize=5)
cont, heir = cv2.findContours(edge.copy(), cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
contours = [cv2.approxPolyDP(cnt, 3, True) for cnt in cont]
cv2.morphologyEx(img, cv2.MORPH_CLOSE, np.ones((5,5), dtype='uint8'))
cv2.drawContours(img, contours, -1, 255, -1)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis

大多数情况下,我在猜测参数(反复试验;这很难!)。不幸的是,我得到的不是整齐的轮廓,而是用白色填充的,更像是这样的:

有什么想法吗?显然,我需要更好地关闭边缘,并调整我的一些 Canny 参数,但我真的可以使用一些指导。

谢谢!

编辑:阈值不能很好地创建我想要的那种蒙版,要么: 我认为我的“亮”点没有比背景足够亮,但我会喜欢在黑色背景上有白点。

代码:

    img = cv2.imread(os.path.join(fName,f), 0)
    cv2.bilateralFilter(img, 9, 90,16)
    #img = cv2.GaussianBlur(img,(5,5),0)
    #binImg = np.zeros((img.shape[0], img.shape[1]), np.uint8)   
    binImg = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,           cv2.THRESH_BINARY, 25, 2)
    #binImg = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    #newimg = np.multiply(img, np.divide(edge, 255.0))    
    plt.imshow(binImg, cmap = 'gray', interpolation = 'bicubic')
    plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
    #plt.show()  

【问题讨论】:

    标签: python opencv


    【解决方案1】:

    “识别轮廓”和“识别所有特征”是什么意思?如果您只需要不需要的明亮图像部分的蒙版,则查找轮廓,然后为您展示的这种图像填充它们,只需使用任何类型的阈值,您将获得所需的二进制蒙版。

    【讨论】:

    • 这里的“特征”是指图像中颜色较浅的点。 'Countours' 是指这些点上的边缘。由于某些自动阈值算法,过去使用 ImageJ 进行二进制过滤并不可靠,但它是一种有效的替代方法。我想比较这两种方法。
    【解决方案2】:

    就其价值而言,二进制掩码是更好的选择。谢谢你的建议。这只是意味着玩一些参数。对于这些功能,我发现如下代码:

    img = cv2.imread(os.path.join(fName,f), 0)
    cv2.bilateralFilter(img, 9, 90,16)
    img = cv2.GaussianBlur(img,(5,5),0)
    #binImg = np.zeros((img.shape[0], img.shape[1]), np.uint8)   
    binImg = cv2.adaptiveThreshold(img, 1, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 55, -3)
    #cv2.bilateralFilter(binImg, 9, 90,16)
    #binImg = cv2.GaussianBlur(binImg, (3,3), 0)
    #ret, binImg = cv2.threshold(img, 35000, 1, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    plt.imshow(binImg, cmap = 'gray', interpolation = 'bicubic')
    plt.xticks([]), plt.yticks([])  # to hide tick values on X and Y axis
    

    生产出我正在寻找的那种面具:

    所以,我要结束这个问题了。

    【讨论】:

      【解决方案3】:

      如果您想让它或多或少独立于参数,我建议使用以下管道:-

      1. 进行超像素分割。我建议:https://github.com/PSMM/SLIC-Superpixels
      2. 对于每个超像素,计算平均亮度/强度。
      3. 阈值(自动或某种巧妙的方式)以获得明亮的超像素。
      4. 相应地创建蒙版

      【讨论】:

      • 我会调查的。谢谢!
      • 为了您的信息,现在在 opencv 的 ximgproc.segmentation 模块中提供了一个非常优化的 slic 版本。
      【解决方案4】:

      你可以试试 floodFill()。记得包含

      #include    <opencv2/imgproc.hpp>
      

      【讨论】:

        猜你喜欢
        • 2013-10-13
        • 2016-10-21
        • 1970-01-01
        • 2013-04-23
        • 2014-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多