一、原理
我们常用的直线方程是;
对这个公式移项后得到;
其实,当确定时,这条直线就确定了。我对霍夫曼求直线的理解是:在一个二维平面上有很多个点,然后对
取不同的值时得到不同的直线,查看二维平面上有多少个点落到不同的直线上,比如:
取
,时平面上有5个点满足直线方程
;
取
,时平面上有8个点满足直线方程
;
取
,时平面上有2个点满足直线方程
;
此时我们如果定义至少有4个点在直线上时才能确定为直线,那么我们就将第三种情况排除了,因为它只有两个已知点满足第三种情况的直线。
当然,我们也可以知道,上面第二种情况的直线满足的点的个数最多,第一种情况也满足大于4个点,那我们获得的直线是不是就两条呢,这个还不确定,我们可以再加个条件,就是获得的直线之间的距离最小是3.这个时候我们还需要计算两条直线的距离,如果距离小于3,那么最后的直线只有一条,即第二种情况的直线;如果距离大于3,则两条直线都是我们需要的直线。
我们了解了求直线的原理,而霍夫曼直线不是直接这样求的,他是怎么求的呢,可以说是用了移向后的公式。
大家知道,这个公式的,
代入直线公式上面公式得
根据上面原理可以知道,我们是通过对取不同的值求直线的,那么当我们对
取一组值后,上式中的
就成了常数,既然是常数,那么我也可以把
设成
,相当于对k做了一次变换,只是最后写直线的时候还原回来就行。那么做完这种变换后上式就变为
上式的两边同时乘以得:
是个常数,令
得
经过上述的变换后,我们就对取不同值时求直线转换为对
取不同值时求直线。当然,保留直线的原理和上面相同。
原理就说到这里了,如果大家觉得哪里有问题或不理解,可以评论区讨论。
二、代码
在这里,直接看别人的霍夫曼直线代码了,博文地址为OpenCV-Python 霍夫变换 检测直线,圆形_python opencv 环形文字拉直-CSDN博客
大家也可以根据原理自己写代码。代码如下:
"""
cv2.HoughLines()dst: 输出图像. 它应该是个灰度图 (但事实上是个二值化图)lines: 储存着检测到的直线的参数对 (r,\theta) 的容器 rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.theta: 参数极角 \theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)threshold: 设置阈值: 一条直线所需最少的的曲线交点srn and stn: 参数默认为0cv2.HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 )dst: 输出图像. 它应该是个灰度图 (但事实上是个二值化图) lines: 储存着检测到的直线的参数对 (x_{start}, y_{start}, x_{end}, y_{end}) 的容器rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.theta: 参数极角 \theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)threshold: 设置阈值: 一条直线所需最少的的曲线交点。超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃.maxLineGap: 能被认为在一条直线上的两点的最大距离。
"""
import cv2
import numpy as np original_img= cv2.imread("jianzhu.png", 0)
img = cv2.resize(original_img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_CUBIC)img = cv2.GaussianBlur(img,(3,3),0)
edges = cv2.Canny(img, 50, 150, apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,118) #这里对最后一个参数使用了经验型的值
result = img.copy()
for line in lines:rho = line[0][0] #第一个元素是距离rhotheta= line[0][1] #第二个元素是角度thetaprint (rho)print (theta)if (theta < (np.pi/4. )) or (theta > (3.*np.pi/4.0)): #垂直直线pt1 = (int(rho/np.cos(theta)),0) #该直线与第一行的交点#该直线与最后一行的焦点pt2 = (int((rho-result.shape[0]*np.sin(theta))/np.cos(theta)),result.shape[0])cv2.line( result, pt1, pt2, (255)) # 绘制一条白线else: #水平直线pt1 = (0,int(rho/np.sin(theta))) # 该直线与第一列的交点#该直线与最后一列的交点pt2 = (result.shape[1], int((rho-result.shape[1]*np.cos(theta))/np.sin(theta)))cv2.line(result, pt1, pt2, (255), 1) # 绘制一条直线cv2.imshow('Canny', edges )
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()