Python OpenCV -- 霍夫线变换(十二)

转载 2018年04月15日 11:15:43

霍夫线变换

  1. 霍夫线变换是一种用来寻找直线的方法.

  2. 是用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像.


实现:

  1.  一条直线在图像二维空间可由两个变量表示. 例如:
       a.  在 笛卡尔坐标系: 可由参数: (m,b) 斜率和截距表示.
       b.  在 极坐标系: 可由参数: (r,\theta) 极径和极角表示

                                                                       

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

                                                                       

             化简得: r = x \cos \theta + y \sin \theta

 2.  一般来说对于点 (x_{0}, y_{0}), 我们可以将通过这个点的一族直线统一定义为:

                                          r_{\theta} = x_{0} \cdot \cos \theta  + y_{0} \cdot \sin \theta

    这就意味着每一对 (r_{\theta},\theta) 代表一条通过点 (x_{0}, y_{0}) 的直线.

3.    如果对于一个给定点 (x_{0}, y_{0}) 我们在极坐标对极径极角平面绘出所有通过它的直线, 将得到一条正弦曲线. 例如, 对于给定点 x_{0} = 8 and y_{0} = 6 我们可以绘出下图 (在平面 \theta - r):

                                                        

       只绘出满足下列条件的点 r > 0 and 0< \theta < 2 \pi.

  4. 我们可以对图像中所有的点进行上述操作. 如果两个不同点进行上述操作后得到的曲线在平面 \theta - r 相交, 这就意味着它们通过同一条直线. 例如, 接上面的例子我们继续对点: x_{1} = 9, y_{1} = 4 和点 x_{2} = 12, y_{2} = 3 绘图, 得到下图:

                                                          

     这三条曲线在 \theta - r 平面相交于点 (0.925, 9.6), 坐标表示的是参数对 (\theta, r) 或者是说点 (x_{0}, y_{0}), 点 (x_{1}, y_{1}) 和点 (x_{2}, y_{2}) 组成的平面内的的直线.

  5. 那么以上的材料要说明什么呢? 这意味着一般来说, 一条直线能够通过在平面 \theta - r 寻找交于一点的曲线数量来 检测. 越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成. 一般来说我们可以通过设置直线上点的 阈值 来定义多少条曲线交于一点我们才认为 检测 到了一条直线.


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


标准霍夫线变换和统计概率霍夫线变换

  a. 标准霍夫线变换

        原理在上面的部分已经说明了. 它能给我们提供一组参数对(\theta, r_{\theta})  的集合来表示检测到的直线

       在OpenCV 中通过函数 HoughLines 来实现


 b . 统计概率霍夫线变换

       这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点 (x_{0}, y_{0}, x_{1}, y_{1})

      在OpenCV 中它通过函数 HoughLinesP 来实现


1. 标准霍夫线变换

    在Python 的 OpenCV版本中 标准霍夫线变换 函数为 cv2.HoughLines。它输入一幅含有点集的二值图(由非0像素表示),其中一些点互相联系组成直线。

通常这通过如 Canny 算子获得的一幅边缘图像。

   cv2.HoughLines 函数输出的是 [ float,float ] 形式的ndarray,其中每个值表示检测到的线(ρ,θ)中浮点值的参数。

示例:

