当前位置:文档之家› 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑
【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

本系列文章由@浅墨_毛星云出品,转载请注明出处。

文章链接: https://www.doczj.com/doc/a64362425.html,/poem_qianmo/article/details/26977557

作者:毛星云(浅墨)微博:https://www.doczj.com/doc/a64362425.html,/u/1723155442

知乎:https://www.doczj.com/doc/a64362425.html,/people/mao-xing-yun

邮箱:happylifemxy@https://www.doczj.com/doc/a64362425.html,

写作当前博文时配套使用的OpenCV版本: 2.4.9

本篇文章中,我们一起探讨了OpenCV中霍夫变换相关的知识点,以及了解了OpenCV中实现霍夫线变换的HoughLines、HoughLinesP函数的使用方法,实现霍夫圆变换的HoughCircles函数的使用方法。此博文一共有四个配套的简短的示例程序,其详细注释过的代码都在文中贴出,且文章最后提供了综合示例程序的下载。

先尝鲜一下其中一个示例程序的运行截图:

一、引言

在图像处理和计算机视觉领域中,如何从当前的图像中提取所需要的特征信息是图像识别的关键所在。在许多应用场合中需要快速准确地检测出直线或者圆。其中一种非常有效的解决问题的方法是霍夫(Hough)变换,其为图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。最基本的霍夫变换是从黑白图像中检测直线(线段)。这篇文章就将介绍OpenCV中霍夫变换的使用方法和相关知识。

二、霍夫变换概述

霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。

霍夫变换于1962年由PaulHough首次提出,最初的Hough变换是设计用来检测直线和曲线,起初的方法要求知道物体边界线的解析方程,但不需要有关区域位置的先验知识。这种方法的一个突出优点是分割结果的Robustness,即对数据的不完全或噪声不是非常敏感。然而,要获得描述边界的解析表达常常是不可能的。后于1972年由Richard Duda & Peter Hart推广使用,经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。

霍夫变换在OpenCV中分为霍夫线变换和霍夫圆变换两种,我们下面将分别进行介绍。

三、霍夫线变换

3.1 OpenCV中的霍夫线变换

我们知道,霍夫线变换是一种用来寻找直线的方法. 在使用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像.

OpenCV支持三种不同的霍夫线变换,它们分别是:标准霍夫变换(Standard Hough Transform,SHT)和多尺度霍夫变换(Multi-Scale Hough Transform,MSHT)累计概率霍夫变换(Progressive Probabilistic Hough Transform ,PPHT)。

其中,多尺度霍夫变换(MSHT)为经典霍夫变换(SHT)在多尺度下的一个变种。累计概率霍夫变换(PPHT)算法是标准霍夫变换(SHT)算法的一个改进,它在一定的范围内进行霍夫变换,计算单独线段的方向以及范围,从而减少计算量,缩短计算时间。之所以称PPHT为“概率”的,是因为并不将累加器平面内的所有可能的点累加,而只是累加其中的一部分,该想法是如果峰值如果足够高,只用一小部分时间去寻找它就够了。这样猜想的话,可以实质性地减少计算时间。

在OpenCV中,我们可以用HoughLines函数来调用标准霍夫变换SHT和多尺度霍夫变换MSHT。

而HoughLinesP函数用于调用累计概率霍夫变换PPHT。累计概率霍夫变换执行效率很高,所有相比于HoughLines函数,我们更倾向于使用HoughLinesP函数。

总结一下,OpenCV中的霍夫线变换有如下三种:

<1>标准霍夫变换(StandardHough Transform,SHT),由HoughLines函数调用。

<2>多尺度霍夫变换(Multi-ScaleHough Transform,MSHT),由HoughLines函数调用。

