Hough变换的基本原理

2024-05-07 12:08
文章标签 基本原理 变换 hough

本文主要是介绍Hough变换的基本原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   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的值在合理的范围之类,则对该位置进行累加。

   例如:

  

[cpp] view plain copy print ?
  1. for i=1:ecount  
  2.     for r=1:size_r  
  3.         for k=1:size_angle  
  4.             a = round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));  
  5.             b = round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));  
  6.             if(a>0&a<=m&b>0&b<=n)  
  7.                 hough_space(a,b,r) = hough_space(a,b,r)+1;  
  8.             end  
  9.         end  
  10.     end  
  11. 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;
end
end
end
end

  4.检索完毕,寻找最大值,求出圆心坐标与半径,保存。

  附录:程序中红色的部分是我修改的。修改后编译通过。

 

[cpp] view plain copy print ?
  1. function [hough_space,hough_circle,para] = hough_circle(BW,step_r,step_angle,r_min,r_max,p);  
  2. %[HOUGH_SPACE,HOUGH_CIRCLE,PARA] = HOUGH_CIRCLE(BW,STEP_R,STEP_ANGLE,R_MAX,P)  
  3. %------------------------------算法概述-----------------------------  
  4. % 该算法通过a = x-r*cos(angle),b = y-r*sin(angle)将圆图像中的边缘点  
  5. % 映射到参数空间(a,b,r)中,由于是数字图像且采取极坐标,angle和r都取  
  6. % 一定的范围和步长,这样通过两重循环(angle循环和r循环)即可将原图像  
  7. % 空间的点映射到参数空间中,再在参数空间(即一个由许多小立方体组成的  
  8. % 大立方体)中寻找圆心,然后求出半径坐标。  
  9. %-------------------------------------------------------------------  
  10.   
  11. %------------------------------输入参数-----------------------------  
  12. % BW:二值图像;  
  13. % step_r:检测的圆半径步长  
  14. % step_angle:角度步长,单位为弧度  
  15. % r_min:最小圆半径  
  16. % r_max:最大圆半径  
  17. % p:以p*hough_space的最大值为阈值,p取0,1之间的数  
  18. %-------------------------------------------------------------------  
  19.   
  20. %------------------------------输出参数-----------------------------  
  21. % hough_space:参数空间,h(a,b,r)表示圆心在(a,b)半径为r的圆上的点数  
  22. % hough_circl:二值图像,检测到的圆  
  23. % para:检测到的圆的圆心、半径  
  24. %-------------------------------------------------------------------  
  25.   
  26. % From Internet,Modified by mhjerry,2011-12-11  
  27.   
  28. [m,n] = size(BW);  
  29. size_r = round((r_max-r_min)/step_r)+1;  
  30. size_angle = round(2*pi/step_angle);  
  31.    
  32. hough_space = zeros(m,n,size_r);  
  33.    
  34. [rows,cols] = find(BW);  
  35. ecount = size(rows);  
  36.    
  37. % Hough变换  
  38. % 将图像空间(x,y)对应到参数空间(a,b,r)  
  39. % a = x-r*cos(angle)  
  40. % b = y-r*sin(angle)  
  41. for i=1:ecount  
  42.     for r=1:size_r  
  43.         for k=1:size_angle  
  44.             a = round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));  
  45.             b = round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));  
  46.             if(a>0&a<=m&b>0&b<=n)  
  47.                 hough_space(a,b,r) = hough_space(a,b,r)+1;  
  48.             end  
  49.         end  
  50.     end  
  51. end  
  52.    
  53. % 搜索超过阈值的聚集点  
  54. max_para = max(max(max(hough_space)));  
  55. index = find(hough_space>=max_para*p);  
  56. length = size(index);  
  57. hough_circle=zeros(m,n);  
  58. for i=1:ecount  
  59.     for k=1:length  
  60.         par3 = floor(index(k)/(m*n))+1;  
  61.         par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;  
  62.         par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;  
  63.         if((rows(i)-par1)^2+(cols(i)-par2)^2<(r_min+(par3-1)*step_r)^2+5&...  
  64.                 (rows(i)-par1)^2+(cols(i)-par2)^2>(r_min+(par3-1)*step_r)^2-5)  
  65.             hough_circle(rows(i),cols(i)) = 1;  
  66.         end  
  67.     end  
  68. end  
  69.    
  70. % 打印结果  
  71. for k=1:length  
  72.     par3 = floor(index(k)/(m*n))+1;  
  73.     par2 = floor((index(k)-(par3-1)*(m*n))/m)+1;  
  74.     par1 = index(k)-(par3-1)*(m*n)-(par2-1)*m;  
  75.     par3 = r_min+(par3-1)*step_r;  
  76.     fprintf(1,'Center %d %d radius %d\n',par1,par2,par3);  
  77.     para(:,k) = [par1,par2,par3]';  
  78. 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,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
