opencv使用霍夫圆算法HoughCircles进行圆检测

 原理介绍:

 

opencv —— HoughCircles 霍夫圆变换原理及圆检测

霍夫变换(Hough Transform)

霍夫变换 - 圆检测 (Hough Circle transform)

霍夫圆算法是一种用于检测图像中圆形区域的算法。OpenCV 霍夫圆变换对标准霍夫圆变换做了运算上的优化。它采用的是 “霍夫梯度法”。

霍夫梯度法的原理

第一步:估计圆心

  1. 把原图做一次 Canny 边缘检测,得到边缘检测的二值图。
  2. 对原始图像执行一次 Sobel 算子,计算出所有像素的邻域梯度值。
  3. 初始化圆心空间 N(a,b),令所有的 N(a,b)=0。
  4. 遍历 Canny 边缘二值图中的所有非零像素点,沿着梯度方向 ( 切线的垂直方向 )画线,将线段经过的所有累加器中的点 (a,b) 的 N(a,b)+=1。统计排序 N(a,b),得到可能的圆心(N(a,b) 越大,越有可能是圆心)。   

第二步:估计半径(针对某一个圆心 (a,b))

  1. 计算 Canny 图中所有非 0 点距离圆心的距离。
  2. 距离从小到大排序,根据阈值,选取合适的可能半径(比如 3 和 3.5 都被划为半径值 3 中)。
  3. 初始化半径空间 r, N(r)=0。
  4. 遍历 Canny 图中的非 0 点,N( 距离 )+=1。
  5. 统计得到可能的半径值(N(r) 越大,说明这个距离值出现次数越多,越有可能是半径值)。

霍夫梯度法缺点

  1. 在霍夫梯度法中,我们使用 Sobel 导数来计算局部梯度,那么随之而来的假设是,其可以视作等同于一条局部切线,并这个不是一个数值稳定的做法。在大多数情况下,这样做会得到正确的结果,但或许会在输出中产生一些噪声。
  2. 在边缘图像中的整个非0像素集被看做每个中心的候选部分。因此,如果把累加器的阈值设置偏低,算法将要消耗比较长的时间。
  3. 因为每一个中心只选择一个圆,如果有同心圆,就只能选择其中的一个。
  4. 因为中心是按照其关联的累加器值的升序排列的,并且如果新的中心过于接近之前已经接受的中心的话,就不会被保留下来。且当有许多同心圆或者是近似的同心圆时,霍夫梯度法的倾向是保留最大的一个圆。可以说这是一种比较极端的做法,因为在这里默认Sobel导数会产生噪声,若是对于无穷分辨率的平滑图像而言的话,这才是必须的。

霍夫圆变换:HoughCircles 函数

HoughCircles 函数可以利用霍夫变换算法检测出灰度图中的圆。

函数原型:

CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles,

                               int method, double dp, double minDist,

                               double param1 = 100, double param2 = 100,

                               int minRadius = 0, int maxRadius = 0 );

 @brief Finds circles in a grayscale image using the Hough transform.使用霍夫变换在灰度图中检测圆

The function finds circles in a grayscale image using a modification of the Hough transform.

@note Usually the function detects the centers of circles well. However, it may fail to find correct radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if you know it. Or, in the case of #HOUGH_GRADIENT method you may set maxRadius to a negative number to return centers only without radius search, and find the correct radius using an additional procedure.

此函数可以很容易地检测出圆心,但是可能找不到合适地圆半径。我们可以通过 minRadius 和 maxRadius 两个参数指定最大和最小圆半径,来辅助圆检测的结果。或者可以直接忽略返回半径,让二者均为默认值,只用 HoughCircles 函数检测出圆心,用额外步骤进一步确定半径。

It also helps to smooth image a bit unless it's already soft. For example,GaussianBlur() with 7x7 kernel and 1.5x1.5 sigma or similar blurring may help.

除非图像已经很柔和,否则还可以使图像稍微平滑一些 例如,具有7x7内核和1.5x1.5 sigma或类似模糊效果的GaussianBlur()可能会有所帮助

@param image 8-bit, single-channel, grayscale input image.

@param circles Output vector of found circles. Each vector is encoded as  3 or 4 element

floating-point vector \f$(x, y, radius)\f$ or \f$(x, y, radius, votes)\f$.

@param method Detection method, see #HoughModes. The available methods are #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT.

@param dp Inverse ratio of the accumulator resolution to the image resolution. For example, if dp=1 , the accumulator has the same resolution as the input image. If dp=2 , the accumulator has half as big width and height. For #HOUGH_GRADIENT_ALT the recommended value is dp=1.5, unless some small very circles need to be detected.

累加器分辨率与图像分辨率的反比 例如,如果 dp = 1,累加器具有与输入图像相同的分辨率 如果dp = 2,则累加器具有 宽度和高度的一半 对于#HOUGH GRADIENT ALT,建议值为dp = 1.5, 除非需要检测到一些很小的圆圈