<3>累计概率霍夫变换(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函数调用。

3.2 霍夫线变换的原理

【1】众所周知, 一条直线在图像二维空间可由两个变量表示. 如:

<1>在笛卡尔坐标系: 可由参数: 斜率和截距(m,b) 表示。

<2>在极坐标系: 可由参数: 极径和极角表示。

对于霍夫变换, 我们将采用第二种方式极坐标系来表示直线. 因此, 直线的表达式可为:

化简便可得到:

【2】一般来说对于点, 我们可以将通过这个点的一族直线统一定义为:

这就意味着每一对代表一条通过点的直线。

【3】如果对于一个给定点我们在极坐标对极径极角平面绘出所有通过它的直线, 将得到一条正弦曲线. 例如, 对于给定点X_0= 8 和Y_0= 6 我们可以绘出下图(在平面):

只绘出满足下列条件的点和 .

【4】我们可以对图像中所有的点进行上述操作. 如果两个不同点进行上述操作后得到的曲线在平面相交, 这就意味着它

们通过同一条直线. 例如,接上面的例子我们继续对点和点绘图, 得到下图:

这三条曲线在平面相交于点(0.925, 9.6), 坐标表示的是参数对或者是说点, 点和点组成的平面内的的直线。

【5】以上的说明表明,一般来说, 一条直线能够通过在平面寻找交于一点的曲线数量来检测。

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

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

3.3 HoughLines( )函数详解

此函数可以找出采用标准霍夫变换的二值图像线条。在OpenCV中,我们可以用其来调用标准霍夫变换SHT和多尺度霍夫变换MSHT的OpenCV内建算法。

[cpp]view plaincopyprint?

1.C++: void HoughLines(InputArray image, OutputArray lines, double rho, double th

eta, int threshold, double srn=0, double stn=0 )

第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,

可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。

?第二个参数,InputArray类型的lines,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示,其中,是离坐标原点((0,0)(也就是图像的左上角)的距离。是弧度线条旋转角度(0~垂直线,π/2~水平线)。

?第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。PS:Latex中/rho就表示。

?第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。

?第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。

?第六个参数,double类型的srn,有默认值0。对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn。

?第七个参数,double类型的stn,有默认值0,对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srn和stn同时为0,就表示使用经典的霍夫变换。

否则,这两个参数应该都为正数。

另外,关于霍夫变换的详细解释,可以看此英文页面:

https://www.doczj.com/doc/a64362425.html,/rbf/HIPR2/hough.htm

在学完函数解析,看看浅墨为大家准备的以HoughLines为核心的示例程序,就可以全方位了解HoughLines函数的使用方法了:

[cpp]view plaincopyprint?

1.//-----------------------------------【头文件包含部分】---------------------------------------

2.// 描述:包含程序所依赖的头文件

3.//----------------------------------------------------------------------------------------------

4.#include

5.#include

6.

7.//-----------------------------------【命名空间声明部分】

---------------------------------------

8.// 描述:包含程序所使用的命名空间

9.//----------------------------------------------------------------------------------------------

-

https://www.doczj.com/doc/a64362425.html,ing namespace cv;

11.//-----------------------------------【main( )函数】

--------------------------------------------

12.// 描述:控制台应用程序的入口函数,我们的程序从这里开始

13.//----------------------------------------------------------------------------------------------

-

14.int main( )

15.{

16. //【1】载入原始图和Mat变量定义

17. Mat srcImage = imread("1.jpg"); //工程目录下应该有一张名为1.jpg的素材图

18. Mat midImage,dstImage;//临时变量和目标图的定义

19.

20. //【2】进行边缘检测和转化为灰度图

21. Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测

22. cvtColor(midImage,dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图

23.

24. //【3】进行霍夫线变换

25. vector lines;//定义一个矢量结构lines用于存放得到的线段矢量集合

26. HoughLines(midImage, lines, 1, CV_PI/180, 150, 0, 0 );

27.

28. //【4】依次在图中绘制出每条线段

29. for( size_t i = 0; i < lines.size(); i++ )

30. {

31. float rho = lines[i][0], theta = lines[i][1];

32. Point pt1, pt2;

33. double a = cos(theta), b = sin(theta);

34. double x0 = a*rho, y0 = b*rho;

35. pt1.x = cvRound(x0 + 1000*(-b));

36. pt1.y = cvRound(y0 + 1000*(a));

37. pt2.x = cvRound(x0 - 1000*(-b));

38. pt2.y = cvRound(y0 - 1000*(a));

39. line( dstImage, pt1, pt2, Scalar(55,100,195), 1, CV_AA);

40. }

41.

42. //【5】显示原始图

43. imshow("【原始图】", srcImage);

44.

45. //【6】边缘检测后的图

46. imshow("【边缘检测后的图】", midImage);

47.

48. //【7】显示效果图

49. imshow("【效果图】", dstImage);

50.

51. waitKey(0);

52.

53. return 0;

54.}

运行截图:

来一张大图:

PS:可以通过调节line(dstImage, pt1, pt2, Scalar(55,100,195), 1, CV_AA);一句Scalar(55,100,195)参数中G、B、R颜色值的数值,得到图中想要的线条颜色。

3.4 HoughLinesP( )函数详解

此函数在HoughLines的基础上末尾加了一个代表Probabilistic(概率)的P,表明它可以采用累计概率霍夫变换(PPHT)来找出二值图像中的直线。

[cpp]view plaincopyprint?

1.C++: void HoughLinesP(InputArray image, OutputArray lines, double rho, double t

heta, int threshold, double minLineLength=0, double maxLineGap=0 )

?第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。

?第二个参数,InputArray类型的lines,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2)表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点。

?第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。

?第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。

?第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。

?第六个参数,double类型的minLineLength,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。

?第七个参数,double类型的maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。

对于此函数,依然是为大家准备了示例程序:

[cpp]view plaincopyprint?

1.//-----------------------------------【头文件包含部分】---------------------------------------

2.// 描述:包含程序所依赖的头文件

3.//----------------------------------------------------------------------------------------------

4.#include

5.#include

6.

7.//-----------------------------------【命名空间声明部分】

---------------------------------------

8.// 描述:包含程序所使用的命名空间

9.//----------------------------------------------------------------------------------------------

-

https://www.doczj.com/doc/a64362425.html,ing namespace cv;

11.//-----------------------------------【main( )函数】

--------------------------------------------

12.// 描述:控制台应用程序的入口函数,我们的程序从这里开始

13.//----------------------------------------------------------------------------------------------

-

14.int main( )

15.{

16. //【1】载入原始图和Mat变量定义

17. Mat srcImage = imread("1.jpg"); //工程目录下应该有一张名为1.jpg的素材图

18. Mat midImage,dstImage;//临时变量和目标图的定义

19.

20. //【2】进行边缘检测和转化为灰度图

21. Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测

22. cvtColor(midImage,dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图

23.

24. //【3】进行霍夫线变换

25. vector lines;//定义一个矢量结构lines用于存放得到的线段矢量集合

26. HoughLinesP(midImage, lines, 1, CV_PI/180, 80, 50, 10 );

27.

28. //【4】依次在图中绘制出每条线段

29. for( size_t i = 0; i < lines.size(); i++ )

30. {

31. Vec4i l = lines[i];

32. line( dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186,88,255), 1, CV_AA);

33. }

34.

35. //【5】显示原始图

36. imshow("【原始图】", srcImage);

37.

38. //【6】边缘检测后的图

39. imshow("【边缘检测后的图】", midImage);

40.

41. //【7】显示效果图

42. imshow("【效果图】", dstImage);

43.

44. waitKey(0);

45.

46. return 0;

47.}

运行截图:

来一张大图:

四、霍夫圆变换

霍夫圆变换的基本原理和上面讲的霍夫线变化大体上是很类似的,只是点对应的二维极径极角空间被三维的圆心点x, y还有半径r空间取代。说“大体上类似”的原因是,如果完全用相同的方法的话,累加平面会被三维的累加容器所代替:在这三维中,一维是x,一维是y,另外一维是圆的半径r。这就意味着需要大量的内存而且执行效率会很低,速度会很慢。

对直线来说, 一条直线能由参数极径极角表示. 而对圆来说, 我们需要三个参数来表示一个圆, 也

就是:

这里的表示圆心的位置(下图中的绿点) 而r 表示半径, 这样我们就能唯一的定义一个圆了, 见下图:

在OpenCV中,我们一般通过一个叫做“霍夫梯度法”的方法来解决圆变换的问题。

4.1 霍夫梯度法的原理

霍夫梯度法的原理是这样的。

【1】首先对图像应用边缘检测,比如用canny边缘检测。

【2】然后,对边缘图像中的每一个非零点,考虑其局部梯度,即用Sobel()函数计算x和y方向的Sobel 一阶导数得到梯度。

【3】利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加,这里的斜率是从一个指定的最小值到指定的最大值的距离。

【4】同时,标记边缘图像中每一个非0像素的位置。

【5】然后从二维累加器中这些点中选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻。这些候选的中心按照累加值降序排列,以便于最支持像素的中心首先出现。

【6】接下来对每一个中心,考虑所有的非0像素。

【7】这些像素按照其与中心的距离排序。从到最大半径的最小距离算起,选择非0像素最支持的一条半径。8.如果一个中心收到边缘图像非0像素最充分的支持,并且到前期被选择的中心有足够的距离,那么它就会被保留下来。

这个实现可以使算法执行起来更高效,或许更加重要的是,能够帮助解决三维累加器中会产生许多噪声并且使得结果不稳定的稀疏分布问题。

人无完人,金无足赤。同样,这个算法也并不是十全十美的,还有许多需要指出的缺点。

4.2 霍夫梯度法的缺点

<1>在霍夫梯度法中,我们使用Sobel导数来计算局部梯度,那么随之而来的假设是,其可以视作等同于一条局部切线,并这个不是一个数值稳定的做法。在大多数情况下,这样做会得到正确的结果,但或许会在输出中产生一些噪声。

<2>在边缘图像中的整个非0像素集被看做每个中心的候选部分。因此,如果把累加器的阈值设置偏低,算法将要消耗比较长的时间。第三,因为每一个中心只选择一个圆,如果有同心圆,就只能选择其中的一个。

<3>因为中心是按照其关联的累加器值的升序排列的,并且如果新的中心过于接近之前已经接受的中心的话,就不会被保留下来。且当有许多同心圆或者是近似的同心圆时,霍夫梯度法的倾向是保留最大的一个圆。可以说这是一种比较极端的做法,因为在这里默认Sobel导数会产生噪声,若是对于无穷分辨率的平滑图像而言的话,这才是必须的。

4.3 HoughCircles( )函数详解

HoughCircles函数可以利用霍夫变换算法检测出灰度图中的圆。它和之前的HoughLines和HoughLinesP比较明显的一个区别是它不需要源图是二值的,而HoughLines和HoughLinesP都需要源图为二值图像。

[cpp]view plaincopyprint?

1.C++: void HoughCircles(InputArray image,OutputArray circles, int method, double

dp, double minDist, double param1=100,double param2=100, int minRadius=0, int

maxRadius=0 )

?第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的灰度单通道图像。

?第二个参数,InputArray类型的circles,经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示。

?第三个参数,int类型的method,即使用的检测方法,目前OpenCV中就霍夫梯度法一种可以使用,它的标识符为CV_HOUGH_GRADIENT,在此参数处填这个标识符即可。

?第四个参数,double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。

?第五个参数,double类型的minDist,为霍夫变换检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小的话,多个相邻的圆可能被错误地检测成了一个重合的圆。反之,这个参数设置太大的话,某些圆就不能被检测出来了。

?第六个参数,double类型的param1,有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny 边缘检测算子的高阈值,而低阈值为高阈值的一半。

?第七个参数,double类型的param2,也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。

?第八个参数,int类型的minRadius,有默认值0,表示圆半径的最小值。

?第九个参数,int类型的maxRadius,也有默认值0,表示圆半径的最大值。

需要注意的是,使用此函数可以很容易地检测出圆的圆心,但是它可能找不到合适的圆半径。我们可以通过第八个参数minRadius和第九个参数maxRadius指定最小和最大的圆半径,来辅助圆检测的效果。或者,我们可以直接忽略返回半径,因为它们都有着默认值0,单单用HoughCircles函数检测出来的圆心,然后用额外的一些步骤来进一步确定半径。

依然是为大家准备了基于此函数的示例程序:

[cpp]view plaincopyprint?

1.//-----------------------------------【头文件包含部分】---------------------------------------

2.// 描述:包含程序所依赖的头文件

3.//----------------------------------------------------------------------------------------------

4.#include

5.#include

6.

7.//-----------------------------------【命名空间声明部分】

---------------------------------------

8.// 描述:包含程序所使用的命名空间

9.//----------------------------------------------------------------------------------------------

-

https://www.doczj.com/doc/a64362425.html,ing namespace cv;

11.//-----------------------------------【main( )函数】

--------------------------------------------

12.// 描述:控制台应用程序的入口函数,我们的程序从这里开始

13.//----------------------------------------------------------------------------------------------

-

14.int main( )

15.{

16. //【1】载入原始图和Mat变量定义

17. Mat srcImage = imread("1.jpg"); //工程目录下应该有一张名为1.jpg的素材图

18. Mat midImage,dstImage;//临时变量和目标图的定义

19.

20. //【2】显示原始图

21. imshow("【原始图】", srcImage);

22.

23. //【3】转为灰度图,进行图像平滑

24. cvtColor(srcImage,midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图

25. GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );

26.

27. //【4】进行霍夫圆变换

28. vector circles;

29. HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 );

30.

31. //【5】依次在图中绘制出圆

32. for( size_t i = 0; i < circles.size(); i++ )

33. {

34. Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));

35. int radius = cvRound(circles[i][2]);

36. //绘制圆心

37. circle( srcImage, center, 3, Scalar(0,255,0), -1, 8, 0 );

38. //绘制圆轮廓

39. circle( srcImage, center, radius, Scalar(155,50,255), 3, 8, 0 );

40. }

