问题描述
在检测圈子之前,我将 red
频道替换为 green
频道。替换通道后,我将其通过模糊滤镜,然后进行霍夫变换以检测圆。但是当我这样做时,我收到一条糟糕的错误消息:
Before detecting circles, I am replacing the red
channel with the green
channel. After replacing the channel, I pass it through a blur filter and then do a Hough transform to detect circles. But as I do this, I get a crappy error message:
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
从任何意义上说,因此无法理解我可能做错了什么。这是我所做的摘要。
I could not make any sense from it and thus could not understand what I could be doing incorrectly. Here is the snippet to what I did.
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
函数。我可能做错了什么?
The error happens when I call HoughCircles
function. What is it that I might be doing incorrectly?
推荐答案
关于解释错误。它来自:
About interpreting the error. It comes from hough.cpp#L1659:
CV_Assert(!_image.empty() && _image.type() == CV_8UC1 && (_image.isMat() || _image.isUMat()));
简而言之,必须满足以下所有条件:
Breaking it down, all the following conditions have to be true:
-
!_ image.empty()
:输入图像不应为空; -
_image.type()== CV_8UC1
:输入图像必须为8U
(8位无符号,np.uint8
)和C1
(单通道); -
_image.isMat()|| _image.isUMat()
:检查输入的是Mat
还是UMat
(在Python中,它必须是一个numpy数组);
!_image.empty()
: the input image should not be empty;_image.type() == CV_8UC1
: the input image must be8U
(8-bit unsigned,np.uint8
) andC1
(single-channel);_image.isMat() || _image.isUMat()
: check if the input isMat
orUMat
(in Python, it has to be a numpy array);
关于您的特定错误消息(错误:(-215 )!_image.empty()& _amp; _image.type()==((((0)&((1<< 3)-1))+((((1)-1)<<<< ; 3))&&(_image.isMat()|| _image.isUMat())
):
Regarding your specific error message (error: (-215) !_image.empty() && _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || _image.isUMat())
):
- 错误代码(-215)来自:它是通用
CV_StsAssert
; - 然后是这些数字:代表
CV_8UC1
。您想知道为什么吗?您应该:)我们开始:
- The error code (-215) comes from here: it is the generic
CV_StsAssert
; - And then these numbers: they represent
CV_8UC1
. Are you curious to know why? You should :) Here we go:
-
CV_8UC1
-
CV_MAKETYPE(CV_8U,1)
::从 -
CV_MAKETYPE(0,1)
::从 -
(CV_MAT_DEPTH(0)+((((1)-1)<<< CV_CN_SHIFT)))
::来自 -
((((0)& CV_MAT_DEPTH_MASK)+((((1)-1)<<< CV_CN_SHIFT)))
::来自 -
((((0)&(CV_DEPTH_MAX-1))+((((1)- 1)<< CV_CN_SHIFT))
::来自 -
((((0)&((1<< CV_CN_SHIFT)-1))+((((1)-1)<< CV_CN_SHIFT))
::从 -
(( (0)&(((1<< 3)-1))+((((1)-1)<< 3))
::来自
CV_8UC1
CV_MAKETYPE(CV_8U,1)
:: from#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
CV_MAKETYPE(0,1)
:: from#define CV_8U 0
(CV_MAT_DEPTH(0) + (((1)-1) << CV_CN_SHIFT))
:: from#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
(((0) & CV_MAT_DEPTH_MASK) + (((1)-1) << CV_CN_SHIFT))
:: from#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK)
(((0) & (CV_DEPTH_MAX - 1)) + (((1)-1) << CV_CN_SHIFT))
:: from#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1)
(((0) & ((1 << CV_CN_SHIFT) - 1)) + (((1)-1) << CV_CN_SHIFT))
:: from#define CV_DEPTH_MAX (1 << CV_CN_SHIFT)
(((0) & ((1 << 3) - 1)) + (((1)-1) << 3))
:: from#define CV_CN_SHIFT 3
我会尝试补充的答案,仅仅是因为我很好奇并且想分享一下:)
I'll try to complement @Mark Setchell's answer, simply because I was curious and I want to share :)
如果您查看文档,请是模块(在 子模块)。该文档说,唯一实现的方法是,即两阶段霍夫变换),并指出参考文件 (1990年):)。如果由于付费墙而无法访问,则可以访问)。在本文中,作者评论:
If you look at the documentation, cv2.HoughCircle()
is part of the imgproc module (under the Feature Detection "submodule"). The documentation says that the only implemented method is the HOUGH_GRADIENT (aka 21HT, i.e., Two stage Hough Transform), and they point out to the reference paper "Comparative study of Hough Transform methods for circle finding" (1990) :). If you cannot access because of the paywall, you can access the 1989's version for free). In the paper, the authors comment:
后来,他们写道:
因此,如果要坚持使用21HT,则基本上需要边缘和边缘方向信息。例如,您可以通过 Sobel
获取边缘方向信息(例如, dx
和 dy
),然后使用这些已经计算出的 dx
和 dy
来使用 Canny
。实际上,这就是OpenCV实现的功能。如果导航到,您可以看到Sobel + Sobel + Canny操作。
Therefore, if you want to stick to the 21HT, you basically need both edges and edge direction information. For instance, you could get the edge direction information via Sobel
(e.g., dx
and dy
), and use these already computed dx
and dy
to get the edges using Canny
. In fact, this is what the OpenCV implementation does. If you navigate to modules/imgproc/src/hough.cpp
, you can see the Sobel+Sobel+Canny operations here.
那又怎样?好吧,这意味着如果您有另一种方法(或者想提出一种新方法,为什么不呢?),该方法能够返回更适合您的情况的边缘和边缘方向信息(也许是 colors 在您的情况下具有不同的含义),那么您只需用您的方法替换这三行(Sobel + Sobel + Canny),然后重复使用其余的实现(很酷,是吧?)。如果您有受到启发的感觉:),可以看看 ,然后从那里开始。
So, what? Well, it means that if you have another method (or you want to propose a new one, why not?) that is able to return edges and edge direction information that are better suited for your case (maybe the colors have a different meaning in your case), then you can just replace these 3 lines (Sobel+Sobel+Canny) with your method and re-use the rest of the implementation (cool, huh?). If you are feeling inspired :), you can take a look at "A Short History of Color Edge Detection" and start from there.
然后,为什么我们需要单通道输入?好吧,基本上是因为我们需要边缘,所以通常将它们表示为单通道图像。此外,到目前为止仅支持单通道边缘和边缘方向信息。但是,大多数这些概念可以扩展到多通道输入。我认为,因为没有通用的解决方案(这些概念可能会因情况而异),并且很少有人会从中受益,所以到目前为止,没有人愿意提供任何实现。
Then, why do we need single-channel inputs? Well, basically because we need edges, and they are usually represented as single-channel images. In addition, the implementation only supports single-channel edges and edge direction information so far. However, most of these concepts could be extended to multi-channel inputs. I think that, because there are no generic solutions (probably these concepts change in a case-by-case basis) and very few people would benefit from, no one bothered to provide any implementation so far.
很抱歉,答案很长。我知道TL; DR该方法需要单通道输入就足够了。我很好奇,想分享=]
Sorry for the long answer. I know the TL;DR "the method requires single-channel input" is enough. I got curious and wanted to share =]
这篇关于在3通道输入中使用HoughCircles时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!