OpenCV学习之Hough变换检测圆

来源:互联网 发布:笑郭网络验证4.0破解 编辑:程序博客网 时间:2024/05/21 09:13

Hough变换检测圆

我们在之前利用Hough变换实现了直线的检测,因为两个特征(k,b)或者(theta,r)就能确定一条直线,所以我们的Hough空间是二维的。一个圆由3个特征组成,分别是圆心的横坐标,纵坐标,以及圆的半径,因此我们的Hough空间是三维的。

圆的方程:(x-a)^2 + (y-b)^2 = r^2

过一点(x0,y0),a,b,r的关系就是:(x0-a)^2 + (y0-b)^2 = r^2

因此,我们的Hough空间[a是横坐标,b是纵坐标,r是竖坐标]
我们要用一个二重循环去填充Hough空间
跟直线检测一样,我们现在是在三维数组里找局部最大值,确定圆的(x,y,r)
听完之后是不是觉得方法很简单,跟检测直线没什么区别,也用不到极坐标。

但是,三维累加器中会产生许多噪声并且使得结果不稳定的稀疏分布!
因此,由Hough梯度法来改进这个算法。

Hough梯度法

  • 利用canny检测提取边缘
  • 对每一个边缘点,我们可以计算出梯度[其实就是圆心和边缘点连线方向]
  • 计算出梯度后,我们就可以得到一条垂直于该点切线的直线,我们就有一个二维数组H,用来填充这条直线上所有点
  • H中出现频率最高的肯定就是圆心
  • 对于得到的圆心中的每一个,计算那些边缘点到该圆心的距离,若某个距离很充分出现次数足够,就可以认为这是一个合格的圆
//Hough变换检测圆#include "cv.h"#include "highgui.h"#include "math.h"int main(int argc, char** argv) {    IplImage* img = cvLoadImage("corner.tif", 1);    IplImage* gray = cvCreateImage(cvGetSize(img), 8, 1);    CvMemStorage* storage = cvCreateMemStorage(0);    cvCvtColor(img, gray, CV_BGR2GRAY);    cvSmooth(gray, gray, CV_GAUSSIAN, 9, 9);    //cvHoughCircles(image,storage,method,dp,min_dist,p1 = 100,p2 = 100,min_radius = 0,max_radius = 0);    //CV_HOUGH_GRADIENT H.K于2003年发表的21HT方法    //dp检测圆心累加器的分辨率,1不变,2累加器尺寸为原图一半    //min_dist 检测到的圆心之间的最小距离。取值太小,在一个圆被分解为多个圆。太大则漏检    //p1在CV_HOUGH_GRADIENT情况下,此参数为传递给Canny边缘检测算子的两个阈值较高的那个,低阈值为其一半    //p2取值越小则误检很多不存在的圆    //mix_radius 被搜索圆得最小半径,小于此半径被忽略    //max_radius 最大半径,默认为max(width,height);    CvSeq* circles = cvHoughCircles(gray, storage, CV_HOUGH_GRADIENT, 2, gray->height / 4, 10, 100);    int i;    for (i = 0; i < circles->total; i++) {        float* p = (float*)cvGetSeqElem(circles, i);        cvCircle(img, cvPoint(cvRound(p[0]), cvRound(p[1])), 3, CV_RGB(0, 255, 0), -1, 8, 0);        cvCircle(img, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255, 0, 0), 3, 8, 0);    }    cvNamedWindow("circles", 1);    cvShowImage("circles", img);    cvWaitKey(0);    return 0;}
原创粉丝点击