关于霍夫找圆算法cvHoughCircles

霍夫圆变换详解
本文详细介绍了使用OpenCV中的霍夫圆变换算法检测图像中的圆形。通过调整参数,如累积器分辨率、最小圆间距离及阈值等,实现了对特定大小范围内圆形的有效检测,并用红色标记出检测到的圆形。

 关于霍夫找圆算法cvHoughCircles

http://b217dgy.blog.51cto.com/5704306/1320360

霍夫圆变换的函数为:

HoughCircles

 

利用 Hough 变换在灰度图像中找圆

CvSeq* cvHoughCircles( CvArr* image, void* circle_storage, int method, double dp, double min_dist, double param1=100, double param2=100, int min_radius=0, int max_radius=0 );

image

输入 8-比特、单通道灰度图像.

circle_storage

检测到的圆存储仓. 可以是内存存储仓 (此种情况下,一个线段序列在存储仓中被创建,并且由函数返回)或者是包含圆参数的特殊类型的具有单行/单列的CV_32FC3型矩阵(CvMat*).矩阵头为函数所修改,使得它的 cols/rows 将包含一组检测到的圆。如果 circle_storage 是矩阵,而实际圆的数目超过矩阵尺寸,那么最大可能数目的圆被返回

. 每个圆由三个浮点数表示:圆心坐标(x,y)和半径.

method

Hough变换方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in[Yuen03].

dp