41.

42. //【6】显示效果图

43. imshow("【效果图】", srcImage);

44.

45. waitKey(0);

46.

47. return 0;

48.}

运行截图:

五、源码部分

以一般化视角串联霍夫变换(hough transform),从直线到圆再到广义霍夫变换

计算机视觉中经常需要识别或者定位某些几何图形,比如直线、圆、椭圆,还有其他一些图形。检测直线的霍夫变换提供了在图像中寻找直线的一种算法,是最简单的一种情形,后来发展到检测圆、椭圆、还有一般图形的霍夫变换,其核心思想是把图像中属于某种图形的点集(二维)映射到一个点(可以是高维)上,这个点记录了点集中点的数目,使得程序通过搜索峰值找到该点,这个点就是后面要说到的图形的参数,而该参数的范围就叫做参数空间。霍夫变换不仅能够识别出图像中有无需要检测的图形,而且能够定位到该图像(包括位置、角度等),这就非常有用了。接下来将通过分析从简单到复杂的霍夫变换,导出霍夫变换的实质。 直线:检测直线的霍夫变换使用含极坐标参数的直线表示型式简称极坐标式(不是极坐标方程, 因为还是在笛卡尔坐标下表示)—— 其中的两个参数的意义如下图: 为什么要用极坐标式而不直接用一般形式:ax+by=c(归一化可以去掉参数c),或者其他的如斜截式、截距式呢?首先它们都会遇到奇异情况,比如c=0,斜率=无穷大,其中一个截距=0;再一个是某些形式的参数空间不是闭的,比如斜截式的斜率k,取值范围从0到无穷大,给量化搜索带来了困难。而极坐标式就妙在距离和角度两个参数都是有界的,而且正余弦函数也有界不会发生奇异情况。 直线霍夫变换有两个参数,且这两个参数通过极坐标式相关联,所以程序在投票阶段(图形点集转换到一个点)只需要遍历其中一个,搜索峰值在二维参数空间进行。

