• 售前

  • 售后

热门帖子
入门百科

python+openCV (入门级)车道线检测 学习条记

[复制链接]
luly靓 显示全部楼层 发表于 2022-1-16 00:04:40 |阅读模式 打印 上一主题 下一主题
文章目次




一、openCV安装

win+x选择运行,然后输入cmd
输入pip install opencv-python等候安装
在IDLE中新建脚本.py文件,输入import cv2,如果无报错即为安装乐成。
再输入print(cv2.__version__)可检察openCV版本。
二、实验使用cv2中库函数

1.读取图片

  1. cv2.imread(const String & filename, int flags = IMREAD_COLOR)       
复制代码
  第一个参数是窗口的名字,第二个参数是读取格式(彩色或灰度),函数返回值是图片转换格式后所对应的列表。
  如img = cv2.imread('img.jpg',cv2.IMREAD_GRAYSCALE)
2.图片表现

  1. cv2.imshow(window_name, img)       
复制代码
  第一个参数是窗口的名字,可以创建多个窗口,但是必须给他们差异的名字。第二个参数是表现格式,可以是img图片格式,也可以是mat数组格式。
  
3.延时/停息

  1. cv2.waitKey(int x)
复制代码
  相当于步伐延时,调解cv2.imshow()的表现时间。延时时间为x毫秒。返回值为在延时期间按下键盘上按键所对应的ASCII值。
  x=0时,即cv2.waitKey(0)表现步伐停在此处,直得手动关闭cv2.imshow()的窗口。
比方计划一个,无穷延时,当键盘按下q时退出。
  1. if cv2.waitKey(1) & 0xFF == ord(‘q’): break  
  2. #ord()是将字符转换为ASCII码
复制代码
4.生存图片

  1. cv2.imwrite(newfile_name, img)
复制代码
  第一个参数是生存的新图片的文件名,第二个参数是应生存的图片对应的列表。
  5.清晰全部窗口

  1. cv2.destroyAllWindows()
复制代码
  关闭全部openCV打开的窗口。
  三、Canny边沿检测

CV2提供了提取图像边沿的函数canny。其算法头脑如下:
1. 使用高斯暗昧,去除噪音点(cv2.GaussianBlur)
2. 灰度转换(cv2.cvtColor)
3. 使用sobel算子,盘算出每个点的梯度巨细和梯度方向
4. 使用非极大值克制(只有最大的生存),消除边沿检测带来的杂散效应
5. 应用双阈值,来确定真实和潜伏的边沿
6. 通过克制弱边沿来完成终极的边沿检测
1.高斯滤波

  1. gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize,gaussian_ksize), gaussian_sigmax)
复制代码
  color_img 输入图片
gaussian_ksize 高斯核巨细,可以为方形矩阵,也可以为矩形
gaussian_sigmax X方向上的高斯核标准毛病
没看太懂这个函数,现在仅范围于搬来直接用,下次肯定
  2.图片转换

  1. gray_img = cv2.cvtColor(input_image, flag)
复制代码
  用于颜色空间转换。input_image为必要转换的图片,flag为转换的范例,返回值为颜色空间转换后的图片矩阵。flag对应:
cv2.COLOR_BGR2GRAY BGR -> Gray
cv2.COLOR_BGR2RGB BGR -> RGB
cv2.COLOR_BGR2HSV BGR -> HSV
可以相识一下该函数和cv2.imread()的区别
  
3.边沿检测

  1. edge_img = cv2.Canny(gray_img,canny_threshold1,canny_threshold2)
复制代码
  imag为所操纵的图片,threshold1为下阈值,threshold2为上阈值,返回值为边沿图。
  
四、ROI and mask