累加器图像的分辨率。这个参数允许创建一个比输入图像分辨率低的累加器。(这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨率受此影响会变小(此情况下为一半)。dp的值不能比1小。

Resolution of theaccumulator used to detect centers of the circles. For example, if it is 1, theaccumulator will have the same resolution as the input image, if it is 2 -accumulator will have twice smaller width and height, etc.

min_dist

该参数是让算法能明显区分的两个不同圆之间的最小距离。

Minimum distance betweencenters of the detected circles. If the parameter is too small, multipleneighbor circles may be falsely detected in addition to a true one. If it istoo large, some circles may be missed.

param1

用于Canny的边缘阀值上限,下限被置为上限的一半。

The firstmethod-specific parameter. In case of CV_HOUGH_GRADIENT it is the higherthreshold of the two passed to Canny edge detector (the lower one will be twicesmaller).

param2

累加器的阀值。

The secondmethod-specific parameter. In case of CV_HOUGH_GRADIENT it is accumulatorthreshold at the center detection stage. The smaller it is, the more falsecircles may be detected. Circles, corresponding to the larger accumulatorvalues, will be returned first.

min_radius

最小圆半径。

Minimal radius of thecircles to search for.

max_radius

最大圆半径。

Maximal radius of thecircles to search for. By default the maximal radius is set to max(image_width,image_height).

The function cvHoughCirclesfinds circles in grayscale image using some modification of Hough transform.

-------------------------------------------------------------------------------------------------

 

我的目标是在一直全是圆的图中找出所有圆,并用红色表圈出。

//霍夫变换寻找圆

 

img、img1、img2函数外定义。

 

voidCdialogCVDlg::OnBnClickedBtnhoughcircles()

{

// TODO: Add your control notificationhandler code here

// TODO: Add your control notificationhandler code here

cvNamedWindow("a",1);

cvNamedWindow("b",1);

cvNamedWindow("c",1);

img = cvLoadImage("D:\ii.jpg",1);//原图

 

img1 = cvCreateImage (cvGetSize(img),IPL_DEPTH_8U, 1);//处理的图像必须是八位单通道的

if (img->nChannels == 1)

{

img1 = cvCloneImage (img);

}

else

{

cvCvtColor (img, img1, CV_RGB2GRAY); //转为单通道

}

 

CvMemStorage*storage=cvCreateMemStorage(0);

CvSeq* circle = 0;

 

//cvSmooth( img1, img1, CV_GAUSSIAN, 5,5 ); //看了很多事例,要降噪处理,但测试的结果是

//找圆会有一定偏差,说明用这个要因图而异,噪声高的图才要用

circle = cvHoughCircles(//cvHoughCircles函数需要估计每一个像素梯度的方向,

//因此会在内部自动调用cvSobel,而二值边缘图像的处理是比较难的

img1,

storage,

CV_HOUGH_GRADIENT,

1, //累加器图像的分辨率,增大则分辨率变小

18, //很重要的一个参数,告诉两个圆之间的距离的最小距离,如果已知一副图像,可以先行计

//算出符合自己需要的两个圆之间的最小距离。

100, //canny算法的阈值上限,下限为一半(即100以上为边缘点,50以下抛弃,中间视是否相连而

//定)

25, //决定成圆的多寡 ,一个圆上的像素超过这个阈值,则成圆,否则丢弃

32,//最小圆半径,这个可以通过图片确定你需要的圆的区间范围

45 //最大圆半径

);

 

img2 = cvCreateImage (cvGetSize(img),IPL_DEPTH_8U, 3); //用一个三通道的图片来显示红色的

//圆圈

cvCvtColor (img1, img2, CV_GRAY2RGB); //转为3通道

 

for( int i = 0; i < circle->total;i++ )

{

float* p = ( float* )cvGetSeqElem(circle, i );

//霍夫圆变换

CvPoint pt = cvPoint( cvRound( p[0] ),cvRound( p[1] ) ); //圆心坐标(p(0),p(1))

cvCircle(

img2,

pt, //确定圆心

cvRound( p[2] ), //确定半径

CV_RGB( 255, 0, 0 ),

3

); //画圆函数

}

cvShowImage( "a", img );

cvShowImage("b",img1);

cvShowImage("c",img2);

}

 

//原图:

 

 

 

//效果图

 

 

结论:只要调好参数,霍夫圆算法可以找出你的设定目标圆。

本文出自 “入乎其内出乎其外” 博客,请务必保留此出处http://b217dgy.blog.51cto.com/5704306/1320360

 


import cv2 as cv import numpy as np def hough_circle(image): #因为霍夫检测对噪声很明显,所以需要先滤波一下。 dst =cv.pyrMeanShiftFiltering(image,10,100) cimage=cv.cvtColor(dst,cv.COLOR_BGR2GRAY) circles = cv.HoughCircles(cimage,cv.HOUGH_GRADIENT,1,40,param1=40,param2=29,minRadius=30,maxRadius=0) #把circles包含的心和半径的值变为整数 circles = np.uint16(np.around(circles)) for i in circles[0]: cv.circle(image,(i[0],i[1]),i[2],(0,255,0),3) cv.imshow("circle",image) src = cv.imread("E:/opencv/picture/coins.jpg") cv.imshow("inital_window",src) hough_circle(src) cv.waitKey(0) cv.destroyAllWindows() 霍夫变换的基本思路是认为图像上每一个非零像素点都有可能是一个潜在的上的一点, 跟霍夫线变换一样,也是通过投票,生成累积坐标平面,设置一个累积权重来定位。 在笛卡尔坐标系中的方程为: 其中(a,b)是心,r是半径,也可以表述为: 即 在笛卡尔的xy坐标系中经过某一点的所有映射到abr坐标系中就是一条三维的曲线: 经过xy坐标系中所有的非零像素点的所有就构成了abr坐标系中很多条三维的曲线。 在xy坐标系中同一个上的所有点的方程是一样的,它们映射到abr坐标系中的是同一个点,所以在abr坐标系中该点就应该有的总像素N0个曲线相交。 通过判断abr中每一点的相交(累积)数量,大于一定阈值的点就认为是。 以上是标准霍夫变换实现算法。 问题是它的累加到一个三维的空间,意味着比霍夫线变换需要更多的计算消耗。 Opencv霍夫变换对标准霍夫变换做了运算上的优化。 它采用的是“霍夫梯度法”。它的检测思路是去遍历累加所有非零点对应的心,对心进行考量。 如何定位心呢?心一定是在上的每个点的模向量上,即在垂直于该点并且经过该点的切线的垂直线上,这些上的模向量的交点就是心。 霍夫梯度法就是要去查这些心,根据该“心”上模向量相交数量的多少,根据阈值进行最终的判断。 bilibili: 注意: 1.OpenCV的霍夫变换函数原型为:HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles image参数表示8位单通道灰度输入图像矩阵。 method参数表示检测方法,目前唯一实现的方法是HOUGH_GRADIENT。 dp参数表示累加器与原始图像相比的分辨率的反比参数。例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。如果dp=2,累加器分辨率是元素图像的一半,宽度和高度也缩减为原来的一半。 minDist参数表示检测到的两个心之间的最小距离。如果参数太小,除了真实的一个圈之外,可能错误地检测到多个相邻的圈。如果太大,可能会遗漏一些圈。 circles参数表示检测到的的输出向量,向量内第一个元素是的横坐标,第二个是纵坐标,第三个是半径大小。 param1参数表示Canny边缘检测的高阈值,低阈值会被自动置为高阈值的一半。 param2参数表示心检测的累加阈值,参数值越小,可以检测越多的假圈,但返回的是与较大累加器值对应的圈。 minRadius参数表示检测到的的最小半径。 maxRadius参数表示检测到的的最大半径。 2.OpenCV画的circle函数原型:circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img img参数表示源图像。 center参数表示心坐标。 radius参数表示的半径。 color参数表示设定的颜色。 thickness参数:如果是正数,表示轮廓的粗细程度。如果是负数,表示要绘制实心。 lineType参数表示线条的类型。 shift参数表示心坐标和半径值中的小数位数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值