圆:霍夫变换检测圆使用圆的标准式就可以了 —— 我们发现圆的方程又比直线多了一个参数,这三个参数通过上面的方程相关联,因此在投票阶段需要遍历其中两个,搜索峰值在三维参数空间进行。如果图像比较大,那么这样的遍历搜索是相当耗时的,所以为了满足实时性后来又发展出其他检测圆的霍夫变换,比如概率霍夫变换,结合梯度信息的霍夫变换。 霍夫变换检测椭圆如果使用椭圆的标准式,那么将会有五个参数,它们通过标准式相关,检测圆就已经相当耗时了,如果再用这中方程形式处理势必失去实际用途。 Ballard (1981) 一般化了霍夫变换(Hough,1962),利用图形梯度量加快算法速度,形成了一般霍夫变换。 透过前面的检测直线、圆、一般霍夫变换,已经可以提取出霍夫变换的一个本质——给出图形的一个描述模式,比如图形点集的方程、函数、表格等,然后利用这个模式加上遍历参数空间,把属于该模式的图形点集投射到参数空间的一个点(实际的离散情况一般不会完美的集中到一点),这个点记录的是图形点数目。 一般霍夫变换之所以能处理任意形状的图形并不是找到了可以表示任意图形的方程(这是不可能的),而是使用表的形式描述一种图形,把图形边缘点坐标保存在一张表中,那么该图形就确定下来了,所以其实无论是直线(其实是线段)、圆、椭圆还是其他形状的几何图形,都可以使用同一方法处理,所不同的是这时候的图形是自定义的,是实在的,而代数方程表示的模式是连续的、抽象的,圆的方程只有一种,但自定义的圆却是无穷的,只要你认为它足够圆了就可以。当然两种表示都会有各自的优势和局限。有了表之后就需要找到一种可以把图形点集投射到参数空间的一点的转换算法,例如直线和圆霍夫变换通过方程(函数)及遍历把点集进行投射,使得属于某直线或圆的点集中到一个点;那么仅有一张描述图形边缘坐标点的表如何进行投射呢?我们可以把这张表看作是模板,进行模板匹配,大部分的点匹配成功也就可以理解为这些点都投射到一个点上,不过这时候不需要再搜索参数空间峰值了,这种模式可以认为是参数间没有任何关联,所以是完全的遍历。但有旋转加上缩放的情况模板匹配型的霍夫变换是十分耗时的,也可以想象成因为参数不相关所以增加遍历搜索时间。Ballard (1981) 的一般霍夫变换最精妙之处在于为参数增加了两个关联,使得有平移和旋转(无缩放)的情况只需要遍历一个参数,三个参数分别是图形的中心坐标(横纵),旋转角度(相对参考图形),Ballard 的算法预先把参考图形边缘点对中心的径向量保存起来,利用待搜索图形边缘点的梯度方向(用相对坐标轴的角度表示)作为索引找到相应的径向量,加上该量后就完成了投射,所以要遍历的参数只有旋转角度,所以说有两个关联。当然如果加上缩放就要遍历两个参数,这也只是和霍夫检测圆的规模一样而已。这种一般霍夫变换的图形表不再是直接保存坐标,而是边缘点的梯度加上径向量,还有一个中心坐标,给出了这些量同样的也就能够表示出一种图形了。然而这种一般霍夫变换也是有缺陷的,不少后来者提出了改进方法,这不在本文讨论范围。 再来强调一次,霍夫变换就是通过图形的一种表示模式,加上一种转换方法,把图形的点集投射到一个点上以便检测。我们已经能够知道,参数个数越少,需要遍历的参数个数约少(关联越多),参数空间越小则处理速度越快。所以设计一种合理的转换方法非常关键。

霍夫变换

