如果使用黑白图像,OpenCV findContours()会抱怨

dgr*_*rat 4 python opencv

我想用以下代码执行边缘检测.但是由于图像颜色深度,我得到一个错误.这个错误在我的眼中没有任何意义,因为我将图像正确地转换为灰度图像,并在随后的步骤中转换为黑白图像,这肯定是正确的.当我调用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)
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

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
Run Code Online (Sandbox Code Playgroud)

Tom*_*min 8

您的代码中的问题是您滥用了返回值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)
Run Code Online (Sandbox Code Playgroud)

这会产生以下bw_test.jpg

在此输入图像描述

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

在此输入图像描述


Yan*_*oto 5

更新

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

原始答案

如错误所述FindContours support only 8uC1 and 32sC1 images。因此,可能想使用类似cv.CvtColor将图像转换为支持的色彩空间的方法。

  • 仍然存在以下错误:image = cv2.cvtColor(image,cv2.CV_8UC1)\ n image = cv2.convertScaleAbs(image) (2认同)