1 #!D:/Code/python
2 #-*- coding: utf-8 -*-
3 #@Time : 2019/8/29 16:58
4 #@Author : Johnye
5 #@Site :
6 #@File : detect_RoadL.py
7 #@Software: PyCharm
8
9 importcv2 as cv10 importnumpy as np11 importmath12
13 #LaneLineDetection类
14 #通过对象封装,将其中的重要函数隔离开
15 classLaneLineDetection:16 def __init__(self):17 print("instace it")18 #leftline 和rightline车道检测的两条线
19 #每一条线分别有两个点决定
20 self.left_line = {'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0}21 self.right_line = {'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0}22
23 def process(self, frame, method=0):24 #将图像转化为灰度图像
25 gray =cv.cvtColor(frame, cv.COLOR_BGR2GRAY)26 #canny边缘检测
27 binary = cv.Canny(gray, 150, 300)28 h, w =gray.shape29 #这一步操作没看懂
30 binary[0:np.int(h/2+40),0:w] =031 #轮廓查找
32 contours, hierarchy =cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)33 #创建输出用的空白图像
34 out_image =np.zeros((h, w), frame.dtype)35 #遍历每一个轮廓,进行轮廓分析
36 for cnt inrange(len(contours)):37 #通过多种特征筛选
38 p =cv.arcLength(contours[cnt], True)39 #计算轮廓面积
40 area =cv.contourArea(contours[cnt])41 #获取轮廓的中心坐标以及长、宽
42 x, y, rw, rh =cv.boundingRect(contours[cnt])43 if p < 5 or area < 10:44 continue
45 if y > (h - 50):46 continue
47 #计算最小外接矩形角度
48 (x, y), (a, b), angle =cv.minAreaRect(contours[cnt]);49 angle =abs(angle)50 #筛选标准 角度不能小于20或者大于90度或者等于90度,剔除
51 if angle < 20 or angle > 160 or angle == 90.0:52 continue
53 #contour的长度大于5
54 if len(contours[cnt]) > 5:55 #椭圆拟合
56 (x, y), (a, b), degree =cv.fitEllipse(contours[cnt])57 #椭圆的角度小于5 或者 角度大于160 或者角度在80和160之间,剔除
58 if degree< 5 or degree>160 or 80
60 #不被以上的条件剔除的,在创建的空白图像上绘制该轮廓
61 cv.drawContours(out_image, contours, cnt, (255), 2, 8)62 result =self.fitLines(out_image)63 cv.imshow("contours", out_image)64 dst = cv.addWeighted(frame, 0.8, result, 0.5, 0)65 cv.imshow("lane-lines", dst)66 #直线拟合
67 deffitLines(self, image):68 h, w =image.shape69 h1 = np.int(h / 2 + 40)70 out = np.zeros((h, w, 3), dtype=np.uint8)71 cx = w // 2
72 cy = h // 2
73 left_pts =[]74 right_pts =[]75 for col in range(100, cx, 1):76 for row in range(cy, h, 1):77 pv =image[row, col]78 if pv == 255:79 left_pts.append((col, row))80 for col in range(cx, w-20, 1):81 for row in range(cy, h, 1):82 pv =image[row, col]83 if pv == 255:84 right_pts.append((col, row))85 #检测出的左车道线数量大于2
86 if len(left_pts) >= 2:87 [vx, vy, x, y] = cv.fitLine(np.array(left_pts), cv.DIST_L1, 0, 0.01, 0.01)88 y1 = int((-x * vy / vx) +y)89 y2 = int(((w - x) * vy / vx) +y)90 dy = y2 -y191 dx = w - 1
92 k = dy/dx93 c =y194
95 w1 = (h1 -c)/k96 w2 = (h - c) /k97 cv.line(out, (np.int(w1), np.int(h1)), (np.int(w2), np.int(h)), (0, 0, 255), 8, 8, 0)98 self.left_line['x1'] =np.int(w1)99 self.left_line['y1'] =np.int(h1)100 self.left_line['x2'] =np.int(w2)101 self.left_line['y2'] =np.int(h)102 #检测出的左车道线数量为1
103 else:104 x1 = self.left_line['x1']105 y1 = self.left_line['y1']106 x2 = self.left_line['x2']107 y2 = self.left_line['y2']108 cv.line(out, (x1, y1), (x2, y2), (0, 0, 255), 8, 8, 0)109 #检测出的右车道线数量大于2
110 if len(right_pts) >= 2:111 x1, y1 =right_pts[0]112 x2, y2 = right_pts[len(right_pts) - 1]113 dy = y2 -y1114 dx = x2 -x1115 k = dy /dx116 c = y1 - k *x1117 w1 = (h1 - c) /k118 w2 = (h - c)/k119 cv.line(out, (np.int(w1), np.int(h1)), (np.int(w2), np.int(h)), (0, 0, 255), 8, 8, 0)120 self.right_line['x1'] =np.int(w1)121 self.right_line['y1'] =np.int(h1)122 self.right_line['x2'] =np.int(w2)123 self.right_line['y2'] =np.int(h)124 #检测出的右车道线数量为1
125 else:126 x1 = self.right_line['x1']127 y1 = self.right_line['y1']128 x2 = self.right_line['x2']129 y2 = self.right_line['y2']130 cv.line(out, (x1, y1), (x2, y2), (0, 0, 255), 8, 8, 0)131 returnout132
133
134 defvideo_run():135 capture = cv.VideoCapture("images/road_line.mp4")136 height =capture.get(cv.CAP_PROP_FRAME_HEIGHT)137 width =capture.get(cv.CAP_PROP_FRAME_WIDTH)138 count =capture.get(cv.CAP_PROP_FRAME_COUNT)139 fps =capture.get(cv.CAP_PROP_FPS)140 print(height, width, count, fps)141 detector =LaneLineDetection()142 while(True):143 ret, frame =capture.read()144 if ret isTrue:145 cv.imshow("video-input", frame)146 detector.process(frame, 0)147 c = cv.waitKey(1)148 if c == 27:149 break
150 else:151 break
152
153
154 if __name__ == "__main__":155 video_run()156 cv.waitKey(0)157 cv.destroyAllWindows()