完整版:Python----计算机视觉处理(Opencv:道路检测完整版:透视变换,提取车道线,车道线拟合,车道线显示)
一、透视变换
将透视变换之后的图像再继续透视变换为原图像
可参考Python----计算机视觉处理(Opencv:道路检测之道路透视变换)
导入模块
import numpy as np
import cv2
输入图像
img=cv2.imread('img_to_wrp.png')
获得透视变换矩阵
height, width, _ = img.shape
src = np.float32(
[
[width // 2 - 75, height // 2],
[width // 2 + 100, height // 2],
[0, height],
[width, height]
]
)
dst = np.float32(
[
[0, 0],
[width, 0],
[0, height],
[width, height]
]
)
M = cv2.getPerspectiveTransform(dst,src )
创建一个三通道背景图
wrp_zero=np.zeros_like(img_road1).astype(np.uint8)
color_wrp=np.dstack((wrp_zero,wrp_zero,wrp_zero))
组合车道线坐标
pts_left = np.transpose(np.vstack([left_fitx, ploty]))
pts_right = np.transpose(np.vstack([right_fitx, ploty]))
pts_middle = np.transpose(np.vstack([middle_fitx, ploty]))
绘制车道线
cv2.polylines(color_wrp, np.int32([pts_left]), isClosed=False, color=(202, 124, 0), thickness=15)
cv2.polylines(color_wrp, np.int32([pts_right]), isClosed=False, color=(202, 124, 0), thickness=15)
cv2.polylines(color_wrp, np.int32([pts_middle]), isClosed=False, color=(202, 124, 0), thickness=15)
将得到的车道线的像素点根据逆透视变换映射到原始图像中
newwarp = cv2.warpPerspective(color_wrp, M, (img.shape[1], img.shape[0]))
二、图像融合
将逆透视变换后的结果和原始图像进行融合
result1 = cv2.addWeighted(img, 1, newwarp, 1, 0)
创建一个灰色背景三通道图像
background_zero = np.zeros_like(img).astype(np.uint8) + 127
将原始图像和灰色背景融合
result = cv2.addWeighted(background_zero, 1, newwarp, 1, 0)
图像合并
concatenate_image1 = np.concatenate((img, img_wrp), axis=1)
concatenate_image2 = np.concatenate((result1, result), axis=1)
concatenate_image = np.concatenate((concatenate_image1,concatenate_image2), axis=0)
输出图像
cv2.imshow('concatenate_image', concatenate_image)
cv2.waitKey(0)
三、完整代码
# 读取图像
img = cv2.imread('road_polyfit.png')
height, width, _ = img.shape # 获取图像的高度和宽度
# 定义源点(src)和目标点(dst)进行透视变换
src = np.float32(
[
[width // 2 - 75, height // 2], # 左侧车道线的源点
[width // 2 + 100, height // 2], # 右侧车道线的源点
[0, height], # 底部左侧点
[width, height] # 底部右侧点
]
)
dst = np.float32(
[
[0, 0], # 目标左上角
[width, 0], # 目标右上角
[0, height], # 目标左下角
[width, height] # 目标右下角
]
)
# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(dst, src)
# 创建一个与原图像同样大小的全黑图像用于保存透视变换后的车道线
wrp_zero = np.zeros_like(img).astype(np.uint8)
# 创建一个颜色图像,用于绘制车道线
color_wrp = np.dstack((wrp_zero, wrp_zero, wrp_zero)) # 将黑色图像复制成三个通道
# 组合车道线坐标
pts_left = np.transpose(np.vstack([left_fitx, ploty])) # 左侧车道线的坐标
pts_right = np.transpose(np.vstack([right_fitx, ploty])) # 右侧车道线的坐标
pts_middle = np.transpose(np.vstack([middle_fitx, ploty])) # 中间车道线的坐标
# 绘制车道线,使用指定的颜色和线宽
cv2.polylines(color_wrp, np.int32([pts_left]), isClosed=False, color=(202, 124, 0), thickness=15)
cv2.polylines(color_wrp, np.int32([pts_right]), isClosed=False, color=(202, 124, 0), thickness=15)
cv2.polylines(color_wrp, np.int32([pts_middle]), isClosed=False, color=(202, 124, 0), thickness=15)
# 将得到的车道线的像素点根据逆透视变换映射到原始图像中
newwarp = cv2.warpPerspective(color_wrp, M, (img.shape[1], img.shape[0]))
# 将逆透视变换后的结果和原始图像进行加权融合,显示最终效果
result1 = cv2.addWeighted(img, 1, newwarp, 1, 0)
# 创建一个灰色背景图像,用于显示结果
background_zero = np.zeros_like(img).astype(np.uint8) + 127 # 创建一幅灰色图像
# 经过加权融合得到结果
result = cv2.addWeighted(background_zero, 1, newwarp, 1, 0)
# 拼接图像以便进行可视化
concatenate_image1 = np.concatenate((img, img_wrp), axis=1) # 拼接原始图像和变换后的图像
concatenate_image2 = np.concatenate((result1, result), axis=1) # 拼接加权融合的结果
concatenate_image = np.concatenate((concatenate_image1, concatenate_image2), axis=0) # 纵向拼接完整图像
cv2.imshow('concatenate_image', concatenate_image) # 所有结果拼接的图像
cv2.waitKey(0) # 等待按键以结束
四、库函数
4.1、transpose()
返回轴转置d 的数组。
对于一维数组,这将返回原始数组的未更改视图,因为转置d 向量只是相同的向量。 要将一维数组转换为二维列向量,需要一个额外的维度 必须添加,例如,实现此目的,就像 . 对于 2-D 数组,这是标准矩阵转置。 对于 n-D 数组,如果给定了轴,则它们的顺序表示 轴被置换(参见 Examples)。如果未提供 axes,则 。np.atleast_2d(a).T
a[:, np.newaxis]
transpose(a).shape == a.shape[::-1]
numpy.transpose(a, axes=None)
方法 | 描述 |
---|---|
a | Input 数组。 |
axes | 如果指定,则它必须是包含排列的 Tuples 或 List 的 [0, 1, ..., N-1] 其中 N 是 a 的轴数。阴性 indices 还可用于指定轴。返回的 数组将对应于输入的轴编号。 如果未指定,则默认为 ,这将反转 轴的顺序。axes[i] range(a.ndim)[::-1] |
4.2、concatenate()
沿现有轴连接数组序列。
numpy.concatenate((a1, a2, ...), axis=0, out=None, dtype=None, casting="same_kind")
方法 | 描述 |
---|---|
a1, a2, … | 数组必须具有相同的形状,但维度 对应于 axis (默认情况下是第一个)。 |
axis | 数组将沿其连接的轴。如果 axis 为 None,则 数组在使用前被展平。默认值为 0。 |
out | 如果提供,则为放置结果的目标。形状必须为 correct,匹配 concatenate 在 no out 参数。 |
dtype | 如果提供,目标数组将具有此 dtype。不能 与 out 一起提供。 |
casting | 控制可能发生的数据类型转换。默认为 'same_kind'。 有关选项的描述,请参阅铸造。 |
4.3、polylines()
绘制多条多边形曲线。
cv.polylines( img, pts, isClosed, color[, thickness[, lineType[, shift]]] ) -> img
方法 | 描述 |
---|---|
img | 图像。 |
pts | 多边形曲线数组。 |
isClosed | 指示绘制的多段线是否闭合的标志。如果它们是闭合的,则该函数将从每条曲线的最后一个顶点到其第一个顶点绘制一条线。 |
color | 多段线颜色。 |
thickness | 多段线边线的粗细。 |
lineType | 线段的类型。请参阅线型 |
shift | 顶点坐标中的小数位数。 |
4.4、addWeighted()
cv.addWeighted( src1, alpha, src2, beta, gamma[, dst[, dtype]] ) -> dst
方法 | 描述 |
---|---|
src1 | first input 数组。 |
alpha | 第一个数组元素的权重。 |
src2 | 第二个输入数组的大小和通道号与 src1 相同。 |
beta | 第二个数组元素的权重。 |
gamma | 添加到每个 sum 的标量。 |
dst | output 数组,该数组具有与 input 数组相同的大小和通道数。 |
dtype | 输出数组的可选深度;当两个输入数组具有相同的深度时,可以将 dtype 设置为 -1,这相当于 src1.depth()。 |