‘IEEE Transactions on Pattern Recognition And Machine Intelligence’ ‘IEEE Transactions on Image Processing’ 是最重要的两本,其它的如ICCV、CVPR、ECCV、NIPS、BMVC等的会议文章也非常好。 最小二乘线性拟合算法、随机霍夫变换、局部霍夫变换、 canny算子边缘检测、图像增强 霍夫变换 霍夫变换(Hough Transform)是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。主要用来从图像中分离出具有某种相同特征的几何形状(如,直线,圆等)。最基本的霍夫变换是从黑白图像中检测直线(线段)。 详细内容 我们先看这样一个问题:设已知一黑白图像上画了一条直线,要求出这条直线所在的位置。我们知道,直线的方程可以用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(2,2)。可以求出,过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平面上的一条曲线上。其它的还是一样。 应用实例1

【CN109948470A】基于霍夫变换的停车线距离检测方法及系统【专利】

(19)中华人民共和国国家知识产权局 (12)发明专利申请 (10)申请公布号 (43)申请公布日 (21)申请号 201910154827.0 (22)申请日 2019.03.01 (71)申请人 武汉光庭科技有限公司 地址 430000 湖北省武汉市东湖新技术开 发区凤凰园三路一号 (72)发明人 苏晓聪 杨颖  (74)专利代理机构 武汉河山金堂专利事务所 (普通合伙) 42212 代理人 胡清堂 (51)Int.Cl. G06K 9/00(2006.01) G06K 9/46(2006.01) (54)发明名称基于霍夫变换的停车线距离检测方法及系统(57)摘要本发明所述一种基于霍夫变换的停车线距离检测方法及系统,其无需依靠GPS信号或GPS信息的定位,只需要在要停车的位置在地面画一条等宽的白色横线,利用相机检测离地面白色横线,采用图像像素与距离遍历的方式拟合成一个距离多项式,计算出所标记横线中间距离当前车辆参考点的垂直距离,并以一定帧率将该线离车辆的垂直距离发送给控制系统,为该系统在倒车最后停车时提供一个较为精准的停车位置点,从而达到精准倒车的目的;其计算简单,但计算结果精确,既达到了与控制系统联调实现±10cm的停车精度,又避免了通过复杂的步骤计算相机姿 态从而获得距离。权利要求书3页 说明书7页 附图6页CN 109948470 A 2019.06.28 C N 109948470 A

1.一种基于霍夫变换的停车线距离检测方法,其特征在于,所述基于霍夫变换的停车线距离检测方法包括以下步骤: S1、在停车位的倒车终点位置画一条相对于倒车方向垂直的停车线,并在车体上安装相机,所述相机与地面形成一定倾角,使得车辆最后停止区域在相机垂直照射区域内; S2、用相机拍摄已知大小的棋盘图,对拍摄得到的棋盘图像按像素值位置进行图像遍历,把像素位置定义为自变量,实际位置距离定义为因变量,通过计算自变量与因变量的对应关系找到距离拟合多项式; S3、在车辆自动倒车时,相机实时采集彩色图像,通过直线段角度阈值和纵坐标方向像素距离阈值对采集的彩色图像进行干扰区域筛选,将直线段定位到停车线区域; S4、根据停车线上当前像素点和周围邻域间像素关系来区分检测结果是停车线的上沿还是下沿,根据上沿或下沿的位置确定停车线中间位置到相机的垂直距离; 其中, 所述距离拟合多项式的具体公式如下: 上式中,u,v为棋盘格角点的像素位置,x,y为棋盘格角点与相机之间的实际位置距离,P ij 、q ij 为拟合多项式的参数。 2.根据权利要求1所述基于霍夫变换的停车线距离检测方法,其特征在于,所述步骤S2包括以下分步骤: S21、选一个能覆盖相机垂直视野的棋盘格,将棋盘格的最底部边沿放置在相机的最下沿视野; S22、用安装在车体上的相机拍摄棋盘图,将棋盘中的角点提取出来并标定各角点的物理坐标值; S23、将多个角点的物理坐标值作为自变量,棋盘格角点的实际位置距离作为因变量拟合得到的一个二元二次的距离拟合多项式; S24、量出棋盘格左上角点到相机的物理垂直距离,将测量物理垂直距离作为多项式的常量相加即为图像上在任意像素点的位置与相机之间的垂直方向物理距离。 3.根据权利要求1所述基于霍夫变换的停车线距离检测方法,其特征在于,所述步骤S3包括以下分步骤: S31、在车辆自动倒车时,相机实时采集彩色图像,将彩色图像转换为灰度图像,并对图像使用坎尼算子来检测图像所有边缘; S32、在检测到边缘区域后,用累积霍夫变换来获取直线段候选区域; S33、通过直线段的斜率来保留图像中的横向直线段,并保留纵坐标上离相机最近的一个直线段; S34、将得到的直线段转换为点集,并将同一行上的点集集中起来用最小二乘法拟合成一条直线段,得到停车线的两条边沿直线。 4.根据权利要求1所述基于霍夫变换的停车线距离检测方法,其特征在于,所述步骤S4 权 利 要 求 书1/3页2CN 109948470 A

图像处理之霍夫变换

图像处理之霍夫变换(直线检测算法) 霍夫变换是图像变换中的经典手段之一,主要用来从图像中分离出具有某种相同特征的几何 形状(如,直线,圆等)。霍夫变换寻找直线与圆的方法相比与其它方法可以更好的减少噪 声干扰。经典的霍夫变换常用来检测直线,圆,椭圆等。 霍夫变换算法思想: 以直线检测为例,每个像素坐标点经过变换都变成都直线特质有贡献的统一度量,一个简单 的例子如下:一条直线在图像中是一系列离散点的集合,通过一个直线的离散极坐标公式, 可以表达出直线的离散点几何等式如下: X *cos(theta) + y * sin(theta) = r 其中角度theta指r与X轴之间的夹角,r为 到直线几何垂 直距离。任何在直线上点,x, y都可以表达,其中r,theta是常量。该公式图形表示如下: 然而在实现的图像处理领域,图像的像素坐标P(x, y)是已知的,而r, theta则是我们要寻找 的变量。如果我们能绘制每个(r, theta)值根据像素点坐标P(x, y)值的话,那么就从图像笛卡

