3.霍夫曼求直线原理与代码(python)

一、原理

我们常用的直线方程是y=kx+b

对这个公式移项后得到b=y-kx

3.霍夫曼求直线原理与代码(python)_第1张图片

        其实,当k,b确定时,这条直线就确定了。我对霍夫曼求直线的理解是:在一个二维平面上有很多个点,然后对k,b取不同的值时得到不同的直线,查看二维平面上有多少个点落到不同的直线上,比如:

k,bk_{1},b_{1},时平面上有5个点满足直线方程y=k_{1}x+b_{1}

k,bk_{2},b_{2},时平面上有8个点满足直线方程y=k_{2}x+b_{2}

k,bk_{3},b_{3},时平面上有2个点满足直线方程y=k_{3}x+b_{3}

        此时我们如果定义至少有4个点在直线上时才能确定为直线,那么我们就将第三种情况排除了,因为它只有两个已知点满足第三种情况的直线。

       当然,我们也可以知道,上面第二种情况的直线满足的点的个数最多,第一种情况也满足大于4个点,那我们获得的直线是不是就两条呢,这个还不确定,我们可以再加个条件,就是获得的直线之间的距离最小是3.这个时候我们还需要计算两条直线的距离,如果距离小于3,那么最后的直线只有一条,即第二种情况的直线;如果距离大于3,则两条直线都是我们需要的直线。

       我们了解了求直线的原理,而霍夫曼直线不是直接这样求的,他是怎么求的呢,可以说是用了移向后的公式b=y-kx

       大家知道,这个公式的k=tan\theta =\frac{sin\theta }{cos\theta }

       代入直线公式上面公式得b=-\frac{sin\theta }{cos\theta }x+y

       根据上面原理可以知道,我们是通过对k,b取不同的值求直线的,那么当我们对k,b取一组值后,上式中的b,\theta就成了常数,既然是常数,那么我也可以把-\frac{sin\theta }{cos\theta }设成\frac{cos\theta }{sin\theta },相当于对k做了一次变换,只是最后写直线的时候还原回来就行。那么做完这种变换后上式就变为

b=\frac{cos\theta }{sin\theta }x+y

       上式的两边同时乘以sin\theta得:bsin\theta =xcos\theta +ysin\theta

       bsin\theta是个常数,令r=bsin\theta

r =xcos\theta +ysin\theta

       经过上述的变换后,我们就对k,b取不同值时求直线转换为对r,\theta取不同值时求直线。当然,保留直线的原理和上面相同。

      原理就说到这里了,如果大家觉得哪里有问题或不理解,可以评论区讨论。

二、代码

在这里,直接看别人的霍夫曼直线代码了,博文地址为OpenCV-Python 霍夫变换 检测直线,圆形_python opencv 环形文字拉直-CSDN博客

大家也可以根据原理自己写代码。代码如下:

"""
cv2.HoughLines()
	dst:   输出图像. 它应该是个灰度图 (但事实上是个二值化图)
	lines: 储存着检测到的直线的参数对 (r,\theta) 的容器 
	rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.
	theta: 参数极角 \theta 以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
	threshold:    设置阈值: 一条直线所需最少的的曲线交点
	srn and stn:  参数默认为0

cv2.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]  #第一个元素是距离rho
	theta= line[0][1] #第二个元素是角度theta
	print (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()

你可能感兴趣的:(7.数据处理,算法,机器学习,人工智能)