代码我已经上传到我的资源里,需要下载的,可以进我的空间下载。

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

程序:


运行结果:

原图:

边缘检测后:

 

检测结果:Center 62 59 radius 52


 

这篇关于Hough变换的基本原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967303

相关文章

Verybot之OpenCV应用二:霍夫变换查找圆

其实我是想通过这个程序来测试一下,OpenCV在Verybot上跑得怎么样,霍夫变换的原理就不多说了,下面是程序: #include "cv.h"#include "highgui.h"#include "stdio.h"int main(int argc, char** argv){cvNamedWindow("vedio",0);CvCapture* capture;i

防盗链的基本原理与实现

我的实现防盗链的做法,也是参考该位前辈的文章。基本原理就是就是一句话:通过判断request请求头的refer是否来源于本站。(当然请求头是来自于客户端的,是可伪造的,暂不在本文讨论范围内)。首先我们去了解下什么是HTTP Referer。简言之,HTTP Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务

【CSS in Depth 2 精译_023】第四章概述 + 4.1 Flexbox 布局的基本原理

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一章 层叠、优先级与继承(已完结) 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位(已完结) 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性2.7 本章小结 第三章 文档流与盒模型(已

AI学习指南深度学习篇-带动量的随机梯度下降法的基本原理

AI学习指南深度学习篇——带动量的随机梯度下降法的基本原理 引言 在深度学习中,优化算法被广泛应用于训练神经网络模型。随机梯度下降法(SGD)是最常用的优化算法之一,但单独使用SGD在收敛速度和稳定性方面存在一些问题。为了应对这些挑战,动量法应运而生。本文将详细介绍动量法的原理,包括动量的概念、指数加权移动平均、参数更新等内容,最后通过实际示例展示动量如何帮助SGD在参数更新过程中平稳地前进。

Zookeeper基本原理

1.什么是Zookeeper?         Zookeeper是一个开源的分布式协调服务器框架,由Apache软件基金会开发,专为分布式系统设计。它主要用于在分布式环境中管理和协调多个节点之间的配置信息、状态数据和元数据。         Zookeeper采用了观察者模式的设计理念,其核心职责是存储和管理集群中共享的数据,并为各个节点提供一致的数据视图。在Zookeeper中,客户端(如

Filter基本原理和使用

https://www.cnblogs.com/xdp-gacl/p/3948353.html 一、Filter简介   Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控

【数字信号处理】一文讲清FFT(快速傅里叶变换)

目录 快速傅里叶变换(Fast Fourier Transform,FFT)FFT的背景快速傅里叶变换(Fast Fourier Transform,FFT)DFT的数学表达实际计算重要性和应用频谱泄露、频谱混叠奈奎斯特采样定理参考链接 快速傅里叶变换(Fast Fourier Transform,FFT) FFT的背景 1、为什么要时域→频域频率?50Hz+频率120Hz

傅里叶变换家族

禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

齐次变换矩阵的原理与应用

齐次变换矩阵的原理与应用 通过齐次变换矩阵,可以描述机械臂末端执行器(法兰)在三维空间中的平移和旋转操作。该矩阵结合了旋转和平移信息,用于坐标变换。 1. 齐次变换矩阵的基本形式 一个齐次变换矩阵 T是一个 4x4 矩阵,表示刚体的旋转和平移: T = [ R t 0 1 ] = [ r 11 r 12 r 13 x r 21 r 22 r 23 y r 31 r 32 r 33 z 0

golang学习笔记02——gin框架及基本原理

目录 1.前言2.必要的知识3.路由注册流程3.1 核心数据结构3.2 执行流程3.3 创建并初始化gin.Engine3.4 注册middleware3.5 注册路由及处理函数(1)拼接完整的路径参数(2)组合处理函数链(3)注册完成路径及处理函数链到路由树 3.6 服务端口监听 4. 请求处理5. 请求绑定和响应渲染5.1. 请求绑定5.2 响应渲染 结束语 1.前言 g