您的位置:首页 > 运维架构 > Linux

在Linux上实现摄像头中的霍夫圆检测

2015-07-19 15:17 567 查看



一 霍夫变换的原理

Hough变换的基本思想是利用点-线的对偶性。

一条直线可以用两个元素来确定:在笛卡尔坐标系中用斜率和截距(k,b);在极坐标中用用极径和极角(r,θ)。由于在x-y坐标系中垂直直线的k值为无穷大,这将给计算带来麻烦,所以我们采用极坐标系来表示直线。即:

r=xcosθ+ysinθ

显然对于固定的(x0,y0),(r,θ)将表示一条正弦曲线。也就是说x-y平面的一个点将对应r-θ平面的一条直线。将通过点(x0,y0)的一条直线上的另一些点再描绘到r-θ平面,会发现这些点对应的直线在r-θ平面交于一点,这一点即x-y平面的那些点所在的直线。

这意味着一般来说, 一条直线能够通过在平面

-

寻找交于一点的曲线数量来检测.
越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成. 一般来说我们可以通过设置直线上点的 阈值
来定义多少条曲线交于一点我们才认为 检测 到了一条直线.

这就是霍夫线变换要做的. 它追踪图像中每个点对应曲线间的交点. 如果交于一点的曲线的数量超过了阈值, 那么可以认为这个交点所代表的参数对


在原图像中为一条直线.

霍夫圆变换的原理类似于霍夫线变换。广义的霍夫圆变换中,圆的方程可写为:(x-a)^2+(y-b)^2=r^2

相对于图像空间,参数空间中以(x,y)为圆心,r为半径的圆的方程可写为:(a-x)^2+(b-y)^2=r^2

式中有三个参数a,b,r,所以需要在参数空间建立一个三维的累加数组。可见,这实际上是把输入图像圆边界上的点映射到三维的参数空间的锥面上。检测过程中,对参数空间的每一个(a,b,r)考虑图像中的每一个像素点(x,y)。

二 代码实现

#include "cv.h"
#include "highgui.h"
#include <stdio.h>

int main(int argc,char**argv){
IplImage *pImage=NULL;
IplImage *pImg8u=NULL;

//打开摄像头
CvCapture *capture=cvCaptureFromCAM(0);
if(!capture)
{
printf("could not");
return -1;
}
cvNamedWindow("demo",CV_WINDOW_AUTOSIZE);
IplImage *frame;
while(1){
frame=cvQueryFrame(capture);
if(!frame)
break;
char c=cvWaitKey(100);
if(c==27)
break;
// cvShowImage("demo",frame);

pImage=cvCloneImage(frame);
pImg8u=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
//转化为灰度图
if(frame->nChannels!=1)
cvCvtColor(pImage,pImg8u,CV_BGR2GRAY);
else
cvCopy(pImage,pImg8u,NULL);

cvSmooth(pImg8u,pImg8u,CV_GAUSSIAN,5,5,0,0); //平滑
CvMemStorage* storage=cvCreateMemStorage(0);//声明storage变量,用于存储检测到的线段
CvSeq* circles=cvHoughCircles(pImg8u,storage,CV_HOUGH_GRADIENT,2,pImg8u->height/4,250,55,0,0);
int i=0;
for( i;i<circles->total;i++){
float* p=(float *)cvGetSeqElem(circles,i);
CvPoint pt=cvPoint(cvRound(p[0]),cvRound(p[1]));
cvCircle(pImage,pt,cvRound(p[2]),CV_RGB(255,0,0),3,8,0);
}
cvShowImage("demo",pImage);
}
cvWaitKey(10);
cvReleaseCapture(&capture);
cvReleaseImage(&frame);
cvReleaseImage(&pImage);
cvReleaseImage(&pImg8u);
cvDestroyWindow("demo");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: