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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30757273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:54:24  来源:igfitidea点击:

OpenCV findContours() complains if used with black-white image

pythonopencv

提问by dgrat

I want to perform edge detection with the following code. However I get an error because of the image color depth. This error in my eyes, makes no sense, as I convert the image properly to a gray-scale image, and in a subsequent step to a black and white image, which is definitely working correctly. When I call findContoursI get an error.

我想使用以下代码执行边缘检测。但是,由于图像颜色深度,我收到错误消息。这个错误在我看来是没有意义的,因为我将图像正确转换为灰度图像,并在后续步骤中转换为黑白图像,这绝对可以正常工作。当我打电话时,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)

I get this error:

我收到此错误:

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

采纳答案by Tomas Camin

The problem in your code is that you're misusing the return values of cv2.threshold().

您代码中的问题是您滥用了cv2.threshold().

cv2.thresholdreturns 2 parameters:

cv2.threshold返回 2 个参数:

  • retval

    is used when thresholding using the OTSU method (returning the optimal threshold value) otherwise it returns the same threshold value you passed to the function, 128.0 in your case.

  • dst

    is the thresholded result image

  • 返回值

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

  • 天文台

    是阈值化的结果图像

In your code threshis a float not a Mat.

在您的代码中thresh是一个浮点数而不是一个垫子。

Change:

改变:

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

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

to

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

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

EDIT

编辑

Below find a refactored and simplified version of your original code using the following test image.

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

enter image description here

在此处输入图片说明

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)

This produces the following bw_test.jpg

这会产生以下 bw_test.jpg

enter image description here

在此处输入图片说明

With the following contours highlighted in cnt_test.jpg

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

enter image description here

在此处输入图片说明

回答by Yan Foto

UPDATE

更新

Considering that you already convert you image to gray scale, the problem should be with the channel range. FindContourssupport only 32sand 8u. You could use image.dtypeto make sure that you get something like uint8. If not cv2.convertScaleAbs(image)shouldsolve your problem.

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

ORIGINAL ANSWER

原答案

As the error mentions FindContours support only 8uC1 and 32sC1 images. So might want to use something like cv.CvtColorto convert your image to a supported color space.

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