//TODO
Q:给定图片,如何辨认车道线?
能够从色彩、形态、方向、图像中的地位 几个角度来确定车道线。
色彩:
利用色彩来判断车道线(图中的车道线是红色的)
RGB 图片有三个色彩通道 R、G、B,每个通道中的每一个像素都是 0 到 255 范畴内的值。
其中 0 是最暗值,255 是最亮值。
因而 RGB 图像中,纯白色是 255,255,255
尝试过滤红色外的其余色彩:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
print('start')
# 读取图片,展现原图
image=mpimg.imread('test.jpg')
plt.imshow(image)
plt.show()
# 备份图片,不批改原图
cp_image=np.copy(image)
# 定义筛选阈值,红色是 255,255,255,因而咱们选比 255 稍小的值即可,这里抉择 200
r_threshold=200
g_threshold=200
b_threshold=200
rgb_thresholds=[r_threshold,g_threshold,b_threshold]
# 筛选器,筛选出低于阈值的像素
thresholds=(image[:,:,0]<rgb_thresholds[0]) | (image[:,:,1]<rgb_thresholds[1]) | (image[:,:,2]<rgb_thresholds[2])
# 将不满足条件的值设为 0,0,0,即彩色
cp_image[thresholds]=[0,0,0]
# 展现图片
plt.imshow(cp_image)
plt.show()
# 保留图片
mpimg.imsave('after_color.jpg',cp_image)
执行后果:
区域:
发现只靠色彩无奈精确检测出车道线,因为其余物体也有红色。
当初咱们假如车道线肯定是在车辆前端的固定区域内:
思考只对该区域进行色彩解决。
首先咱们要可能选出一个三角形区域:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
print('start')
# 读取图片,展现
image=mpimg.imread('test.jpg')
plt.imshow(image)
plt.show()
# 显示图片大小
print(image.shape) # 后果:(540,960,3)
# 备份图片,不批改原图
cp_image=np.copy(image)
# 指定区域点,这里是三角形区域,结构三角形的三个点
# 须要留神的是,x 轴是在下面的,y 轴是从上往下的,和平时的坐标轴不太一样
p_left=[0,550]
p_right=[900,550]
p_mid=[400,200]
# 结构三角形的三条边
# np.polyfit 仿佛是给定一组点,拟合出一个多项式的函数
# 咱们这里用来结构直线方程
# 开端的参数 1 示意结构一次方程
line_left=np.polyfit((p_left[0],p_mid[0]),(p_left[1],p_mid[1]),1)
line_right=np.polyfit((p_mid[0],p_right[0]),(p_mid[1],p_right[1]),1)
line_bottom=np.polyfit((p_left[0],p_right[0]),(p_left[1],p_right[1]),1)
# 筛选器,用于筛选区域内的像素
# 首先要结构地位矩阵
# np.meshgrid 传入 X 可选值域和 Y 值域,返回所有可选的坐标
# np.arange(0,xsize,step)是结构 [0,xsize) 中步长为 step 的等差数列,默认步长为 1
# np.arange()和 np.linespace()的区别在于,arange 传入的是步长,linespace 传入的是个数
ysize=cp_image.shape[0] # 留神:行是 y
xsize=cp_image.shape[1] # 留神:列是 x
X,Y=np.meshgrid(np.arange(0,xsize),np.arange(0,ysize))
region_threshold=((X*line_left[0]+line_left[1])<Y) \
& ((X*line_right[0]+line_right[1])<Y) \
& ((X*line_bottom[0]+line_bottom[1])>Y)
# 绘制区域,将区域内的局部涂成红色
cp_image[region_threshold]=[255,0,0]
# 展现区域
plt.imshow(cp_image)
plt.show()
运行后果:
联合色彩和区域:
只在特定区域内进行色彩解决:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
print('start')
image = mpimg.imread('test.jpg')
plt.imshow(image)
plt.show()
# 结构色彩筛选器
r_threshold=200
g_threshold=200
b_threshold=200
rgb_thresholds=[r_threshold,g_threshold,b_threshold]
color_thresholds=(image[:,:,0]<rgb_thresholds[0]) \
| (image[:,:,1]<rgb_thresholds[1]) \
| (image[:,:,2]<rgb_thresholds[2])
# 结构区域筛选器
p_left=[0,540]
p_right=[900,540]
p_mid=[500,300]
line_left=np.polyfit((p_left[0],p_mid[0]),(p_left[1],p_mid[1]),1)
line_right=np.polyfit((p_mid[0],p_right[0]),(p_mid[1],p_right[1]),1)
line_bottom=np.polyfit((p_left[0],p_right[0]),(p_left[1],p_right[1]),1)
ysize=image.shape[0] # 留神:行是 y
xsize=image.shape[1] # 留神:列是 x
X,Y=np.meshgrid(np.arange(0,xsize),np.arange(0,ysize))
region_threshold=((X*line_left[0]+line_left[1])<Y) \
& ((X*line_right[0]+line_right[1])<Y) \
& ((X*line_bottom[0]+line_bottom[1])>Y)
# 显示区域
# plt.ploy()是画直线用的
# plt.ploy()的第三个参数中,b 示意色彩 blue,-- 示意虚线,b-- 即蓝色虚线
cp_image=np.copy(image)
x=[p_left[0],p_mid[0],p_right[0],p_left[0]]
y=[p_left[1],p_mid[1],p_right[1],p_left[1]]
plt.plot(x,y,'b--',lw=5)
plt.imshow(cp_image)
plt.show()
# 对区域内进行色彩解决
# cp_image[~region_threshold]=[0,0,0]
cp_image[region_threshold&~color_thresholds]=[255,0,0]
plt.imshow(cp_image)
plt.show()
执行后果:
这样就实现了仅在特定区域内筛选色彩
其余色彩的车道线怎么办:canny 边缘检测算法
然而,车道线不仅仅都是红色,有可能呈现其余色彩。
咱们甚至无奈事后晓得车道线的色彩,这时候怎么办呢?
有没有方法可能解决任何色彩的线条?
图像是 x – y 的数学函数,因而也能够对他进行数学运算,例如求导。
图像是二维的,因而对于 x 和 y 同时求导是有意义的,这称为梯度。
咱们测量像素点在每个地位上的变动水平,以及哪个方向变动最快,
通过梯度计算,可能取得较粗的边缘线,
利用 canny 算法,咱们通过仅保留梯度最大的像素点,将边缘细化,
而后,再通过蕴含一些梯度强度更低一些的像素点,再次扩大高强度边缘的宽度。
梯度强度低的像素点阈值是咱们调用 canny 函数时能够本人定的。
利用 canny 算法检测边缘线:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import cv2
image = mpimg.imread('exit-ramp.jpg')
plt.imshow(image)
plt.show()
# 转化为灰度图片,灰度的目标 '应该' 是更好的检测梯度变动,防止色彩烦扰
gray_image=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
plt.imshow(gray_image,cmap='gray')
plt.show()
# 先进行高斯含糊,高斯含糊实质上是克制噪声和伪梯度均匀的一种办法
# 实际上 cv2.Canny()外部自带高斯平滑,但再做一次能够进一步平滑
kernel_size=5 # 能够抉择任意奇数,越大越平滑
blur_gray_image=cv2.GaussianBlur(gray_image,(kernel_size,kernel_size),0)
# 算法首先会检测出 >high_threshold 的强像素,并回绝 <low_threshold 的强像素
# 接着,在 low_threshold 和 high_threshold 之间的像素,和强像素联通的保留
# 输入的 edges 在边缘地位是红色的,非边缘地位是彩色的
# 参数取值:因为像素值是 256 的,因而阈值能够选成十上百
# 官网倡议 low 与 high 的比值为 1:2 或 1:3
low_threshold=50
high_threshold=150
edges=cv2.Canny(blur_gray_image,low_threshold,high_threshold)
plt.imshow(edges,cmap='Greys_r')
plt.show()
运行后果: