如题,现在还写不出啥高级的识别,识别车道都还是在截取的目标范围内只有左右各一条车道线才识别是个对的

因为直线拟合的部分用的是最小二乘拟合的,所以想都想得到结果就是 拟歪来

图像识别 曲线形态 图像识别线条_图像识别


图像识别 曲线形态 图像识别线条_二值化_02


目前还没想到好点的办法,想到了再改改把

import cv2
import numpy as np

#读取图像及灰度图像处理
img=cv2.imread('load.png')
p=np.zeros_like(img,np.uint8)
grap=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

#canny边缘化处理
edges=cv2.Canny(grap, 50, 200, 3)
dst=cv2.convertScaleAbs(edges)

#获取图片尺寸
size=img.shape
w=int(size[1])
h=int(size[0])

#根据尺寸获取目标区域
pts=np.array([[0.6*w,0.6*h],[0.4*w,0.6*h],[0.15*w,h],[0.8*w,h]],dtype=np.int32)
cv2.fillConvexPoly(p,pts,(255,255,255))
p=cv2.cvtColor(p,cv2.COLOR_RGB2GRAY)
load=cv2.bitwise_and(p,dst)


#hough变换
minLineLength = 1
maxLineGap = 0
lines = cv2.HoughLinesP(load, 1, np.pi / 180, 10, minLineLength, maxLineGap)

#使用最小二乘法拟合车道线
color=(0,255,0)
thickness=2
left_lines_x = []
left_lines_y = []
right_lines_x = []
right_lines_y = []
line_y_max = 0
line_y_min = 999
for line in lines:
    for x1, y1, x2, y2 in line:
        if y1 > line_y_max:
            line_y_max = y1
        if y2 > line_y_max:
            line_y_max = y2
        if y1 < line_y_min:
            line_y_min = y1
        if y2 < line_y_min:
            line_y_min = y2
        k = (y2 - y1) / (x2 - x1)
        if k < -0.3:
            left_lines_x.append(x1)
            left_lines_y.append(y1)
            left_lines_x.append(x2)
            left_lines_y.append(y2)
        elif k > 0.3:
            right_lines_x.append(x1)
            right_lines_y.append(y1)
            right_lines_x.append(x2)
            right_lines_y.append(y2)
# 最小二乘直线拟合
left_line_k, left_line_b = np.polyfit(left_lines_x, left_lines_y, 1)
right_line_k, right_line_b = np.polyfit(right_lines_x, right_lines_y, 1)

# 根据直线方程和最大、最小的y值反算对应的x
cv2.line(img,
         (int((line_y_max - left_line_b) / left_line_k), line_y_max),
         (int((line_y_min - left_line_b) / left_line_k), line_y_min),
         color, thickness)
cv2.line(img,
         (int((line_y_max - right_line_b) / right_line_k), line_y_max),
         (int((line_y_min - right_line_b) / right_line_k), line_y_min),
         color, thickness)

cv2.imshow('dst',img)
cv2.waitKey(0)

中间有几个让人头疼的函数
HoughlinesP()一定要在末尾加P,加了P,返回的值就是获取的一条线段的首尾两点的坐标(x1,y1),(x2,y2)
Houghlines()不加P的,返回的是两个元素的矢量表示(ρ,Θ),其中ρ是离坐标原点((0,0)(也就是图像的左上角)的距离。 Θ是弧度线条旋转角度。

HoughLinesP(image,rho,theta,threshold,minLineLength=0,maxLineGap=0 )

之后就是参数问题,Houghlines()我觉得是不太好用的,但有时说不定还行
1、HoughLinesP()第一个参数和Houghlines()是一样的,image,一个图片,这里必须是二值化后的图片(我的理解,平常图像都是三值,R,G,B或者H,S,V,二值化就只有0,1),为了以防什么地方把图片类型变了,在使用前就最好再灰度处理一次

gray=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

这样就必是二值化图像了
2、rhotheta分别是以像素为单位的距离精度和以弧度为单位的角度精度,通常设为1和图像识别 曲线形态 图像识别线条_图像识别 曲线形态_03就没什么太大问题。
3、threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。通俗讲就是多长的线段才能标识为线段,太大的话就对过滤一些小线段。
4、minLineLength这也是过滤用的参数,只有大于这个值才能显现,看上去和threshold作用差不多
5、maxLineGap允许将同一行点与点之间连接起来的最大的距离

然后就是图像的选择,一开始是用4个确切的点来定位剪切的,但后来发现这样子的话,换一个尺寸的图就会错,所以就用比例来定位目标区域了

#根据尺寸获取目标区域
pts=np.array([[0.6*w,0.6*h],[0.4*w,0.6*h],[0.15*w,h],[0.8*w,h]],dtype=np.int32)
cv2.fillConvexPoly(p,pts,(255,255,255))
p=cv2.cvtColor(p,cv2.COLOR_RGB2GRAY)
load=cv2.bitwise_and(p,dst)

pts就是把四个点的坐标存起来,四个点的 顺序是从右上角开始逆时针连接的

cv2.fillConvexPoly()就是在p这个图中,四个点围成的区域内填充(255,255,255)白色,然后cv2.bitwise_and()就是把p和dst两个图的每个像素值做操作(AND),就可以把区域内的图像筛选出来

图像识别 曲线形态 图像识别线条_二值化_04


图像识别 曲线形态 图像识别线条_最小二乘_05


图像识别 曲线形态 图像识别线条_最小二乘_06


下面是获取指定像素点坐标的代码,运行后直接在图上点就好了

import cv2

def mouse(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        xy = "%d,%d" % (x, y)
        cv2.circle(img, (x, y), 1, (255, 255, 255), thickness = -1)
        cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,
                    1.0, (255, 255, 255), thickness = 1)
        cv2.imshow("image", img)

img = cv2.imread("load2.png")
cv2.namedWindow("image")
cv2.imshow("image", img)
cv2.setMouseCallback("image", mouse)

cv2.waitKey(0)
cv2.destroyAllWindows()