原图如下:
对图像进行sobely,纵向求出其梯度值,然后从下到上取出第一个最大的值,对这些值的坐标进行最小二乘法来拟合(没有用到scipy库)
附上代码:
import cv2
import numpy as np
import math
orgFrame=None
def gradient(Imask):
global orgFrame
#没有检测到黑白界线,则返回的angle=None
Imask=cv2.flip(Imask,0)
sobely=cv2.Sobel(Imask,cv2.CV_64F,0,1,ksize=5)
_,c=cv2.threshold(abs(sobely), 50, 255, cv2.THRESH_BINARY)#二值化
row,col=c.shape
c=abs(c)
x=np.linspace(0,col-1,col)
x=np.array(x,int)
y=np.array(x)
j=0
for i in range(col):
cy=np.argmax(c[:,i])
if c[cy,i]==255:
y[j]=cy
x[j]=i
j+=1
while True:
if j<i:
np.delete(x,j,0)
np.delete(y,j,0)
j+=1
else:
break
orgFrame=cv2.flip(orgFrame,0)##########################
cv2.line(orgFrame,(x[0],y[0]),(x[-1],y[-1]),(255,0,0),2)###############
orgFrame=cv2.flip(orgFrame,0)
cv2.imshow('o',orgFrame)##########
xmean=x.mean()
ymean=y.mean()
denominator=pow(x,2).mean()-(xmean**2)
if denominator:
k=((x*y).mean()-xmean*ymean)/denominator
#b=ymean-k*xmean
angle =math.atan(k)
angle=float(angle*180/math.pi)
else:
angle=None
print(angle,ymean)
return angle,ymean
orgFrame=cv2.imread('C:\\Users\\YS\\Desktop\\205.jpg')
#orgframe = cv2.resize(orgFrame, (640, 480), interpolation=cv2.INTER_LINEAR)
orgframe=orgFrame
frame = cv2.cvtColor(orgframe, cv2.COLOR_BGR2GRAY)#转化为灰度图像
frame = cv2.GaussianBlur(frame, (3,3), 0)#高斯模糊,去噪
_, Imask = cv2.threshold(frame, 100, 255, cv2.THRESH_BINARY)#二值化
Imask = cv2.erode(Imask, None, iterations=2)
Imask = cv2.dilate(Imask, np.ones((8, 8), np.uint8), iterations=2)
cv2.imshow('1',Imask)
gradient(Imask)
cv2.waitKey(0)
Imask图如下:
拟合的直线如下: