【问题标题】:Error using HoughCircles with 3-channel input使用带有 3 通道输入的 HoughCircles 时出错
【发布时间】:2019-06-20 04:24:48
【问题描述】:

在检测圆圈之前,我将red 频道替换为green 频道。更换通道后,我将其通过模糊过滤器,然后进行霍夫变换以检测圆圈。但是当我这样做时,我收到一条糟糕的错误消息:

OpenCV(3.4.1) Error: Assertion failed (!_image.empty() && _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || 

_image.isUMat())) in HoughCircles, file /io/opencv/modules/imgproc/src/hough.cpp, line 1659
Traceback (most recent call last):

  File "circle_light.py", line 44, in <module>
    param1=param1,param2=param2,minRadius=minRadius,maxRadius=maxRadius)

cv2.error: OpenCV(3.4.1) /io/opencv/modules/imgproc/src/hough.cpp:1659: error: (-215) !_image.empty() 

&& _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || _image.isUMat()) in function HoughCircles

我无法从中理解,因此无法理解我可能做错了什么。这是我所做的 sn-p。

import cv2

img = cv2.imread("images/{}".format("img.png"), 1)

b,g,r = cv2.split(img)
img = cv2.merge([b,g,g])
img = cv2.GaussianBlur(img,(5,5),0)

minDist = 11
param1 = 20
param2 = 20
minRadius = 10
maxRadius = 20

circles = cv2.HoughCircles(
    img, cv2.HOUGH_GRADIENT, 1, minDist,
    param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius
)

当我调用HoughCircles 函数时发生错误。我可能做错了什么?

【问题讨论】:

  • 如果您有兴趣,我会在我的回答中解释错误消息,并提供更多关于为什么cv2.HoughCircles() 使用单通道输入的信息。答案很长,但这是你的错:你的问题让我很好奇:)

标签: python opencv image-processing computer-vision hough-transform


【解决方案1】:

您只能在单通道(灰度)图像上调用cv2.HoughCircles(),您的图像有 3 个通道。

Documentation.

【讨论】:

  • 这背后的原因是什么?
  • 我猜人们通常会先找到边缘,这会产生灰度图像,然后再寻找构成圆圈的边缘。
  • @MarkSetchell 需要注意的是,cv2.HoughCircle() 将在内部应用 Sobel 和 Canny 来获取 21HT 算法所需的边缘和边缘信息。我在答案的第二部分提供了一些细节(以补充您的答案)。希望你不要介意。
  • @Berriel 我总是很高兴能学到新东西 - 所以谢谢。
【解决方案2】:

关于解释错误。来自hough.cpp#L1659

CV_Assert(!_image.empty() && _image.type() == CV_8UC1 && (_image.isMat() || _image.isUMat()));

分解,以下所有条件都必须为真:

  • !_image.empty():输入图片不能为空;
  • _image.type() == CV_8UC1:输入图像必须为8U(8位无符号,np.uint8)和C1(单通道);
  • _image.isMat() || _image.isUMat():检查输入是Mat还是UMat(在Python中,它必须是一个numpy数组);

关于您的具体错误消息 (error: (-215) !_image.empty() &amp;&amp; _image.type() == (((0) &amp; ((1 &lt;&lt; 3) - 1)) + (((1)-1) &lt;&lt; 3)) &amp;&amp; (_image.isMat() || _image.isUMat())):


我会尝试补充@Mark Setchell的答案,只是因为我很好奇,我想分享:)

如果您查看文档,cv2.HoughCircle()imgproc 模块的一部分(在Feature Detection子模块”下)。文档说唯一实现的方法是HOUGH_GRADIENT(又名21HT,即两阶段霍夫变换),他们指出参考论文“Comparative study of Hough Transform methods for circle finding”(1990):)。如果因为付费墙而无法访问,您可以访问1989's version for free)。在论文中,作者评论:

形状分析的 HT 方法使用一个约束方程,将特征空间中的点与所搜索形状的可能参数值相关联。对于每个 特征点,总是边缘点,对所有满足约束的参数组合累积投票。 [...]

后来,他们写道:

如果边缘方向信息可用,那么减少圆查找的存储和计算需求的一种方法是将问题分解为两个 阶段 [...]

因此,如果你想坚持21HT,你基本上需要边缘和边缘方向信息。例如,您可以通过Sobel(例如dxdy)获取边缘方向信息,并使用这些已经计算的dxdy 来使用Canny 获取边缘。事实上,这就是 OpenCV 实现的作用。如果导航到modules/imgproc/src/hough.cpp,可以看到Sobel+Sobel+Canny 操作here

那么,什么?好吧,这意味着如果您有另一种方法(或者您想提出一个新方法,为什么不呢?)能够返回更适合您的情况的边缘和边缘方向信息(可能是 colors em> 在你的情况下有不同的含义),那么你可以用你的方法替换这 3 行(Sobel+Sobel+Canny)并重新使用其余的实现(很酷,是吗?)。如果您受到启发 :),您可以查看“A Short History of Color Edge Detection”并从那里开始。

那么,为什么我们需要单通道输入?嗯,基本上是因为我们需要边缘,它们通常表示为单通道图像。另外implementation目前只支持单通道边缘和边缘方向信息。但是,这些概念中的大多数都可以扩展到多通道输入。我认为,因为没有通用的解决方案(这些概念可能会根据具体情况而变化)并且很少有人会从中受益,所以到目前为止没有人费心提供任何实现。

抱歉,答案很长。我知道 TL;DR “该方法需要单通道输入”就足够了。我很好奇并想分享=]

【讨论】:

    猜你喜欢
    • 2011-07-28
    • 2019-03-26
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2023-01-14
    • 2021-02-26
    相关资源
    最近更新 更多