今天记录一下简单的车道线检测,为一下几个步骤
0.导入数据
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import cv2
%matplotlib inline
import os
# 导入视频路径
TEST_IMAGES = "./test_images/"
TEST_VIDEO = "./test_videos/"
image_list = os.listdir("test_images/")
video_list = os.listdir("test_videos/")
image_list = [TEST_IMAGES+path for path in image_list]
video_list = [TEST_VIDEO+path for path in video_list]
print(image_list)
print(video_list)
image = cv2.imread(image_list[0])
1.读取图片和视频
读取图片
def show_image(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyWindow(name)
读取视频
import cv2
ret=True
cap = cv2.VideoCapture(video_list[1])
while ret:
ret, images = cap.read()
# 必须检测ret,因为有可能为False,images 为空
if ret == True:
cv2.imshow("capture", images)
if cv2.waitKey(50) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
cap.release()
2.灰度处理
def grayscale(img):
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
3.高斯滤波
#高斯模糊
def gaussian(img, kernel_size):
g_img = cv2.GaussianBlur(img, (kernel_size, kernel_size), 0)
return g_img
4.边缘检测
def canny(img, low_threshold, high_threshold):
"""Applies the Canny transform"""
return cv2.Canny(img, low_threshold, high_threshold)
5.感兴趣区域检测
我们将感兴趣区域设置为梯形,具体顶尖可以手动调整
# 区域选择
def select_regions(img):
rows, cols = img.shape[:2]
# 设置边界点
pt_top_left = [cols*0.4, rows*0.65]
pt_top_right = [cols*0.62, rows*0.65]
pt_bottom_left = [cols*0.12, rows*0.99]
pt_bottom_right = [cols*0.95, rows*0.99]
# 点为顺时针顺序
verties = np.array([[pt_top_left, pt_top_right, pt_bottom_right, pt_bottom_left ]], dtype=np.int32)
mask = np.zeros_like(img)
cv2.fillPoly(mask, verties, 255)
img_region = cv2.bitwise_and(img, mask)
return img_region
6.霍夫变换
通过霍夫变换来得到直线
def draw_lines(img, lines, color=[255, 0, 0], thickness=10):
left_x = []
left_y = []
right_x = []
right_y = []
for line in lines:
for x1,y1,x2,y2 in line:
# 根据得到直线的斜率来区分是左边的线还是右边的线
k = ((y2-y1)/(x2-x1))
# 右侧线
if k >=0.2:
right_x.extend((x1, x2))
right_y.extend((y1, y2))
#cv2.line(img, (x1, y1), (x2, y2), [0,255,0], thickness)
# 左侧线
elif k <=-0.2:
left_x.extend((x1, x2))
left_y.extend((y1, y2))
#cv2.line(img, (x1, y1), (x2, y2), [0,0,255], thickness)
# 通过点来拟合一条直线right_fit 为直线的参数
# right_fit[0]为k 斜率
# right_fit[1]为b 截距
right_fit = np.polyfit(right_x, right_y, 1)
r_y1= 351
# 根据直线方程的y推出x
r_x1 = int((r_y1 - right_fit[1])/right_fit[0])
r_y2= 529
r_x2 = int((r_y2 - right_fit[1])/right_fit[0])
cv2.line(img, (r_x1, r_y1), (r_x2, r_y2), [0,0,255], thickness)
left_fit = np.polyfit(left_x, left_y, 1)
l_y1= 529
l_x1 = int((l_y1 - left_fit[1])/left_fit[0])
l_y2= 351
l_x2 = int((l_y2 - left_fit[1])/left_fit[0])
cv2.line(img, (l_x1, l_y1), (l_x2, l_y2), [0,0,255], thickness)
return img
def hough_lines(img):
lines = cv2.HoughLinesP(img, rho=1, theta=np.pi/180, threshold=15, minLineLength=9, maxLineGap=10)
mask = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
line_img = draw_lines(mask, lines)
return line_img
7.图片混合
def weighted_img(img, initial_img, α=0.8, β=1., γ=0.):
"""
`img` is the output of the hough_lines(), An image with lines drawn on it.
Should be a blank image (all black) with lines drawn on it.
`initial_img` should be the image before any processing.
The result image is computed as follows:
initial_img * α + img * β + γ
NOTE: initial_img and img must be the same shape!
"""
return cv2.addWeighted(initial_img, α, img, β, γ)
显示视频
import cv2
ret=True
cap = cv2.VideoCapture(video_list[1])
while ret:
ret, images = cap.read()
if ret == True:
# 灰度处理
imgray = grayscale(images)
# 高斯滤波
g_img = gaussian(imgray, 5)
# 边缘检测
canny_imag = canny(g_img, 100, 200)
# 选择区域
img_region = select_regions(canny_imag)
# 霍夫转换,寻找直线
line_img = hough_lines(img_region)
# 在原图上混合车道线
img_limes = weighted_img(line_img, images)
# 显示图片
cv2.imshow("capture", img_limes)
if cv2.waitKey(50) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
cap.release()