霍夫变换直线检测

Posted 双龙路潇洒哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了霍夫变换直线检测相关的知识,希望对你有一定的参考价值。

目录

霍夫变换原理

映射

峰值统计

总结

OpenCv中的霍夫线检测


霍夫变换原理

霍夫变换运用两个坐标空间之间的变换,将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。

可以看出,要搞清楚的主要问题:

  1. 映射
  2. 峰值统计

映射

比如说,当霍夫空间参数为(k,q)时:

在笛卡尔坐标平面(x、y坐标系)中的一条直线(y=kx+q)对应霍夫空间的一个点(k,q)。

反过来同样成立,笛卡尔坐标系中的一个点对应着霍夫空间种的一条直线。

并且经过验证,若笛卡尔坐标系中n点在同一直线上,那么在霍夫空间中n线就交于同一点。

以上就是映射,但是未考虑到完整的情况,如果在笛卡尔坐标系中有线是垂直x轴的(也就是k=∞),那么在霍夫空间中这个点要画到无穷远处去了。因此应对笛卡尔坐标系进行极坐标变换后再霍夫空间参数设为ρ,θ。

可以看出点映射直线,变成了点映射曲线,但是该相交还是相交。

峰值统计

上面已经提到,原坐标系空间中的在一条直线上的点映射成霍夫空间中的一族曲线后交于同一点。

那么峰值统计要统计的就是霍夫空间中每个点被经过的曲线数量。 

为什么?因为当霍夫空间中一个点被经过的曲线越多,那就说明原空间中越多的点在同一条直线上,那就说明这条“直线”是直线的概率越大。(总所周知,直线其实就是无数个点连在一起...)

那怎么统计呢?对霍夫空间进行离散化,然后对网格单元进行检查,累加计数值最大的网格,其坐标值(ρ0, θ0)就对应图像空间中所求的直线。

总结

原理步骤

1. 霍夫变换

2.对每一点统计峰值

3.设置阈值,得到直线

当然你也可以在霍夫变换之前进行平滑去噪、Canny边缘检测等其他操作。

OpenCv中的霍夫线检测

opencv中存在两种方法:

1.霍夫线检测:

lines = cv.HoughLines( image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]] )

  • lines:返回值(ρ,θ),ρ以像素为单位,θ以弧度为单位。
  • rho:累加器的距离分辨率(以像素为单位)。
  • theta:累加器的角度分辨率(弧度)。
  • threshold:阈值,仅大于的才可以被返回。
  • srn:对于多尺度Hough变换,它是距离分辨率rho的除数。粗累加器距离分辨率为rho,精确累加器分辨率为rho/srn。如果srn=0和stn=0,则使用经典Hough变换。否则,这两个参数都应为正值。
  • stn:对于多尺度Hough变换,它是距离分辨率θ的除数。
  • min_theta:对于标准和多尺度Hough变换,检查直线的最小角度。必须介于0和最大θ之间。
  • max_theta:对于标准和多尺度Hough变换,检查直线的最大角度。必须介于min_theta和CV_PI之间。
import cv2
import numpy as np

img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)

lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv2.imwrite('houghlines3.jpg',img)

2.概率霍夫线检测:

lines = cv.HoughLinesP( image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]] ) 

  • lines:返回两个端点的坐标。
  • rho:累加器的距离分辨率(以像素为单位)。
  • theta:累加器的角度分辨率(弧度)。
  • threshold:阈值,仅大于的才可以被返回。
  • minLineLength:最小行长度。小于该长度的线段将被拒绝。
  • maxLineGap:同一直线上连接点的最大允许间距。
import cv2
import numpy as np

img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv2.imwrite('houghlines5.jpg',img)

相关参考:

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

图像直线检测——霍夫线变换

霍夫变换直线检测(Line Detection)原理及示例

以上是关于霍夫变换直线检测的主要内容,如果未能解决你的问题,请参考以下文章

Python OpenCV 霍夫(Hough Transform)直线变换检测原理,图像处理第 33 篇博客

pyhton—opencv直线检测(HoughLines)找到最长的一条线

pyhton—opencv直线检测(HoughLines)找到最长的一条线

CImg霍夫变换——直线检测

图像处理之霍夫变换(直线检测算法)

图像处理之霍夫变换(直线检测算法)