将 HoughCircles 与 3 通道输入一起使用时出错
Error using HoughCircles with 3-channel input
在检测圆圈之前,我将 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
我无法从中得到任何意义,因此无法理解我可能做错了什么。这是我所做的片段。
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()
,您的图像有 3 个通道。
关于解释错误。它来自 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() && _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || _image.isUMat())
):
- 错误代码(-215)来自here:它是通用的
CV_StsAssert
;
- 然后是这些数字:它们代表
CV_8UC1
。你想知道为什么吗?你应该 :) 我们开始吧:
CV_8UC1
CV_MAKETYPE(CV_8U,1)
:: 来自#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
CV_MAKETYPE(0,1)
:: 来自#define CV_8U 0
(CV_MAT_DEPTH(0) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
(((0) & CV_MAT_DEPTH_MASK) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK)
(((0) & (CV_DEPTH_MAX - 1)) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1)
(((0) & ((1 << CV_CN_SHIFT) - 1)) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_DEPTH_MAX (1 << CV_CN_SHIFT)
(((0) & ((1 << 3) - 1)) + (((1)-1) << 3))
:: 来自#define CV_CN_SHIFT 3
我会尝试补充 @Mark Setchell 的答案,只是因为我很好奇并且想分享:)
如果您查看文档,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)。在论文中,作者评论:
The HT method of shape analysis uses a constraint equation relating points in a feature space to possible parameter values of the searched for shape. For each
feature point, invariably edge points, votes are accumulated for all parameter combinations which satisfy the constraint. [...]
后来,他们写道:
If edge direction information is available, then one way to reduce the storage and computational demands of circle finding is to decompose the problem into two
stages [...]
因此,如果你想坚持21HT,你基本上需要边缘和边缘方向信息。例如,您可以通过 Sobel
(例如 dx
和 dy
)获取边缘方向信息,并使用这些已经计算出的 dx
和 dy
来获得使用 Canny
的边缘。事实上,这就是 OpenCV 实现所做的。如果您导航到 modules/imgproc/src/hough.cpp
, you can see the Sobel+Sobel+Canny operations here.
那么,什么?嗯,这意味着如果你有另一种方法(或者你想提出一个新方法,为什么不呢?)能够 return 更适合你的情况的边缘和边缘方向信息(也许 colors 在你的情况下有不同的含义),那么你可以用你的方法替换这 3 行(Sobel+Sobel+Canny)并重新使用其余的实现(很酷,是吧? ).如果你有灵感:),你可以看看“A Short History of Color Edge Detection”然后从那里开始。
那么,为什么我们需要单通道输入?好吧,主要是因为我们需要边缘,它们通常表示为 单通道图像 。另外,implementation目前只支持单通道的边缘和边缘方向信息。然而,这些概念中的大多数都可以扩展到多通道输入。我认为,因为没有通用的解决方案(可能这些概念会根据具体情况而改变)并且很少有人会从中受益,所以到目前为止还没有人费心提供任何实施。
抱歉回答太长了。我知道 TL;DR "the method requires single-channel input" 就足够了。我很好奇,想分享 =]
在检测圆圈之前,我将 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
我无法从中得到任何意义,因此无法理解我可能做错了什么。这是我所做的片段。
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()
,您的图像有 3 个通道。
关于解释错误。它来自 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() && _image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) && (_image.isMat() || _image.isUMat())
):
- 错误代码(-215)来自here:它是通用的
CV_StsAssert
; - 然后是这些数字:它们代表
CV_8UC1
。你想知道为什么吗?你应该 :) 我们开始吧:CV_8UC1
CV_MAKETYPE(CV_8U,1)
:: 来自#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
CV_MAKETYPE(0,1)
:: 来自#define CV_8U 0
(CV_MAT_DEPTH(0) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
(((0) & CV_MAT_DEPTH_MASK) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK)
(((0) & (CV_DEPTH_MAX - 1)) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1)
(((0) & ((1 << CV_CN_SHIFT) - 1)) + (((1)-1) << CV_CN_SHIFT))
:: 来自#define CV_DEPTH_MAX (1 << CV_CN_SHIFT)
(((0) & ((1 << 3) - 1)) + (((1)-1) << 3))
:: 来自#define CV_CN_SHIFT 3
我会尝试补充 @Mark Setchell 的答案,只是因为我很好奇并且想分享:)
如果您查看文档,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)。在论文中,作者评论:
The HT method of shape analysis uses a constraint equation relating points in a feature space to possible parameter values of the searched for shape. For each feature point, invariably edge points, votes are accumulated for all parameter combinations which satisfy the constraint. [...]
后来,他们写道:
If edge direction information is available, then one way to reduce the storage and computational demands of circle finding is to decompose the problem into two stages [...]
因此,如果你想坚持21HT,你基本上需要边缘和边缘方向信息。例如,您可以通过 Sobel
(例如 dx
和 dy
)获取边缘方向信息,并使用这些已经计算出的 dx
和 dy
来获得使用 Canny
的边缘。事实上,这就是 OpenCV 实现所做的。如果您导航到 modules/imgproc/src/hough.cpp
, you can see the Sobel+Sobel+Canny operations here.
那么,什么?嗯,这意味着如果你有另一种方法(或者你想提出一个新方法,为什么不呢?)能够 return 更适合你的情况的边缘和边缘方向信息(也许 colors 在你的情况下有不同的含义),那么你可以用你的方法替换这 3 行(Sobel+Sobel+Canny)并重新使用其余的实现(很酷,是吧? ).如果你有灵感:),你可以看看“A Short History of Color Edge Detection”然后从那里开始。
那么,为什么我们需要单通道输入?好吧,主要是因为我们需要边缘,它们通常表示为 单通道图像 。另外,implementation目前只支持单通道的边缘和边缘方向信息。然而,这些概念中的大多数都可以扩展到多通道输入。我认为,因为没有通用的解决方案(可能这些概念会根据具体情况而改变)并且很少有人会从中受益,所以到目前为止还没有人费心提供任何实施。
抱歉回答太长了。我知道 TL;DR "the method requires single-channel input" 就足够了。我很好奇,想分享 =]