[python] view plain copy
  1. #!/usr/bin/env python    
  2. # encoding: utf-8    
  3. import cv2    
  4. import numpy as np   
  5.   
  6. img = cv2.imread("6.jpg"0)    
  7.     
  8. img = cv2.GaussianBlur(img,(3,3),0)    
  9. edges = cv2.Canny(img, 50150, apertureSize = 3)    
  10.   
  11. #(函数参数3和参数4) 通过步长为1的半径和步长为π/180的角来搜索所有可能的直线  
  12. #118 --是经过某一点曲线的数量的阈值  
  13. lines = cv2.HoughLines(edges,1,np.pi/180,118)  #这里对最后一个参数使用了经验型的值   
  14. result = img.copy()    
  15. for line in lines[0]:   
  16.     rho = line[0#第一个元素是距离rho    
  17.     theta= line[1#第二个元素是角度theta    
  18.     print rho    
  19.     print theta    
  20.     if  (theta < (np.pi/4. )) or (theta > (3.*np.pi/4.0)): #垂直直线    
  21.                 #该直线与第一行的交点    
  22.         pt1 = (int(rho/np.cos(theta)),0)    
  23.         #该直线与最后一行的焦点    
  24.         pt2 = (int((rho-result.shape[0]*np.sin(theta))/np.cos(theta)),result.shape[0])    
  25.         #绘制一条白线    
  26.         cv2.line( result, pt1, pt2, (255))    
  27.     else#水平直线    
  28.         # 该直线与第一列的交点    
  29.         pt1 = (0,int(rho/np.sin(theta)))    
  30.         #该直线与最后一列的交点    
  31.         pt2 = (result.shape[1], int((rho-result.shape[1]*np.cos(theta))/np.sin(theta)))    
  32.         #绘制一条直线    
  33.         cv2.line(result, pt1, pt2, (255), 1)    
  34.     
  35. cv2.imshow('Canny', edges )    
  36. cv2.imshow('Result', result)    
  37. cv2.waitKey(0)    
  38. cv2.destroyAllWindows()    


效果图:


注意:

  在Opencv C++ 版本中,HoughLines 函数得到的结果是一个向量lines, 其中的元素是由两个元素组成的向量(rho , theta),所以 lines 的访问方式类似二维数组

[python] view plain copy
  1. std::vector<cv::Vec2f>::const_iterator it= lines.begin();    
  2. float rho= (*it)[0];    
  3. float theta= (*it)[1];    

 OpenCV Python 版本中,返回的是一个三维的 np.ndarray 。可通过检验HoughLines 返回的 lines 的 ndim 属性得到。
[python] view plain copy
  1. lines = cv2.HoughLines(edges,1,np.pi/180,118)    
  2.   
  3. # 输出结果  
  4. #lines.ndim属性    
  5. (152#lines.shape属性    
  6.     
  7. #lines[0]    
  8. [[  4.20000000e+01   2.14675498e+00]    
  9.  [  4.50000000e+01   2.14675498e+00]    
  10.  [  3.50000000e+01   2.16420817e+00]    
  11.  [  1.49000000e+02   1.60570288e+00]    
  12.  [  2.24000000e+02   1.74532920e-01]]    
  13. ===============    
  14. #lines本身    
  15. [[[  4.20000000e+01   2.14675498e+00]    
  16.   [  4.50000000e+01   2.14675498e+00]    
  17.   [  3.50000000e+01   2.16420817e+00]    
  18.   [  1.49000000e+02   1.60570288e+00]    
  19.   [  2.24000000e+02   1.74532920e-01]]]    


1.概率霍夫变换

   通过上面的例子可以看出,其中 Hough 变换看起来就像在图像中查找对齐的边界像素点集合。但这样会在一些情况下导致虚假检测,如像素偶然对齐或多条直线

穿过同样的对齐像素造成的多重检测。

  要避免这样的问题,并检测图像中分段的直线(而不是贯穿整个图像的直线),由此出现了 概率 Hough 变换(Probabilistic Hough)

Python 版本中 由 cv2.HoughLinesP 实现:

[python] view plain copy
  1. #!/usr/bin/env python    
  2. # encoding: utf-8    
  3. import cv2    
  4. import numpy as np   
  5.   
  6. img = cv2.imread("6.jpg")    
  7.     
  8. img = cv2.GaussianBlur(img,(3,3),0)    
  9. edges = cv2.Canny(img, 50150, apertureSize = 3)    
  10. lines = cv2.HoughLines(edges,1,np.pi/180,118)    
  11. result = img.copy()    
  12.     
  13. #经验参数    
  14. minLineLength = 200    
  15. maxLineGap = 15    
  16. lines = cv2.HoughLinesP(edges,1,np.pi/180,80,minLineLength,maxLineGap)    
  17. for x1,y1,x2,y2 in lines[0]:    
  18.     cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)    
  19.     
  20. cv2.imshow('Result', img)    
  21. cv2.waitKey(0)    
  22. cv2.destroyAllWindows()   

效果图:




本文参考和转载:
代码程序使用 sunny2038 博客所提供
http://blog.csdn.net/sunny2038/article/details/9253823
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html

opencv学习笔记(二十四)霍夫线变换

霍夫变换霍夫变换是一种在图像中寻找直线.、圆及其他简单形状的方法。 原始的霍夫变化是一种直线变换,即在二值图像中寻找直线的一种相对快速方法。变换可以推广到其他普通的情况,而不仅仅是简单的直线。 这...
  • u014751607
  • u014751607
  • 2017-01-20 16:31:04
  • 1084

Opencv学习笔记-----霍夫变换直线检测及原理理解

霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍...
  • ycj9090900
  • ycj9090900
  • 2016-10-27 12:33:38
  • 13136

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

本篇文章中,我们一起探讨了OpenCV中霍夫变换相关的知识点,以及了解了OpenCV中实现霍夫线变换的HoughLines、HoughLinesP函数的使用方法,实现霍夫圆变换的HoughCircle...
  • zhmxy555
  • zhmxy555
  • 2014-05-26 09:19:39
  • 77120

OpenCV霍夫变换系列(前篇)-经典霍夫线变换

最近新来的的我的大学室友(现在也是我的学弟)在研究霍夫线变换,我之前只是知道这玩意可以拿来做直线检测,并没有深入研究,那既然提到了,还是按照我们的老规矩,原理,示例以及OpenCV这一套流程走下来...
  • qq_37059483
  • qq_37059483
  • 2017-09-08 10:21:11
  • 1036

OpenCV学习笔记-霍夫圆变换

霍夫圆变换的函数为:HoughCircles利用 Hough 变换在灰度图像中找圆CvSeq* cvHoughCircles( CvArr* image, void* circle_storage, ...
  • superdont
  • superdont
  • 2011-08-05 22:51:27
  • 13745

python+opencv实现霍夫变换检测直线

python+opencv实现高斯平滑滤波 python+opencv实现阈值分割(2016-5-10)到OpenCV-Python Tutorials’s documentation可以下载功能:...
  • xieyi4650
  • xieyi4650
  • 2016-05-10 11:16:05
  • 3064

opencv学习笔记(二十五)霍夫圆变换

霍夫圆变换与之前所描述的霍夫直线变换是大体上是类似的。说“大体上类似”的原因是——如果想要尝试完全类似——累加平面会被三维的累加容器所代替:在这三维中,一维是x,一维是y,另一维是圆的半径r。这就意味...
  • u014751607
  • u014751607
  • 2017-02-18 10:02:26
  • 722

OpenCV-Python教程(9)(10)(11): 使用霍夫变换检测直线 直方图均衡化 轮廓检测

OpenCV-Python教程(9、使用霍夫变换检测直线) 相比C++而言,Python适合做原型。本系列的文章介绍如何在Python中用OpenCV图形库,以及与C++调用相应OpenCV...
  • GarfieldEr007
  • GarfieldEr007
  • 2016-05-05 21:02:48
  • 3804

OpenCV霍夫系列(后篇)-统计概率霍夫变换(HoughLinesP)

之前我也忽视了这个统计概率霍夫变换-作为霍夫系列的完结篇,今天终于算是结束了。 原理+Samples+源码分析...
  • qq_37059483
  • qq_37059483
  • 2017-09-12 11:41:00
  • 1110

【OpenCV】基于傅立叶变换和霍夫变化的文本倾斜校正

//此函数应用傅立叶变换进行原始图像倾斜校正 IplImage* mycvRotateImage(const IplImage* src) { int op_width = cvGetOpt...
  • hero_myself
  • hero_myself
  • 2015-10-28 23:34:57
  • 1115
收藏助手
不良信息举报
您举报文章:Python OpenCV -- 霍夫线变换(十二)
举报原因:
原因补充:

(最多只允许输入30个字)