简介:车道线识别是无人驾驶的基础,通过多种手段获取地面车道线位置,再根据车辆参数估算出车辆相对位置,以此为依据计算出车辆运动参数,这一节中我们先了解一下视图的转换。
车辆行驶过程中,只需要关注车辆前方一定范围内的车道线情况,由于摄像头视角为前视图,车道线在图像中并不是平行的,导致不容易估计车辆位置,转化为俯视图,就可以很直观的观察车辆位置的情况,如下图:
而前视图与俯视图的转换需要用到cv2.warpPerspective()透视变换函数,该函数可保持直线不变形,但是平行线可能不再平行。
cv2.warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None) --> dst
src:输入图像 dst:输出图像
M:3×3的变换矩阵
dsize:变换后输出图像尺寸
flag:插值方法
borderMode:边界像素外扩方式
borderValue:边界像素插值,默认用0填充
它的变换矩阵可以通过cv2.getPerspectiveTransform()函数获得,投射变换至少需要四组变换前后对应的点坐标,设取原图上的四个点组成矩阵points1,变换后的四个点组成的矩阵points2:
投影矩阵 M = cv2.getPerspectiveTransform(points1, points2)
对应点坐标可通过以下方法获取:
$ cd ~/gym-duckietown
$ python3 manual_control.py --env-name Duckietown --map-name calibration_map_ext
开启虚拟仿真环境,通过键盘方向键控制视野移动,使草坪下边缘正好与图像下边缘重合,按下enter键截图,图像保存为当前目录下的screen.png,另外拷贝~/.local/lib/python3.8/site-packages/duckietown_world/data/gd1/textures/tiles-processed/photos/calibration_tile/texture.jpg备用,这张图是棋盘格俯视图:
用opencv打开图片,可通过鼠标获取图像点左边,编程实现如下(源码文件:getPoints.py,图片放在源码文件所在目录下的images目录下):
#!/usr/bin/env python3
import cv2
screen = cv2.imread("images/screen.png")
texture = cv2.imread("images/texture.jpg")
#texture.jpg是512*512像素的,等比例放大到640
texture = cv2.resize(texture, (640,640), interpolation=cv2.INTER_NEAREST)
#保留640*480的区域
texture = texture[160: , :, :]
cv2.imshow("screen",screen)
cv2.imshow("texture",texture)
cv2.waitKey(0)
cv2.destroyAllWindows()
通过鼠标在右侧图中取4个点,要求4个点中任意3个都不在同一直线上,一般取最边缘的4个内角点:
pointsT = np.array([[214,55], [428,55], [428,320], [214,320]], np.float32)
通过鼠标在左侧图中取右侧图所取点的对应点:
pointsF = np.array([[256,207], [384,207], [447,283], [195,283]], np.float32)
编程计算投影矩阵(getM.py):
#!/usr/bin/env python3
import cv2
import numpy as np
line = cv2.imread("images/colorBanlance.png")
pointsT = np.array([[214,55], [428,55], [428,320], [214,320]], np.float32)
pointsF = np.array([[256,207], [384,207], [447,283], [195,283]], np.float32)
M = cv2.getPerspectiveTransform(pointsF, pointsT)
print(M)
lineT = cv2.warpPerspective(line, M, (640, 480), borderValue = None)
cv2.imshow("line",line)
cv2.imshow("lineT",lineT)
cv2.waitKey(0)
cv2.destroyAllWindows()
同时获取到投影矩阵:
[[-1.02032622e+00 -2.48368883e+00 6.44725345e+02]
[ 2.54332970e-16 -4.61731493e+00 9.22218319e+02]
[-8.37904170e-19 -7.77917189e-03 1.00000000e+00]]