乐趣区

关于图像识别:学习笔记计算机视觉基础知识

//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()

运行后果:

退出移动版