Hough变换在opencv中的应用
霍夫曼变换(Hough Transform)的原理
霍夫曼变换是一种可以检测出某种特殊形状的算法,OpenCV中用霍夫曼变换来检测出图像中的直线、椭圆和其他几何图形。由它改进的算法,可以用来检测任何形状的图形。
传统Hough变换 : 枚举统计法
找到通过足够多数量的像素点的所有直线,它分析每个单独的像素,并识别出所有的可能经过它的直线。
当同一条直线穿过许多点,便意味着这条线的存在足够明显。
累加器
累加器就是用来记录某条直线被识别了多少次,霍夫曼最直接的想法是,计算所有可能的直线,找出重复数量最多的那几条,重复次数就是识别的阈值。
演算步骤
Hough transform演算步骤(以直线为例):
直线公式: y = ax – b
称(x,y)为图像空间的坐标,(a,b)为参数空间
1. 在图像上找出所有可能的特征点
2. 对于每个特征点
1. 对于每个a,计算通过(x,y)的所有直线(a,b)
2. 在累加器的(a,b)位置上加一
重复步骤2,直到所有的特征点都计算完毕
1. 找到累加器里的最大值
2. 将每一个极大值,映射回图片上代表的每一条直线
极坐标
OpenCV实际采用的是极坐标(r,s),以左上角为原点:
r = xcos(s) + ysin(s)
代码:
// 选择特征点 (x, y)
int x = 50, y = 30;
// 计算通过它的所有直线
for(inti = 0; i < 180; i++) {
double s = i * PI/180. ;
double r = x*cos(s) + y*sin(s);
// j对应的r从 -100 到 100
int j = static_cast<int>(r + 100.5); std::cout << i << ","<<j<<std::endl;
// 填入累加器,极坐标 (j代表r,i代表s)
acc.at<uchar>(j,i)++;
}
性能
由上面的数学原理可知,Hough转换是一个运算耗时,需要大量内存的算法
概率Hough变换
为了改进原算法,提出了一个优化方案,即概率霍夫曼变换
在原算法的基础上做了少许的修改
1. 不再逐行扫描像素点,而是随机挑选
2. 某个直线达到投票值后,扫描并移除所有经过的点,这次扫描结束后还可以得到线段长度
3. 增加两个参数:线段最小长度、组成连续线段的最大像素间隔
算法复杂度增加,但是参与投票的像素点少了,补偿了整个算法的复杂度。
检测其他几何体
霍夫曼变换也可用于检测其他几何体,事实上只要是可以用参数方程表示的东西都可以用Hough进行检测
检测圆形
r^2 = (x – a)^2 + (y – b)^2
方程有3个参数,需要3维累加器,如同直线检测:
// 对某个特征点 (怎么选择是一种优化)
int x, y;
for(a = 0; a < max_a; a++)
for(b = 0; b < max_b; b++)
{
r = (int)sqrt((x-a)*(x-a) + (y-b)*(y-b));
if(r > 0 && r < max_r)
acc.at<uchar>(a, b, r)++;
}
维度变高后,复杂度和可靠度都会变坏,因为精确定位局部峰值变的困难了,OpenCV做了优化,比如只增加圆环梯度方向上的累加器,对结果求直方图而非极值,峰值对应的是检测到的园的半径
广义霍夫曼变换
虽然很难用参数表示一些形状,但原理是相同的:创建一个累加器,用来表示所有可能在目标形状上的位置
为了检测无法被参数化的(没有解析模型)不规则形状泛化Hough变换被提出,Generalized Hough Transform(GHT)
广义hough变换,如果再考虑旋转和缩放就需要在更高维度上搜索.
5个参数表示
定义任意形状的表示参数:
X,Y,r,s,a,thea,其中,XY为形状内的一个参考点,s是缩放因子,thea是方向
分为两大步AB
A:计算R-table
计算R-Table,r是到原点的距离,a是梯度与x轴的夹角(0-180),%代表该点切线(梯度垂直)方向与X轴的夹角
r-table是r-table[%] = (r,a),(r',a')
%1 : (r1, a1), (r1',a1')
%2 : (r2, a2), (r2', a2')
… : …
%n : (rn, an), (rn', an')
1. 选取参考点(xc,yc)
2. 初始化R-table为空
3. 对每个边缘点,计算(r,a)值
1. r = sqrt((x-xc)^2 + (y-yc)^2)
1. a = tan'((y-yc)/(x-xc))
4. 计算%(切线),并将(r,a)加入与%最接近的%i
5. 重复4、5,直到所有的边缘点都已经加入R-table
B:形状检测
1. 建立2维的hough table H(xc, yc),初始化为0
2. 针对每一个边缘点,计算切线(垂直梯度)夹角%
3. 在R-table中,查找最接近%的%i,对其内的所有(r,a),计算对应的原点(xc,yc)
xc = x + rcos(a)
yc = y + rsin(a)
4. 将H(xc, yc)累加1,重复2、3,直到所有的边缘点都完成检测
5. 找出H(xc,yc)中的局部最大值,其(xc,yc)即为检测出来的形状
考虑旋转和缩放
上面的过程没考虑旋转thea和缩放因子,考虑内的H变为
H(xc, yc, thea, s)
B中的3步骤改为
xc = x + r.Scos(a + thea)
yc = y + r.Ssin(a + thea)
问题
GHT占用内存大,计算复杂,单匹配固定形状的精度高,也许在未来能有更优化的版本
Hough变换在opencv中的应用的更多相关文章
- 利用Hough变换识别图像中的直线
引入 近期看到2015年数学建模A题太阳影子定位中的第四问,需要根据附件中视频里的直杆的太阳影子的变化确定拍摄地点.其实确定拍摄地点这个问题并不是十分困难,因为有前三问的铺垫,我们已经得出了太阳影子长 ...
- Matlab实现Hough变换检测图像中的直线 分类: 图像处理 2014-06-14 22:07 641人阅读 评论(0) 收藏
Hough变换的原理: 将图像从图像空间变换至参数空间,变换公式如下: 变换以后,图像空间与参数空间存在以下关系: 图像空间中的一点在参数空间是一条曲线,而图像空间共线的各点对应于参数空间交于一点的各 ...
- Matlab实现Hough变换检測图像中的直线
Hough变换的原理: 将图像从图像空间变换至參数空间.变换公式例如以下: 变换以后,图像空间与參数空间存在下面关系: 图像空间中的一点在參数空间是一条曲线,而图像空间共线的各点相应于參数空间交于一点 ...
- OpenCV中的霍夫线变换和霍夫圆变换
一.霍夫线变换 霍夫线变换是OpenCv中一种寻找直线的方法,输入图像为边缘二值图. 原理: 一条直线在图像二维空间可由两个变量表示, 例如: 1.在 笛卡尔坐标系: 可由参数: (m,b) 斜率和截 ...
- hough变换算法
1.算法思想 边缘检测比如canny算子可以识别出图像的边缘,但是实际中由于噪声和光照不均匀等因素,很多情况下获得的边缘点是不连续的,必须通过边缘连接将他们转换为有意义的边缘.Hough变化是一个重要 ...
- Hough变换原理
Hough变换原理 一.简单介绍 Hough变换是图像处理中从图像中识别几何形状的基本方法之一.Hough变换的基本原理在于利用点与线的对偶性,将原始图像空间的给定的曲线通过曲线表达形式变为参数空间的 ...
- 查找图像中椭圆轮廓的快速随机hough变换
查找图像中椭圆轮廓的快速随机hough变换 图像中椭圆轮廓的查找在视频监控等领域有着广泛的应用,经典hough变换给我们提供了一种查找各种图形轮廓的方法,特别是在直线查找方面具有非常高的精确度.但是由 ...
- [OpenCV-Python] OpenCV 中的图像处理 部分 IV (六)
部分 IVOpenCV 中的图像处理 OpenCV-Python 中文教程(搬运)目录 23 图像变换 23.1 傅里叶变换目标本小节我们将要学习: • 使用 OpenCV 对图像进行傅里叶变换 • ...
- hough变换检测线和圆
参考:http://blog.163.com/yuyang_tech/blog/static/21605008320130233343990/ 这篇介绍的基本思想. http://www.cnblog ...
随机推荐
- Linux网卡设置
http://blog.chinaunix.net/uid-20149676-id-1733254.html
- android面试题之三
十一.对一些资源以及状态的操作保存,最好是保存在生命周期的哪个函数中进行? 若在onPause()中进行保存,相应需要在onResume()中进行恢复. 若在onStop()中进行保存,相应需要在on ...
- UVALive 5102 Fermat Point in Quadrangle 极角排序+找距离二维坐标4个点近期的点
题目链接:点击打开链接 题意: 给定二维坐标上的4个点 问: 找一个点使得这个点距离4个点的距离和最小 输出距离和. 思路: 若4个点不是凸4边形.则一定是端点最优. 否则就是2条对角线的交点最优,能 ...
- 【转】lnmp_auto:自动化安装lnmp环境脚本
原文链接: lnmp_auto:自动化安装lnmp环境脚本 这哥们整理的这篇博文很好 转载分享 博文转载如下: 源代码在github上:https://github.com/jianfengye/ ...
- 【集训笔记】归纳与递推【HDOJ1297
例:(2050)折线分割平面 问题描述: 平面上有n条折线,问这些折线最多能将平面分割成多少块? 样例输入 1 2 样例输出 2 7 平面上有n条折线,问这些折线最多能将平面分割成多少块? 解: 折线 ...
- 在DE1-SOC上运行Linux
1,设定串口终端 安装驱动 :使用mini-USB线将计算机与DE1-SoC的UART转USB接口.drivers\USB2UART_driver文件夹内放置有驱动程序 设定串口终端规格 : 设定串口 ...
- 鼠标滑轮一滚动Excel就停止工作
鼠标滑轮一滚动Excel就停止工作 问题签名: 问题事件名称:APPCRASH 应用程序名:EXCEL.EXE 应用程序版本:15.0.4420.1017 应用程序时间戳:50673286 故障模块名 ...
- Android编程心得-设计一个可重用的自定义Dialog
我们在实际开发过程中,会遇到一个问题,我们的Dialog如果使用一般的方法进行设置调用出来,会有很多的重复代码,如何将Dialog按照自己的思路设计呢,并让其可重用呢,下面我来介绍一下 ...
- BZOJ 1305: [CQOI2009]dance跳舞( 最大流 )
云神代码很短...0 ms过的...看了代码 , 大概是贪心... orz 我不会证 数据这么小乱搞就可以了吧... ←_← 这道题网络流还是可以写的... 既然限制了最多只能和 k 个不喜欢的人da ...
- list和用vector区别(Vector相当于是数组,读写快,插入慢)
stl提供了三个最基本的容器:vector,list,deque. vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即[]操作符,但由 ...