使用数组选取ROI(region of interest,感性趣的地区,然后与原图举行布尔运算(与运算)。

  1. poly_pts = numpy.array([[[0,368],[300,210],[340,210],[640,368]]])
复制代码
  四个数组创建后生存在变量poly_pts中。
  1. mask = np.zeros_like(gray_img)
复制代码
  构建一个与gray_img同维度的数组,并初始化全部变量为零。
  1. cv2.fillPoly(mask, pts, color)
复制代码
  绘制多边形函数。mask为绘制对像,pts为绘制范围,color为绘制颜色。
  1. img_mask = cv2.bitwise_and(gray_img, mask)
复制代码
  与运算
  
五、霍夫变更

得到一系列的直线
  1. lines = cv2.HoughLinesP(edge_img,  1, np.pi / 180, 15, minLineLength=40, maxLineGap=20)
复制代码
  edge_img: 要检测的图片矩阵
参数2: 间隔r的精度,值越大,思量越多的线
参数3: 间隔theta的精度,值越大,思量越多的线
参数4: 累加数阈值,值越小,思量越多的线
minLineLength: 最短长度阈值,短于这个长度的线会被清除
maxLineGap:同不绝线两点之间的最大间隔
返回值::
[np.array([[x_1,y_1, x_2, y_2]]),
np.array([[x_1, y_1, x_2, y_2]]),
…,
np.array([[x_1, y_1, x_2, y_2]])]
  六、离群值过滤

循环查找超出设定范围的斜率,并去除。
  1. idx = np.argmax(diff)
复制代码
  当diff中存放的是一维时,找到diff中最大的数值,并返回该值地点位置。
  1. 示例:
  2. one_dim_array = np.array([1, 4, 5, 3, 7, 2, 6])
  3. print(np.argmax(one_dim_array))
  4. 打印结果为        4
复制代码
  1. lines.pop(idx)
复制代码
  从列表lines中把第idx数去除
  七、最小二乘法拟合

得到左车道线和右车道线的抱负直线
  1. x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
复制代码
  将多维数组降为一维
还未想明确转换关系,下次肯定
  1. poly = np.polyfit(x, y, deg)
复制代码
  x, y为各个点的横纵坐标,deg为拟合曲线的次数
  1. y_e = np.polyval(poly, x)
复制代码
  拟合曲线之后,x在曲线上对应的y值
  八、车道线标注

  1. cv2.line(img, tuple(line[0]), tuple(line[1]), color,thickness)
复制代码
  在图片上画线,img为所标注的目标图片,ine[0]为出发点坐标,line[1]为止境坐标,thickness为线宽。
注意两个坐标必要为tuple元组格式,即tuple(line[0])
  
九、视频读写

1.打开视频

  1. capture = cv2.VideoCapture('video.mp4')
复制代码
  如果为cv2.VideoCapture(0),表现打开条记本的内置摄像头。
  2.按帧读取视频

  1. ret, frame = capture.read()
复制代码
  此中ret是布尔值,如果读取帧是准确的则返回True,如果文件读取到末了,它的返回值就为False。
frame就是每一帧的图像,是个三维矩阵。
  3.视频编码格式设置

  1. fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
复制代码
  fourcc意为四字符代码(Four-Character Codes),顾名思义,该编码由四个字符构成,下面是VideoWriter_fourcc对象一些常用的参数,注意:字符序次不能弄混
cv2.VideoWriter_fourcc(‘I’, ‘4’, ‘2’, ‘0’),该参数是YUV编码范例,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘P’, ‘I’, ‘M’, ‘I’),该参数是MPEG-1编码范例,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘X’, ‘V’, ‘I’, ‘D’),该参数是MPEG-4编码范例,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘T’, ‘H’, ‘E’, ‘O’),该参数是Ogg Vorbis,文件名后缀为.ogv
cv2.VideoWriter_fourcc(‘F’, ‘L’, ‘V’, ‘1’),该参数是Flash视频,文件名后缀为.flv
  4.写视频参数设置

  1. outfile = cv2.VideoWriter(filename, fourcc, 25, (1280,368))
复制代码
  filename为写入视频的文件名,fourcc为视频编码格式cv2.VideoWriter_fourcc()的返回值,25为帧率,(1280,368)为视频巨细。
  1. ret, frame = capture.read()
复制代码
  第一个参数ret 为布尔值即True 大概False,代表有没有读取到图片,第二个参数frame表现截取到一帧的图片
  1. output = np.concatenate((origin, frame), axis=1)
复制代码
  可以或许一次完成多个数组的拼接
不写axis参数的话,默以为按列拼接;若axis = 1的话,即为按行拼接;
axis参数意义没搞太明确,下次肯定
  
十、其他

步伐存在小bug但不影响检测视频天生,如果哪位大佬知道bug怎么办理记得踢我一脚。
cv2.imshow()总是卡住无相应,无法本身关闭窗口,使用cv2.destroyAllWindows()也照旧卡住;
而且陈诉错误:
  1. error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\smooth.dispatch.cpp:617: error: (-215:Assertion failed) !_src.empty() in function 'cv::GaussianBlur'
复制代码
  1. > 卡住的问题有人说是openCV对一部分硬件的适配不好,我比较在赞成这种观点。 报错  cv2.error  error:
  2. > (-215:Assertion failed) dst.data == (uchar*)dst_ptr in function
  3. > 'cvShowImage'
  4. >
  5. > 同样的代码,我发现在公司电脑1060上,cv2.imshow()就可以显示,但在自己2080ti上就总是报错如上。于是锁定在cv2版本问题,果然卸掉最新的4.0版本,换上3.4.4.19就好了。
  6. >
  7. > 可能是4.0版本与2080ti的卡还不兼容。
  8. > 来源:https://blog.caogenba.net/qq_39938666/article/details/88179966