尔坐标系统转换到极坐标霍夫空间系统,这种从点到曲线的变换称为直线的霍夫变换。变换 通过量化霍夫参数空间为有限个值间隔等分或者累加格子。当霍夫变换算法开始,每个像素 坐标点P(x, y)被转换到(r, theta)的曲线点上面,累加到对应的格子数据点,当一个波峰出现 时候,说明有直线存在。同样的原理,我们可以用来检测圆,只是对于圆的参数方程变为如 下等式: (x –a ) ^2 + (y-b) ^ 2 = r^2其中(a, b)为圆的中心点坐标,r圆的半径。这样霍夫的参数空间就 变成一个三维参数空间。给定圆半径转为二维霍夫参数空间,变换相对简单,也比较常用。 编程思路解析: 1. 读取一幅带处理二值图像,最好背景为黑色。 2. 取得源像素数据 3. 根据直线的霍夫变换公式完成霍夫变换,预览霍夫空间结果 4. 寻找最大霍夫值,设置阈值,反变换到图像RGB值空间(程序难点之一) 5. 越界处理,显示霍夫变换处理以后的图像 关键代码解析: 直线的变换角度为[0 ~ PI]之间,设置等份为500为PI/500,同时根据参数直线参数方程的取值 范围为[-r, r]有如下霍夫参数定义: [java]view plaincopy 1.// prepare for hough transform 2.int centerX = width / 2; 3.int centerY = height / 2;

霍夫变换检测直线圆流程+

Hough 变换直线检测是直接按照hough 变换的定义来进行的, 算法如下: 1) 对原始的图像进行二值化, 假设0代表背景, 1代表物体特征点; 2) 在参数空间ρ, θ里建立一个累加的数组[],H ρθ , 并且置数组H 中的每 一个元素的初值都为零; 对于二值图像中每个以1 表示的点(,)x y , 我们让θ取遍θ轴上所有可能的值, 并根据式(3-3)计算对应的ρ; 再根据ρ与θ的值(假设都已经取整) 对数组进行累加计算([][],,1H H ρθρθ=+) ; 3) 然后对数组[],H ρθ 进行局部的峰值检测, 得到被检测直线的参数ρ和θ。上述的算法受直线中的间隙与噪声的影响较小, 鲁棒性比较强,但其具有运算量太大的缺点, 极端情况下, 它的运算复杂度为3 ()n ο 。 传统随机hough 变换的具体算法如下: (a)构造一个边缘点集D , 然后初始化参数单元集P NULL = ,循环的次数K = 0 ; (b)从D 中随机的选取3 个点; (c)由这3个点解特征的参数p ; (d)在P 中寻找一个c p ,使它满足p c p δ-≤,如果找到则转(f);否则就转(e); (e)将p 插入到P 中,其对应的计数值变为1,转(g); (f)将c p 所对应的计数的值加1,如果小于指定阈值t N ,转(g);否则就转(h); (g)1k k =+;如果 max k k > ,则结束;否则,转(b); (h)c p 是候选圆的特征参数,如果该参数对应圆上的边缘的点数min pc M M >,转(i); (i) c p 是真实的圆参数,把落在参数c p 对应的特征上的点从D 中去除,然 后判断已经检测到的圆的数目是否已达到规定的数目,若是就结束,否 则的话重置P NULL =,0K =,转(b)。 其中max k 是规定的检测一个圆的过程中所允许采样的最大的循环次数。min M 为圆所必需的最小的点数, 通常设为2r πλ,其中λ是一个固定系数,r 是候选圆的半径。P 是参数空间中的参数单元的集合,它是一个动态的链表结构。pc M 是图像空间中落到了候选圆上的点数。

霍夫变换检测圆和直线

霍夫变换检测任意形状 一、实验目的 1.掌握MATLAB软件的使用,以及其设计流程; 2.掌握霍夫变换的实现方法; 3.用MATLAB语言设计基于霍夫变换的任意图形的识别。 二、实验仪器或设备 装MATLAB软件的微机一台 三、总体设计原理及流程图 1、程序设计的原理 霍夫变换的基本思想就是把图像平面上的点对应到参数平面上的曲线,最后通过统计特性来解决问题。具有良好的抗噪声性能和对部分遮盖的不敏感等特性。 2、程序流程图

四、主要程序代码 1、霍夫变换检测圆程序 clear all; close all; clc; % [cr,st]=circle_product;%st(1)->x,st(2)->y,st(3)->r cr=imread('sample.bmp');%circle1.bmp figure; imshow(cr); [row,range]=size(cr); p=row*range;a=0;Y=zeros(1,p);Q=zeros(1,p); for k1=1:1:row for k2=1:1:range if cr(k1,k2)==0 a=a+1; XXX=k2-1;YYY=row+1-k1; Y(a)=YYY;Q(a)=XXX; end end end for k3=1:1:p if Y(k3)==0&Q(k3)==0 break; end end % z=ones(1,5); % a=1:1:300;b=1:1:300; % z1=sqrt((a-Q(1)).^2+(b-Y(1)).^2); % z2=sqrt((a-Q(2)).^2+(b-Y(2)).^2); % z3=sqrt((a-Q(3)).^2+(b-Y(3)).^2); % z4=sqrt((a-Q(4)).^2+(b-Y(4)).^2); % z5=sqrt((a-Q(5)).^2+(b-Y(5)).^2); % % z1=sqrt((a-Q(1))*(a-Q(1))+(b-Y(1))*(b-Y(1))); % % Z1=(a-Q(1)).^2+(b-Y(1)).^2; r0=(abs(z1-z2)<=0.1&abs(z1<=z3)<=0.1&abs(z1<=z4)<=0.1&abs(z1<=z5)<=0.1&abs(z2<=z3)< =0.1&abs(z2<=z4)<=0.1&abs(z2<=z5)<=0.1); % r=r0.*z1; % aa=r0.*a; % bb=r0.*b; % rrr=round(r(r0~=0)) % aaa=aa(r0~=0) % bbb=bb(r0~=0) k7=floor(k3/6);k5=2; a=1:1:300;b=1:1:300;rrr=zeros(1,p);aaa=zeros(1,p);bb=zeros(1,p);k6=0;as=0;k11=1; for k5=1:1:k7

