车道线检测—python_opencv 代码解读
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 import cv2 as cv 10 import numpy as np 11 import math 12 13 # LaneLineDetection类 14 # 通过对象封装,将其中的重要函数隔离开 15 class LaneLineDetection: 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.shape 29 # 这一步操作没看懂 30 binary[0:np.int(h/2+40),0:w] = 0 31 # 轮廓查找 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 in range(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<degree<100: 59 continue 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 def fitLines(self, image): 68 h, w = image.shape 69 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 - y1 91 dx = w - 1 92 k = dy/dx 93 c = y1 94 95 w1 = (h1 -c)/k 96 w2 = (h - c) / k 97 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 - y1 114 dx = x2 - x1 115 k = dy / dx 116 c = y1 - k * x1 117 w1 = (h1 - c) / k 118 w2 = (h - c)/k 119 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 return out 132 133 134 def video_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 is True: 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()