复制代码
报错的标题现在未办理,也修改不掉。
总结

完全实现对视频情势的单车道直线行驶时对车道线检测和标注。
附视频检测完备步伐

  1. import cv2
  2. import numpy as np
  3. #高斯滤波+canny边缘检测
  4. def get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1,
  5.                  canny_threshold1=50, canny_threshold2=100):
  6.     #param intoduction
  7.     #color_img 输入图片    gaussian_ksize 高斯核大小
  8.     #gaussian_sigmax X方向上的高斯核标准偏差
  9.     gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize, gaussian_ksize),
  10.                                 gaussian_sigmax)
  11.     gray_img = cv2.cvtColor(gaussian,cv2.IMREAD_GRAYSCALE)
  12.     edge_img = cv2.Canny(gray_img,canny_threshold1,canny_threshold2);
  13.     return edge_img
  14. def roi_mask(gray_img):
  15.     poly_pts = np.array([[[0,368],[300,210],[340,210],[640,368]]])
  16.     mask = np.zeros_like(gray_img)
  17.     cv2.fillPoly(mask, pts=poly_pts, color=255)
  18.     img_mask = cv2.bitwise_and(gray_img, mask)
  19.     return img_mask
  20. def get_lines(edge_img):
  21.    
  22.     #斜率计算
  23.     def calculate_slope(line):
  24.         x_1, y_1, x_2, y_2 = line[0]
  25.         slope = (y_2-y_1)/(x_2-x_1)
  26.         return slope
  27.     #离群值过滤
  28.     def reject_abnormal_lines(lines, threshold):
  29.         slopes = [calculate_slope(line) for line in lines]
  30.         while len(lines)>0:
  31.             mean = np.mean(slopes)
  32.             diff = [abs(s-mean) for s in slopes]
  33.             idx = np.argmax(diff)
  34.             if diff[idx]>threshold:
  35.                 slopes.pop(idx)
  36.                 lines.pop(idx)
  37.             else:
  38.                 break
  39.         return lines
  40.    
  41.     #最小二乘拟合
  42.     def least_squares_fit(lines):
  43.    
  44.         x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
  45.         y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])
  46.         # 2. 进行直线拟合.得到多项式系数
  47.         poly = np.polyfit(x_coords, y_coords, deg=1)
  48.         # 3. 根据多项式系数,计算两个直线上的点,用于唯一确定这条直线
  49.         point_min = (np.min(x_coords), np.polyval(poly, np.min(x_coords)))
  50.         point_max = (np.max(x_coords), np.polyval(poly, np.max(x_coords)))
  51.         return np.array([point_min, point_max],dtype=np.int0)
  52.     lines = cv2.HoughLinesP(edge_img, 1, np.pi/180, 15, minLineLength=40, maxLineGap=20)
  53.     left_lines = [line for line in lines if calculate_slope(line)<0]
  54.     right_lines = [line for line in lines if calculate_slope(line)>0]
  55.    
  56.     left_lines = reject_abnormal_lines(left_lines, threshold=0.2)
  57.     right_lines = reject_abnormal_lines(right_lines, threshold=0.2)
  58.     return least_squares_fit(left_lines),least_squares_fit(right_lines)
  59. def draw_line(img, lines):
  60.     left_line, right_line = lines
  61.     cv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0,255,255),thickness=5)
  62.     cv2.line(img, tuple(right_line[0]), tuple(right_line[1]), color=(0,255,255),thickness=5)
  63. def show_lane(color_img):
  64.     edge_img = get_edge_img(color_img)
  65.     mask_gray_img = roi_mask(edge_img)
  66.     lines = get_lines(mask_gray_img)
  67.     draw_line(color_img, lines)
  68.     return color_img
  69. if __name__ == '__main__':
  70.     capture = cv2.VideoCapture('video.mp4')
  71.     fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
  72.     outfile = cv2.VideoWriter('output.avi', fourcc, 25, (1280,368))
  73.     while True:
  74.         ret, frame = capture.read()
  75.         origin = np.copy(frame)
  76.         frame = show_lane(frame)
  77.         output = np.concatenate((origin, frame), axis=1)
  78.         outfile.write(output)
  79.         cv2.imshow('video', output)
  80.         cv2.waitKey(10)
复制代码
  分步操纵检测图片和检测视频的源码、测试图片和测试视频毗连:https://download.caogenba.net/download/qq_27839923/75831347

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作