hough变换原理求取峰值的阈值怎么设置

The page is temporarily unavailable
nginx error!
The page you are looking for is temporarily unavailable.
Please try again later.
Website Administrator
Something has triggered an error on your
This is the default error page for
nginx that is distributed with
It is located
/usr/share/nginx/html/50x.html
You should customize this error page for your own
site or edit the error_page directive in
the nginx configuration file
/etc/nginx/nginx.conf.&& Hough变换的基本原理在于,利用点与线的对偶性,将图像空间的线条变为参数空间的聚集点,从而检测给定图像是否存在给定性质的曲线。圆的方程为:(x-a)^2+(y-2)^2=r^2,通过Hough变换,将图像空间对应到参数空间。附录中的MATLAB程序为网上比较常见的,实际运行中存在一些问题,这里进行些修改。
&&& 原理:
&&& 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。最基本的霍夫变换是从黑白图像中检测直线(线段)。
&&& 我们先看这样一个问题:设已知一黑白图像上画了一条直线,要求出这条直线所在的位置。我们知道,直线的方程可以用y=k*x+b&来表示,其中k和b是参数,分别是斜率和截距。过某一点(x0,y0)的所有直线的参数都会满足方程y0=kx0+b。即点(x0,y0)确定了一族直线。方程y0=kx0+b在参数k--b平面上是一条直线,(你也可以是方程b=-x0*k+y0对应的直线)。这样,图像x--y平面上的一个前景像素点就对应到参数平面上的一条直线。我们举个例子说明解决前面那个问题的原理。设图像上的直线是y=x,&我们先取上面的三个点:A(0,0),&B(1,1),&C(22)。可以求出,过A点的直线的参数要满足方程b=0,&过B点的直线的参数要满足方程1=k+b,&过C点的直线的参数要满足方程2=2k+b,&这三个方程就对应着参数平面上的三条直线,而这三条直线会相交于一点(k=1,b=0)。 同理,原图像上直线y=x上的其它点(如(3,3),(4,4)等) 对应参数平面上的直线也会通过点(k=1,b=0)。这个性质就为我们解决问题提供了方法:
&&& 首先,我们初始化一块缓冲区,对应于参数平面,将其所有数据置为0.
&&& 对于图像上每一前景点,求出参数平面对应的直线,把这直线上的所有点的值都加1。
&&& 最后,找到参数平面上最大点的位置,这个位置就是原图像上直线的参数。&&&& 上面就是霍夫变换的基本思想。就是把图像平面上的点对应到参数平面上的线,最后通过统计特性来解决问题。假如图像平面上有两条直线,那么最终在参数平面上就会看到两个峰值点,依此类推。
&&& 在实际应用中,y=k*x+b形式的直线方程没有办法表示x=c形式的直线(这时候,直线的斜率为无穷大)。所以实际应用中,是采用参数方程p=x*cos(theta)+y*sin(theta)。这样,图像平面上的一个点就对应到参数p---theta平面上的一条曲线上。其它的还是一样。
&&& 在看下面一个问题:我们要从一副图像中检测出半径以知的圆形来。这个问题比前一个还要直观。我们可以取和图像平面一样的参数平面,以图像上每一个前景点为圆心,以已知的半径在参数平面上画圆,并把结果进行累加。最后找出参数平面上的峰值点,这个位置就对应了图像上的圆心。在这个问题里,图像平面上的每一点对应到参数平面上的一个圆。
&&& 把上面的问题改一下,假如我们不知道半径的值,而要找出图像上的圆来。这样,一个办法是把参数平面扩大称为三维空间。就是说,参数空间变为x--y--R三维,对应圆的圆心和半径。图像平面上的每一点就对应于参数空间中每个半径下的一个圆,这实际上是一个圆锥。最后当然还是找参数空间中的峰值点。不过,这个方法显然需要大量的内存,运行速度也会是很大问题。
&&& 有什么更好的方法么?我们前面假定的图像都是黑白图像(2值图像),实际上这些2值图像多是彩色或灰度图像通过边缘提取来的。我们前面提到过,图像边缘除了位置信息,还有方向信息也很重要,这里就用上了。根据圆的性质,圆的半径一定在垂直于圆的切线的直线上,也就是说,在圆上任意一点的法线上。这样,解决上面的问题,我们仍采用2维的参数空间,对于图像上的每一前景点,加上它的方向信息,都可以确定出一条直线,圆的圆心就在这条直线上。这样一来,问题就会简单了许多。
&&& 接下来还有许多类似的问题,如检测出椭圆,正方形,长方形,圆弧等等。这些方法大都类似,关键就是需要熟悉这些几何形状的数学性质。霍夫变换的应用是很广泛的,比如我们要做一个支票识别的任务,假设支票上肯定有一个红颜色的方形印章,我们可以通过霍夫变换来对这个印章进行快速定位,在配合其它手段进行其它处理。霍夫变换由于不受图像旋转的影响,所以很容易的可以用来进行定位。&&&& 霍夫变换有许多改进方法,一个比较重要的概念是广义霍夫变换,它是针对所有曲线的,用处也很大。就是针对直线的霍夫变换也有很多改进算法,比如前面的方法我们没有考虑图像上的这一直线上的点是否连续的问题,这些都要随着应用的不同而有优化的方法。
&&& 实现:
&&&上文中提到了检测圆的切线的方法,这里暂且不讨论,这里讨论经典HOUGH算法。下面为我写的利用极坐标表示圆的一种算法流程。
&&&1.图像灰度化,二值化(注意:二值化的好坏对检测结果有很大影响,常用的有SOBEL算子)
&& 2.检测图像中的边缘点,并保存其坐标位置。设置角度theta的变化范围和步长,半径r的变换范围和步长。
&& 3.利用公式x=a+rcos(theta),y=b+rsin(theta)求出a和b的值。(注意:x和y为实际的图像空间某个边缘点的坐标,a和b为其对应的参数空间的坐标),如果a和b的值在合理的范围之类,则对该位置进行累加。
for&i=1:ecount&&&&&&for&r=1:size_r&&&&&&&&&&for&k=1:size_angle&&&&&&&&&&&&&&a&=&round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));&&&&&&&&&&&&&&b&=&round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));&&&&&&&&&&&&&&if(a&0&a&=m&b&0&b&=n)&&&&&&&&&&&&&&&&&&hough_space(a,b,r)&=&hough_space(a,b,r)+1;&&&&&&&&&&&&&&end&&&&&&&&&&end&&&&&&end&&end&&
for i=1:ecount
for r=1:size_r
for k=1:size_angle
a = round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));
b = round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));
if(a&0&a&=m&b&0&b&=n)
hough_space(a,b,r) = hough_space(a,b,r)+1;
& 4.检索完毕,寻找最大值,求出圆心坐标与半径,保存。
& 附录:程序中红色的部分是我修改的。修改后编译通过。
function&[hough_space,hough_circle,para]&=&hough_circle(BW,step_r,step_angle,r_min,r_max,p);&&%[HOUGH_SPACE,HOUGH_CIRCLE,PARA]&=&HOUGH_CIRCLE(BW,STEP_R,STEP_ANGLE,R_MAX,P)&&%------------------------------算法概述-----------------------------&&%&该算法通过a&=&x-r*cos(angle),b&=&y-r*sin(angle)将圆图像中的边缘点&&%&映射到参数空间(a,b,r)中,由于是数字图像且采取极坐标,angle和r都取&&%&一定的范围和步长,这样通过两重循环(angle循环和r循环)即可将原图像&&%&空间的点映射到参数空间中,再在参数空间(即一个由许多小立方体组成的&&%&大立方体)中寻找圆心,然后求出半径坐标。&&%-------------------------------------------------------------------&&&&%------------------------------输入参数-----------------------------&&%&BW:二值图像;&&%&step_r:检测的圆半径步长&&%&step_angle:角度步长,单位为弧度&&%&r_min:最小圆半径&&%&r_max:最大圆半径&&%&p:以p*hough_space的最大值为阈值,p取0,1之间的数&&%-------------------------------------------------------------------&&&&%------------------------------输出参数-----------------------------&&%&hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数&&%&hough_circl:二值图像,检测到的圆&&%&para:检测到的圆的圆心、半径&&%-------------------------------------------------------------------&&&&%&From&Internet,Modified&by&mhjerry,&&&&[m,n]&=&size(BW);&&size_r&=&round((r_max-r_min)/step_r)+1;&&size_angle&=&round(2*pi/step_angle);&&&&&hough_space&=&zeros(m,n,size_r);&&&&&[rows,cols]&=&find(BW);&&ecount&=&size(rows);&&&&&%&Hough变换&&%&将图像空间(x,y)对应到参数空间(a,b,r)&&%&a&=&x-r*cos(angle)&&%&b&=&y-r*sin(angle)&&for&i=1:ecount&&&&&&for&r=1:size_r&&&&&&&&&&for&k=1:size_angle&&&&&&&&&&&&&&a&=&round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));&&&&&&&&&&&&&&b&=&round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));&&&&&&&&&&&&&&if(a&0&a&=m&b&0&b&=n)&&&&&&&&&&&&&&&&&&hough_space(a,b,r)&=&hough_space(a,b,r)+1;&&&&&&&&&&&&&&end&&&&&&&&&&end&&&&&&end&&end&&&&&%&搜索超过阈值的聚集点&&max_para&=&max(max(max(hough_space)));&&index&=&find(hough_space&=max_para*p);&&length&=&size(index);&&hough_circle=zeros(m,n);&&for&i=1:ecount&&&&&&for&k=1:length&&&&&&&&&&par3&=&floor(index(k)/(m*n))+1;&&&&&&&&&&par2&=&floor((index(k)-(par3-1)*(m*n))/m)+1;&&&&&&&&&&par1&=&index(k)-(par3-1)*(m*n)-(par2-1)*m;&&&&&&&&&&if((rows(i)-par1)^2+(cols(i)-par2)^2&(r_min+(par3-1)*step_r)^2+5&...&&&&&&&&&&&&&&&&&&(rows(i)-par1)^2+(cols(i)-par2)^2&(r_min+(par3-1)*step_r)^2-5)&&&&&&&&&&&&&&hough_circle(rows(i),cols(i))&=&1;&&&&&&&&&&end&&&&&&end&&end&&&&&%&打印结果&&for&k=1:length&&&&&&par3&=&floor(index(k)/(m*n))+1;&&&&&&par2&=&floor((index(k)-(par3-1)*(m*n))/m)+1;&&&&&&par1&=&index(k)-(par3-1)*(m*n)-(par2-1)*m;&&&&&&par3&=&r_min+(par3-1)*step_r;&&&&&&fprintf(1,'Center&%d&%d&radius&%d\n',par1,par2,par3);&&&&&&para(:,k)&=&[par1,par2,par3]';&&end&&
function [hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,r_min,r_max,p);
%[HOUGH_SPACE,HOUGH_CIRCLE,PARA] = HOUGH_CIRCLE(BW,STEP_R,STEP_ANGLE,R_MAX,P)
%------------------------------算法概述-----------------------------
% 该算法通过a = x-r*cos(angle),b = y-r*sin(angle)将圆图像中的边缘点
% 映射到参数空间(a,b,r)中,由于是数字图像且采取极坐标,angle和r都取
% 一定的范围和步长,这样通过两重循环(angle循环和r循环)即可将原图像
% 空间的点映射到参数空间中,再在参数空间(即一个由许多小立方体组成的
% 大立方体)中寻找圆心,然后求出半径坐标。
%-------------------------------------------------------------------
%------------------------------输入参数-----------------------------
% BW:二值图像;
% step_r:检测的圆半径步长
% step_angle:角度步长,单位为弧度
% r_min:最小圆半径
% r_max:最大圆半径
% p:以p*hough_space的最大值为阈值,p取0,1之间的数
%-------------------------------------------------------------------
%------------------------------输出参数-----------------------------
% hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数
% hough_circl:二值图像,检测到的圆
% para:检测到的圆的圆心、半径
%-------------------------------------------------------------------
% From Internet,Modified by mhjerry,
[m,n] = size(BW);
size_r = round((r_max-r_min)/step_r)+1;
size_angle = round(2*pi/step_angle);
hough_space = zeros(m,n,size_r);
[rows,cols] = find(BW);
ecount = size(rows);
% Hough变换
% 将图像空间(x,y)对应到参数空间(a,b,r)
% a = x-r*cos(angle)
% b = y-r*sin(angle)
for i=1:ecount
for r=1:size_r
for k=1:size_angle
a = round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));
b = round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));
if(a&0&a&=m&b&0&b&=n)
hough_space(a,b,r) = hough_space(a,b,r)+1;
% 搜索超过阈值的聚集点
max_para = max(max(max(hough_space)));
index = find(hough_space&=max_para*p);
length = size(index);
hough_circle=zeros(m,n);
for i=1:ecount
for k=1:length
par3 = floor(index(k)/(m*n))+1;
par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;
par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;
if((rows(i)-par1)^2+(cols(i)-par2)^2&(r_min+(par3-1)*step_r)^2+5&...
(rows(i)-par1)^2+(cols(i)-par2)^2&(r_min+(par3-1)*step_r)^2-5)
hough_circle(rows(i),cols(i)) = 1;
% 打印结果
for k=1:length
par3 = floor(index(k)/(m*n))+1;
par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;
par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;
par3 = r_min+(par3-1)*step_r;
fprintf(1,'Center %d %d radius %d\n',par1,par2,par3);
para(:,k) = [par1,par2,par3]';
end代码我已经上传到我的资源里,需要下载的,可以进我的空间下载。
注意半径范围的选取,直接影响到你想要检测的圆。而且,如果图像太大,且步长取得太小,可能会存在内存不够的情况。
运行结果:
边缘检测后:
检测结果:Center 62 59 radius 52
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:14455次
排名:千里之外
原创:14篇
(3)(1)(3)(1)(8)(5)21332人阅读
CV相关(281)
&&& 霍夫变换是图像处理中的一个检测直线、圆等简单几何形状的方法。它最初是用于在二值化的图像中进行直线检测的。对于图像中的一条直线而言,利用直角坐标系,可以表示为:的形式。那么,该直线上任意一点()变换到参数空间将变成一个“点”。也就是说,将图像空间中所有的非零像素转换到参数空间,那么它们将聚焦在一个点上。如此一来,参数空间中的一个局部峰值点就很有可能对应着原图像空间中的一条直线。不过,由于直线的斜率可能为无穷大,或者无穷小,那么,在参数空间就不便于对直线进行刻画和描述。所以,研究人员提出采用极坐标参数空间进行直线检测。在极坐标系中,直线可以表述为以下形式:
&&& 上图()所示为原始的图像空间中一个点;()所示为直角坐标系当中为过同一四条直线;()所示为这四条直线在极坐标参数空间可以表示为四个点;
在当中,霍夫之间检测函数并不会告诉你具体的计算步骤,而只是将极坐标空间中局部峰值点予以返回。支持两种不同的霍夫直线变换。标准霍夫变换和&,渐进概率式霍夫变换。就是刚才所述的在极坐标空间进行参数表示的方法。而是的改进,它是在一定的范围内进行霍夫变换,从而减少计算量,缩短计算时间。在中,以上两种霍夫直线变换,都可以用以下函数来实现:
CvSeq*&cvHoughLines2(CvArr*&image,&&void*&lineStorage,&&int&method,&&double&rho,&&&double&theta,&&int&threshold,&&double&param1=0,&&double&param2=0);该函数的第一个参数,是输入图片(必须是二值化后的图片),第二个参数是一个指针,指向保存函数返回结果的内存空间。第三个参数可以是也可以是或者分别代表了标准霍夫变换(),渐进概率式霍夫变换()和多尺度标准霍夫变换。接下来的两个参数和设置极坐标系的精度,其中以像素为单位,以弧度为单位。是用户设定的一个阈值,只有超过该阈值才被认定为是一条符合条件的直线。在方法中,和是不会被使用到的,而在方法中,设置检测到的直线(准确点说,是线段)的最短长度,则设置共线的两条线段的最小分割间隔。对于多尺度的标准霍夫变换()来说,首先根据用户设定的和来检测直线,之后,按照和的值对检测结果进行优化(即,)。
下面,我给出利用中的直线检测代码:
#include&&stdafx.h&
#include&&cv.h&
#include&&highgui.h&
#include&&iostream&
using&namespace&std;
bool&key&=&false;
int&_tmain(int&argc,&_TCHAR*&argv[])
IplImage*&src&=&cvLoadImage(&c:/img1.bmp&,&CV_LOAD_IMAGE_GRAYSCALE);
cout&&&src&load&error...&&&endl;
system(&pause&);
IplImage*&dst&=&cvCreateImage(&cvGetSize(src),&8,&1&);
IplImage*&color_dst&=&cvCreateImage(&cvGetSize(src),&8,&3&);
//cvCanny(&src,&dst,&50,&200,&3&);
cvThreshold(src,&dst,&50,&255,&CV_THRESH_BINARY_INV);
cvCvtColor(dst,&color_dst,&CV_GRAY2BGR);
CvMemStorage*&storage&=&cvCreateMemStorage(0);
CvSeq*&lines&=&0;
lines&=&cvHoughLines2(&dst,&storage,&CV_HOUGH_STANDARD,&1,&CV_PI/180,&100,&0,&0&);
for(&i&=&0;&i&&&MIN(lines-&total,100);&i++&)
float*&line&=&(float*)cvGetSeqElem(lines,i);
float&rho&=&line[0];
float&theta&=&line[1];
CvPoint&pt1,&pt2;
double&a&=&cos(theta),&b&=&sin(theta);
double&x0&=&a*rho,&y0&=&b*rho;
pt1.x&=&cvRound(x0&+&1000*(-b));
pt1.y&=&cvRound(y0&+&1000*(a));
pt2.x&=&cvRound(x0&-&1000*(-b));
pt2.y&=&cvRound(y0&-&1000*(a));
cvLine(&color_dst,&pt1,&pt2,&CV_RGB(255,0,0),&3,&CV_AA,&0&);
lines&=&cvHoughLines2(&dst,&storage,&CV_HOUGH_PROBABILISTIC,&1,&CV_PI/180,&50,&50,&10&);
for(&i&=&0;&i&&&lines-&total;&i++&)
CvPoint*&line&=&(CvPoint*)cvGetSeqElem(lines,i);
cvLine(&color_dst,&line[0],&line[1],&CV_RGB(255,0,0),&3,&CV_AA,&0&);
cvNamedWindow(&&Source&,&1&);
cvShowImage(&&Source&,&src&);
cvNamedWindow(&&Hough&,&1&);
cvShowImage(&&Hough&,&color_dst&);
cvSaveImage(&c:/result.bmp&,&color_dst);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvReleaseImage(&color_dst);
cvClearSeq(lines);
cvReleaseMemStorage(&storage);
system(&pause&);
以上代码的执行结果为:
&&&&&&&&&&&&&&&&&&&&&&&&& 原图
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 直线检测结果
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2607211次
积分:23959
积分:23959
排名:第215名
原创:175篇
转载:147篇
评论:1184条
(2)(1)(3)(1)(1)(2)(1)(1)(5)(3)(3)(5)(6)(3)(7)(8)(8)(7)(9)(11)(10)(7)(4)(10)(1)(8)(14)(12)(7)(1)(12)(6)(5)(16)(8)(5)(5)(5)(8)(2)(4)(4)(4)(5)(4)(4)(5)(5)(5)(2)(4)(1)(5)(6)(11)(10)(4)(6)(3)(1)君,已阅读到文档的结尾了呢~~
广告剩余8秒
文档加载中
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
利用局部算子检测峰值的改进Hough变换算法
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口

我要回帖

更多关于 hough变换检测圆代码 的文章

 

随机推荐