霍夫变换

霍夫变换

标准霍夫变换 1.C++: void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 ) 第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。 第二个参数,InputArray类型的lines,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示,其中,是离坐标原点((0,0)(也就是图像的左上角)的距离。是弧度线条旋转角度(0~垂直线,π/2~水平线)。 第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。PS:Latex中/rho就表示。 第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。 第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。 第六个参数,double类型的srn,有默认值0。对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn。 第七个参数,double类型的stn,有默认值0,对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srn和stn同时为0,

霍夫变换+最小二乘法 直线检测

霍夫变换中直线拟合的最小二乘法 ichriZ 1.基本概念 (1)霍夫变换 霍夫变换(Hough Transform) 是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。最基本的霍夫变换是从黑白图像中检测直线或线段。 (2)最小二乘法 曲线拟合方法的一种,通过最小化误差的平方和寻找数据的最佳函数匹配。 2.适用情况 霍夫变换是基于统计的方法,能将图像中的噪声或干扰点的影响消除,但其结果存在精度不够与直线有效区间不易控制的问题;最小二乘法是直线拟合的有效方法,但直接用于拟合时易受干扰点或噪声点影响。在检测图像中的直线段时,先利用霍夫变换消除无效点的影响,再结合最小二乘法法进行拟合,可以提高检测效果。 3.霍夫变换原理与实现方法 (一)霍夫变换原理 在平面直角坐标系中一条直线,任取其上一点,有 表示参数平面中的一条直线。再取上另一点则有 表示参数平面中的一条直线。与相交于一点,对应于坐标系 中直线 即:同一直线上的不同的点在对应的参数平面中对应不同的直线,但都交于同一点,所以可以通过坐标系中的交点来寻找坐标系中的直线。当坐标系中的直 线数量为R时,坐标系中对应R个峰值交点,它们对应于坐标系中的R 条直线。 此种方法不能够表示这类直线,实际中常将原有直线表示为参数方程 此直线上的点对应坐标系中的一族三角函数曲线,它们在有效区间内交于一点

,对应于坐标系中的。下图是一个具体例子: 交点坐标 (二)最小二乘法原理 对于给定数据,要求在某个函数类 中寻求一个函数 ,使 本文中讨论的是直线的最小二乘法,故均取一次多项式。 设具有如下格式 霍夫变换—>

霍夫变换函数

霍夫变换函数:hough;houghpeaks;houghlines(1) (2014-03-31 11:50:36) 转载▼ 分类:matlab 图像处理工具箱提供了三个与霍夫变换有关的函数。函数hough实现了前面讨论的概念,函数houghpeaks寻找霍夫变换的峰值(累加单元的高计数),函数houghlines以来自其他两个函数的结果为基础在原始图像中提取线段。 1. 函数hough 函数hough支持任意的默认语法: [H, theta, rho] = hough(f) 还支持完整的语法形式: [H, theta, rho] = hough(f, 'ThetaRes', val1, 'RhoRes', val2) 其中,H是霍夫变换矩阵,theta(以度计)和rho是ρ和θ值向量,在这些值上产生霍夫变换。输入f是二值图像,val1是0到90的标量,指定了沿θ轴霍夫变换的间距(默认是1),val2是0 例10.5 霍夫变换的说明 在这个例子中,我们用简单的合成图像来说明hough函数的机理:>> f = zeros(101, 101); >> f(1, 1) = 1; f(101, 1) = 1; f(1, 101) = 1; >> f(101, 101) = 1; f(51, 51) = 1; 图10-10(a)显示了我们的测试图像,下面使用默认值计算并显示霍夫变换的结果:

>> H = hough(f) >> Imshow(H,[]) 图10-10(b)显示了结果,以熟悉的方法使用imshow函数来显示。在带有标度轴的较大图中显现霍夫变换常常更有用。 在接下来的代码片段中,我们调用带有三个参数的hough函数。然后把向量theta和rho作为附加输入参量传递给imshow,从而控制水平轴和垂直轴的标度。我们还要把'InitialMagnification'选项传递给带有值'fit'的imshow函数,因此,整个图像将被强迫在图形窗口中进行装配。axis 函数被用来打开轴标记,并使其显示填充图的矩形框。最后,xlabel和ylabel函数(见2.3.1节)用希腊字母LaTeX字体符号在轴上标值: >> [H, theta, rho] = hough(f); >> imshow(H, [], 'XData', theta, 'YData', rho ,'InitialMagnification', 'fit') >> axis on, axis normal >> xlabel('\theta'), ylabel('\rho') 图10-10(c)显示了标上值之后的结果。三条曲线(直线也可考虑为曲线)在±45°处的交点指出:f中有两组三个共线的点。两条曲线在 (ρ,θ)=(0,-90)、(-100,-90)、(0,0)和(100,0)处的交点指出:有4组位于垂直线和水平线上的共线点。

霍夫变换

3.3.3 提取图形区域(Extracting Graphic Region ) 图形的描述相对较复杂,考虑到文档图象中常见的图形主要是直线,因此我们在实际处理中仅检测各方向的直线。 由于在文档的光电转换中,如扫描等,常会出现图象倾斜,Stuart 等[30]指出,进行倾斜校正会使压缩比提高1%左右,因此有必要对倾斜的图象进行校正。同时,使原本水平和竖直的直线更加容易发现。此外,在图象中除了水平和竖直的直线外,通常还会出现其它方向的直线。为了能够检测到不是水平或竖直的直线,我们需要构造具有一定方向性的形态学算子。在本文中,我们检测图象中的各直线段方向,然后构造相应的结构元素将其检测出。 (1) HOUGH 变换 在检测直线中,很容易想到利用Hough 变换[60]。下面简单介绍Hough 变换。 直线y = mx + b 可用极坐标表示为: )sin()cos(θθy x r +=,也可表示为: y x tg y x r =++= )()sin(2 2??θ,其中 式(3.15) 其中,(r ,θ)定义了一个从原点到该直线最近点的向量,显然,这个向量与该直线垂直。如图3.7所示。 图3.7 直线的极坐标表示 Fig3.7 Polar Coordinates of a line 考虑一个以参数r 和θ构成的二维空间。x,y 平面的任意一直线对应了r,θ平面上的一个点。因此,x,y 平面上的任意一直线的Hough 变换是r, θ平面上的一个点。 现在考虑x,y 平面的一个特定的点(x 0,y 0)。过该点的直线可以有很多,每一条都对应了r, θ空间中的一个点。然而这些点必须是满足以x 0,y 0作为常量时

基于matlab的霍夫变换

基于matlab的霍夫变换 一、简单介绍 Hough变换是图像处理中从图像中识别几何形状的基本方法之一。Hough变换的基本原理在于利用点与线的对偶性,将原始图像空间的给定的曲线通过曲线表达形式变为参数空间的一个点。这样就把原始图像中给定曲线的检测问题转化为寻找参数空间中的峰值问题。也即把检测整体特性转化为检测局部特性。比如直线、椭圆、圆、弧线等。 二、基本原理 Hough变换的基本原理在于,利用点与线的对偶性,将图像空间的线条变为参数空间的聚集点,从而检测给定图像是否存在给定性质的曲线(圆的方程为:(x-a)^2+(y-b)^2=r^2,通过Hough变换,将图像空间对应到参数空间)。 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。最基本的霍夫变换是从黑白图像中检测直线(线段)。 三、hough变换检测直线 设已知一黑白图像上画了一条直线,要求出这条直线所在的位置。我们知道,直线的方程可以用y=k*x+b 来表示,其中k和b是参数,分别是斜率和截距。过某一点(x0,y0)的所有直线的参数都会满足方程y0=kx0+b。即点 (x0,y0)确定了一族直线。方程y0=kx0+b在参数k--b平面上是一条直线,(你也可以是方程b=-x0*k+y0对应的直线)。如下图1所示: 从图1中可看出,x-y坐标和k-b坐标有点----线的对偶性。x-y坐标中的点P1、P2对应于k-b坐标中的L1、L2;而k-b坐标中的点P0对应于x-y坐标中的线L0 。 这样,图像x--y平面上的一个前景像素点就对应到参数平面上的一条直线。我们举个例子说明解决前面那个问题的原理。设图像上的直线是y=x, 我

霍夫变换

霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。最基本的霍夫变换是从黑白图像中检测直线(线段)。 我们先看这样一个问题: 设已知一黑白图像上画了一条直线,要求出这条直线所在的位置。 我们知道,直线的方程可以用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)。这个性质就为我们解决问题提供了方法: 1.首先,我们初始化一块缓冲区,对应于参数平面,将其所有数据置为0. 2.对于图像上每一前景点,求出参数平面对应的直线,把这直线上的所有点 的值都加1。 3.最后,找到参数平面上最大点的位置,这个位置就是原图像上直线的参数。 上面就是霍夫变换的基本思想。就是把图像平面上的点对应到参数平面上的线,最后通过统计特性来解决问题。假如图像平面上有两条直线,那么最终在参数平面上就会看到两个峰值点,依此类推。 在实际应用中,y=k*x+b形式的直线方程没有办法表示x=c形式的直线(这时候,直线的斜率为无穷大)。所以实际应用中,是采用参数方程 p=x*cos(theta)+y*sin(theta)。这样,图像平面上的一个点就对应到参数 p---theta平面上的一条曲线上。其它的还是一样。 再看下面一个问题: 我们要从一副图像中检测出半径以知的圆形来。这个问题比前一个还要直观。我们可以取和图像平面一样的参数平面,以图像上每一个前景点为圆心,以已知的半径在参数平面上画圆,并把结果进行累加。最后找出参数平面上的峰值点,这个位置就对应了图像上的圆心。 在这个问题里,图像平面上的每一点对应到参数平面上的一个圆。 把上面的问题改一下,假如我们不知道半径的值,而要找出图像上的圆来。这样,一个办法是把参数平面扩大称为三维空间。就是说,参数空间变为x--y--R三维,对应圆的圆心和半径。图像平面上的每一点就对应于参数空间中每个半径下的一个圆,这实际上是一个圆锥。最后当然还是找参数空间中的峰值点。不过,这个

