【问题标题】:OpenCV findContours() complains if used with black-white image如果与黑白图像一起使用,OpenCV findContours() 会抱怨
【发布时间】:2015-06-10 13:07:02
【问题描述】:

我想使用以下代码执行边缘检测。但是,由于图像颜色深度,我得到一个错误。我眼中的这个错误毫无意义,因为我将图像正确转换为灰度图像,并在后续步骤中转换为黑白图像,这绝对可以正常工作。当我打电话给findContours 时,我得到一个错误。

import cv2

def bw_scale(file_name, tresh_min, tresh_max):
    image = cv2.imread(file_name)
    image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    #(thresh, im_bw) = cv2.threshold(image, tresh_min, tresh_max, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    (thresh, im_bw) = cv2.threshold(image, tresh_min, tresh_max, 0)

    cv2.imwrite('bw_'+file_name, im_bw)
    return (thresh, im_bw)

def edge_detect(file_name, tresh_min, tresh_max):
    (thresh, im_bw) = bw_scale(file_name, tresh_min, tresh_max)
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


if __name__ == '__main__':
  edge_detect('test.jpg', 128, 255)

我收到此错误:

dgrat@linux-v3pk:~> python aoi.py
OpenCV Error: Unsupported format or combination of formats ([Start]FindContours support only 8uC1 and 32sC1 images) in cvStartFindContours, file /home/abuild/rpmbuild/BUILD/opencv-2.4.9/modules/imgproc/src/contours.cpp, line 196
Traceback (most recent call last):
  File "aoi.py", line 25, in <module>
    edge_detect('test.jpg', 128, 255)
  File "aoi.py", line 19, in edge_detect
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.error: /home/abuild/rpmbuild/BUILD/opencv-2.4.9/modules/imgproc/src/contours.cpp:196: error: (-210) [Start]FindContours support only 8uC1 and 32sC1 images in function cvStartFindContours

【问题讨论】:

    标签: python opencv


    【解决方案1】:

    您的代码中的问题是您误用了cv2.threshold() 的返回值。

    cv2.threshold返回2个参数:

    • retval

      在使用 OTSU 方法进行阈值处理时使用(返回最佳阈值),否则它会返回您传递给函数的相同阈值,在您的情况下为 128.0。

    • dst

      是阈值化的结果图像

    在您的代码中,thresh 是浮点数而不是 Mat。

    变化:

    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    编辑

    在下面使用以下测试图像查找原始代码的重构和简化版本。

    import cv2
    
    def edge_detect(file_name, tresh_min, tresh_max):
        image = cv2.imread(file_name)
        im_bw = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    
        (thresh, im_bw) = cv2.threshold(im_bw, tresh_min, tresh_max, 0)
        cv2.imwrite('bw_'+file_name, im_bw)
    
        contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        cv2.drawContours(image, contours, -1, (0,255,0), 3)
        cv2.imwrite('cnt_'+file_name, image)
    
    if __name__ == '__main__':
      edge_detect('test.jpg', 128, 255)
    

    这会产生以下 bw_test.jpg

    在 cnt_test.jpg 中突出显示以下轮廓

    【讨论】:

    • 仍然出现同样的错误。我想知道是python问题还是我。
    • 我只是使用我帖子中提到的更改运行您的代码,它可以正常工作。轮廓被正确检测。
    • 无论我做什么,我总是得到这个错误。我将在另一台电脑上测试它:(
    【解决方案2】:

    更新

    考虑到您已经将图像转换为灰度,问题应该出在通道范围上。 FindContours 仅支持 32s8u。你可以使用image.dtype 来确保你得到类似uint8 的东西。如果不是cv2.convertScaleAbs(image)should解决你的问题。

    原始答案

    正如错误中提到的FindContours support only 8uC1 and 32sC1 images。所以可能想使用cv.CvtColor 之类的东西将您的图像转换为支持的色彩空间。

    【讨论】:

    • >> image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) 这不是正确的函数吗?
    • 两个概念很重要:通道数和像素表示。您可能有灰度图片,但在8U32S 中没有。
    • 还是同样的错误:image = cv2.cvtColor(image, cv2.CV_8UC1) \n image = cv2.convertScaleAbs(image)
    • @dgrat;您是否需要在convertScaleAbs 之前调用cvtColor,因为根据定义convertScaleAbs 将“缩放,采用abs 值并转换为无符号8 位类型”?因此covnertScaleAbs 的最终结果是8uC#convertScaleAbs 将分别为每个频道执行此操作,这意味着您无需更改频道数。如果你真的有一个黑白图像,你应该只有 1 个通道,如果你有即具有透明度的黑白图像,你将有额外的“alpha”通道。如果您的错误仍然存​​在,这意味着您可能没有将其正确转换为黑白?
    【解决方案3】:

    我在尝试使用灰度图像时遇到了同样的错误,然后我尝试将具有 Canny 边缘检测器的平均 5X5 块的高斯滤波器应用于 cvtColor 转换的灰度图像。瞧!图片上的轮廓。

    试试这个代码

    image = cv2.imread('testimage.jpeg')
    im_bw = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    
    blur = cv2.GaussianBlur(im_bw, (5,5), 0)
    im_bw = cv2.Canny(blur, 10, 90)
    
    contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(image, contours, -1, (0,255,0), 3)
    plt.imshow(image)
    plt.show()
    

    【讨论】:

      【解决方案4】:

      如今,findContours 仅返回轮廓和层次结构。

      在将图像作为参数传递给函数之前,它必须是 uint8 并且必须是灰度的。当我使用RETR_CCOM 作为模式时,这些都有效。

      【讨论】:

        猜你喜欢
        • 2013-06-23
        • 1970-01-01
        • 2022-12-15
        • 2019-04-11
        • 2017-12-11
        • 1970-01-01
        • 2011-11-29
        • 1970-01-01
        • 2023-03-17
        相关资源
        最近更新 更多