@param minDist Minimum distance between the centers of the detected circles. If the parameter is too small, multiple neighbor circles may be falsely detected in addition to a true one. If it is too large, some circles may be missed.

被检测圆的中心之间的最小距离。如果参数太小,可能会错误地检测到多个邻居圆,而不是一个真邻居圆。如果太大,可能会漏掉一些圆圈。

@param param1 First method-specific parameter. In case of #HOUGH_GRADIENT and #HOUGH_GRADIENT_ALT, it is the higher threshold of the two passed to the Canny edge detector (the lower one is twice smaller).

Note that #HOUGH_GRADIENT_ALT uses #Scharr algorithm to compute image derivatives, so the threshold value shough normally be higher, such as 300 or normally exposed and contrasty images.

第一个method-specific参数。在#HOUGH GRADIENT和#HOUGH ALT的情况下,它是传递给Canny边缘检测器的两个较高的阈值(较低的那个小1 / 2)。注意,#HOUGH梯度ALT使用#Scharr算法来计算图像导数,所以阈值通常会更高,例如300或正常曝光和对比度图像。

@param param2 Second method-specific parameter. In case of #HOUGH_GRADIENT, it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first. In the case of #HOUGH_GRADIENT_ALT algorithm, this is the circle "perfectness" measure. The closer it to 1, the better shaped circles algorithm selects. In most cases 0.9 should be fine.

If you want get better detection of small circles, you may decrease it to 0.85, 0.8 or even less. But then also try to limit the search range [minRadius, maxRadius] to avoid many false circles.

第二种方法特定的参数; 如果是#HOUGH GRADIENT,则为 圆的累加器阈值在检测阶段居中 越小越多 可能会检测到错误的圆圈 与较大的累加器值相对应的圆将是 首先返回 在#HOUGH GRADIENT ALT算法的情况下,这是圈 perfectness 度量 它越接近1,则选择的形状更好的圆形算法 在大多数情况下,0.9应该可以 如果要更好地检测小圆圈,可以将其降低到0.85 0.8甚至更低 但是,然后还要尝试限制搜索范围[minRadius,maxRadius],以避免出现许多错误的圆圈

@param minRadius Minimum circle radius.

@param maxRadius Maximum circle radius. If <= 0, uses the maximum image dimension. If < 0, #HOUGH_GRADIENT returns centers without finding the radius. #HOUGH_GRADIENT_ALT always computes circle radiuses.

  • image,输入图像,即源图像,需要为 8 位的灰度单通道图像。
  • circles,调用 HoughCircles 函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了 3 个元素的浮点矢量(x,y,radius)表示。
  • method,使用的检测方法,目前 OpenCV 中就霍夫梯度法一种可以使用,标识符为 HOUGH_GRADIENT。
  • dp,累加面分辨率(大小) = 原始图像分辨率(大小) × 1/dp。默认 dp = 1 时,两者分辨率相同。
  • minDist,两个圆心之间的最小距离。若两圆心距离 < minDist,则认为是同一个圆。
  • param1,Canny 边缘检测的高阈值,低阈值被自动置为高阈值的一半,默认为 100。
  • param2,累加平面某点是否是圆心的判定阈值。它越大,能通过检测的圆就更接近完美的圆形,默认为 100。
  • minRadius,圆半径的最小值。默认为 0。
  • maxRadius,圆半径的最大值,默认为 0。
参数描述
InputArray image8位、单通道、灰度输入图像
HoughMethods method目前,唯一的实现方法是HoughCirclesMethod.Gradient
double dp累加器分辨率与图像分辨率的反比。dp=1
double minDist检测到的圆的中心之间的最小距离。可以分辨时两个圆还是同心圆
double param1 = 100第一个方法特定的参数。[默认值是100],边缘检测的低阈值
double param2 = 100第二个方法特定于参数。 [默认值是100],中心点累加器阈值,候选圆心
int minRadius = 0最小半径
int maxRadius = 0最大半径

#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int hough_value = 55;
Mat src, gray;
void hough_change(int, void*) {
	vector<Vec3f>circles;    //minDist 和 param2 数值的设定是关键
	HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 10, 110, hough_value, 0, 0);
	Mat show = src.clone();
	for (int i = 0; i < circles.size(); i++) {
		circle(show, Point(circles[i][0], circles[i][1]), circles[i][2], Scalar(0, 0, 255), 2);
	}
	imshow("show", show);
}
int main() {
	src = imread("circles.bmp");
	GaussianBlur(src, src, Size(3, 3), 0, 0);
	imshow("原图", src);
	cvtColor(src, gray, COLOR_BGR2GRAY);
	namedWindow("show");
	createTrackbar("hough_value", "show", &hough_value, 200, hough_change);
	hough_change(0, 0);

	waitKey(0);
}

 使用HoughCircles()函数进行圆检测,其中参数的选择很关键,尤其是minDist 和 param2 两个参数的数值选择,决定着圆检测效果的好坏。

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值