霍夫变换直线检测C++程序代码

霍夫变换直线检测C++程序代码 前段时间想在网上找个现成的霍夫变换直线检测的C++程序,发现找到的都是调用OpenCV 库函数来实现的,都不能用,没办法,回头只能自己写了。具体代码如下,如有问题还请多多指教!个人百度空间:https://www.doczj.com/doc/a64362425.html,/new/zxw080800 // 接口参数描述 // pImg ----待检测图片指针 // width----图像宽 // height---图像高 // k----------返回检测到的直线的斜率 // b---------返回检测到的直线的纵截距 // FIT_POINT_PIX_VAL-----用于进行直线检测的拟合点的像素值(预先设定好) void zxwHoughTransform(BYTE *pImg, int width, int height, double &k, double &b) { // 赋初值,检测角度的最大值和最小值 const int MinTheta = 0; const int MaxTheta = 180; int i, j; int w, h; int cosV, sinV; int **count, max, nmax; int theta, thro; // 初始化 nmax = (int)sqrt(width * width + height * height); count = new int * [MaxTheta]; for (i = 0; i < MaxTheta; i++) { count[i] = new int[nmax]; memset(count[i], 0, sizeof(int) * nmax); } // 统计count值 BYTE *pCur = pImg; for(theta = MinTheta; theta < MaxTheta; theta += 1) { cosV = (int)(cos(PI * theta / 180) * 2048); sinV = (int)(sin(PI * theta / 180) * 2048); for(h = 0; h < height; h++) { for(w = 0; w < width; w++) {

相关主题
文本预览
相关文档 最新文档