Hough变换检测圆(附:MATLAB程序)

Hough变换检测圆(附:MATLAB程序)Hough 变换的基本原理在于 利用点与线的对偶性 将图像空间的线条变为参数空间的聚集点 从而检测给定图像是否存在给定性质的曲线 圆的方程为 x a 2 y 2 2 r 2 通过 Hough 变换 将图像空间对应到参数空间 附录中的 MATLAB 程序为网上比较常见的 实际运行中存在一些问题 这里进行些修改 nbsp nbsp nbsp 原理 nbsp nbsp nbsp 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一 应

    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

  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,2011-12-11 [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

代码我已经上传到我的资源里,需要下载的,可以进我的空间下载。

注意半径范围的选取,直接影响到你想要检测的圆。而且,如果图像太大,且步长取得太小,可能会存在内存不够的情况。

程序:


运行结果:

原图:Hough变换检测圆(附:MATLAB程序)

边缘检测后:Hough变换检测圆(附:MATLAB程序)

 

检测结果:Center 62 59 radius 52


 Hough变换检测圆(附:MATLAB程序)




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218220.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午7:47
下一篇 2026年3月18日 上午7:47


相关推荐

  • pl sql 循环_sql循环语句怎么写

    pl sql 循环_sql循环语句怎么写1、Loop……endLoop语句标准格式:LOOP statement_list–循环代码块 IFexit_conditionTHEN EXIT;–满足IF条件退出循环 ENDIF;ENDLOOP;–从1开始打印,当i=10退出循环。pl/sql中“=”表示比较,“:=”表示赋值。DECLAREiNUMBER;BEGIN i:=0; LOOP i:=i+1; dbms_output.put_line(i); IF i=

    2022年10月9日
    6
  • 单片机毕业生设计题目_单片机毕业设计作品

    单片机毕业生设计题目_单片机毕业设计作品可追溯农产品电商管理系统的设计与实现 农产品用户商城系统设计与实现 基于OpenGL的全局光照算法的设计与实现 分布式存储系统分析与设计 基于机器学习的数据库融合技术研究 基于知识图谱的对话系统设计与实现 具有日志的虚拟WEB攻防系统设计与实现 企业生产自动排产系统设计 能效管理系统的设计 视频会议终端软件设计 空间演化博弈平台的设计和研究 基于APS数据集的科研合作网络的结构演化研究 Internet拓扑网络的K-核演化特性研究 基于空间网络的城市轨道交

    2026年4月15日
    6
  • js对日期进行升序排序

    js对日期进行升序排序

    2021年11月22日
    57
  • Spring batch教程 之 配置Step「建议收藏」

    Spring batch教程 之 配置Step「建议收藏」正如在BatchDomainLanguage中叙述的,Step是一个独立封装域对象,包含了所有定义和控制实际处理信息批任务的序列。这是一个比较抽象的描述,因为任意一个Step的内容都是开发者自己编写的Job。一个Step的简单或复杂取决于开发者的意愿。一个简单的Step也许是从本地文件读取数据存入数据库,写很少或基本无需写代码。一个复杂的Step也许有复杂的业务规则(取决于所实现的方式),并作

    2022年5月28日
    39
  • pidstat_进程实时监控pidstat命令详解

    pidstat_进程实时监控pidstat命令详解pidstat 主要用于监控全部或指定进程占用系统资源的情况 如 CPU 内存 设备 IO 任务切换 线程等 pidstat 首次运行时显示自系统启动开始的各项统计信息 之后运行 pidstat 将显示自上次运行该命令以后的统计信息 用户可以通过指定统计的次数和时间来获得所需的统计信息 实例讲解默认参数执行 pidstat 将输出系统启动后所有活动进程的 cpu 统计信息 pidstat1Linu 13

    2026年3月18日
    2
  • StringBuilder详解「建议收藏」

    StringBuilder详解「建议收藏」1、简介StringBuilder和StringBuffer一样,都是继承自抽象类AbstractStringBuilder类,也是一个可变的字符序列。StringBuilder和StringBuffer非常相似,甚至有互相兼容的API,不过,StringBuilder不是线程安全的,这是和StringBuffer的主要区别。StringBuilder的层次结构如下:StringB

    2022年6月28日
    26

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号