道路分割
找到道路分割的onnx,分析其onnx的大致使用逻辑,然后写出最简洁版本predict.py
-
分析segment_onnx,查看输入输出
a. 输入 [1, 3, 512, 896]
b. 输出 [1, 512, 896, 4], 并且是概率值,仅不确定4通道代表什么,下面猜测
马路边边
不可行使区域
车道线
可行使区域
2. 查看代码,找到onnx的预处理,分析预处理逻辑
c. Normalize -> mean = 0 , norm = 1/255.0 // 这里已经除过255了,所以在后面就不用除了
d. 对输入图像直接resize到 [512, 896]
e. 确定输入的就是BGR图像
f. Normalize = (src_image - normalize.mean) * normalize.norm
3. 针对获得的信息,编写predict.py, 尝试写出来
import onnxruntime
import cv2
import numpy as np
session = onnxruntime.InferenceSession("workspace/road-segmentation-adas.onnx", providers=["CPUExecutionProvider"])
image = cv2.imread("workspace/imgs/dashcam_00.jpg")
image = cv2.resize(image, (896, 512)) // 因为原图在norm的时候除了255,所以这里不用再除一次了
image_tensor = (image.astype(np.float32))
image_tensor = image_tensor.transpose(2, 0, 1)[None] // ONNX模型通常期望输入的格式是(通道, 高度, 宽度)
prob = session.run(
["tf.identity"], {"data": image_tensor}
)[0]
cv2.imwrite("prob0.jpg", prob[0, :, :, 2] * 255)
深度估计
从这里可以分析到的结果
-
输入[1, 3, 256, 512] 输出[1, 1, 256, 512]
-
它的输出只需要'2499',其他输出都多余
-
NCHW is True :即直接resize
-
IS_RGB is True :即需要BGR转RGB
从下图这里得到均值和方差
5. normalize.mean = 0.485f norm = 0.229f
-
new_mean = mean * 255
-
new_norm = 1 / (norm * 255)
-
y = (x - new_mean) * new_norm --> y = (x / 255 - mean) / norm
分析差不多了,开始写代码
import onnxruntime
import cv2
import numpy as np
import matplotlib.pyplot as plt
session = onnxruntime.InferenceSession("workspace/ldrn_kitti_resnext101_pretrained_data_grad_256x512.onnx", providers=["CPUExecutionProvider"])
image = cv2.imread("workspace/imgs/dashcam_00.jpg")
image = cv2.resize(image, (512, 256))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image_tensor = (image / 255.0)
mean = [0.485, 0.456, 0.406]
norm = [0.229, 0.224, 0.225]
image_tensor = ((image_tensor - mean) / norm).astype(np.float32)
image_tensor = image_tensor.transpose(2, 0, 1)[None]
prob = session.run(
["2499"], {"input.1": image_tensor}
)[0]
# # cv
# prob = prob[0, 0] * -5 + 255
# y = int(prob.shape[0] * 0.18)
# prob = prob[y:]
# cv2.imwrite("depth.jpg", prob)
# plt
prob = prob[0, 0]
y = int(prob.shape[0] * 0.18)
prob = prob[y:]
plt.imsave("depth.jpg", prob, cmap='plasma_r')
# cmap='plasma_r' 反向等离子映射
消融实验
不加初始化
cv深度估计图
plt深度估计图
车道线检测
根据实际任务获取的先验知识
半张图,四条线,18点,200份+1份(是否存在),位置概率
输入 :[1, 3, 288, 800]
输出 :[1, 201, 18, 4]
先验 :
-
只需要识别4根线
-
车道线都是地面上,所以y方向可以中图像中心开始,也就是anchor起始坐标是图像中心到图像底部
-
线是连续的,但可以用离散的点表示,所以选择18个点表示一条线
-
因此回归一个点,其y坐标已知,x坐标需要回归出来
-
对于x回归,采用了位置概率来表示,划分为200个网格表示坐标
-
对于车道线的点是否存在的问题,采用第201个概率表示;若不存在,则该点最大
图像的预处理 : image / 255
图像需要BGR --> RGB
图像直接resize [288, 800]
后处理部分
-
对0—200维度进行softmax
-
对位置概率和位置索引点乘相加得到location,此时location是[18, 4]
-
对原始输出的最大值进行判断,决定该点是否存在;
-
最后过滤得到4根线的坐标
import onnxruntime
import cv2
import numpy as np
import matplotlib.pyplot as plt
import scipy.special
session = onnxruntime.InferenceSession("workspace/ultra_fast_lane_detection_culane_288x800.onnx", providers=["CPUExecutionProvider"])
image = cv2.imread("workspace/imgs/dashcam_00.jpg")
show = image.copy()
image = cv2.resize(image, (800, 288))
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image_tensor = (image / 255.0).astype(np.float32)
image_tensor = image_tensor.transpose(2, 0, 1)[None]
pred = session.run(
["200"], {"input.1": image_tensor}
)[0][0]
prob = scipy.special.softmax(pred[:-1, :, :], axis=0)
idx = np.arange(200) + 1
idx = idx.reshape(-1, 1, 1)
loc = np.sum(prob * idx, axis=0)
col_sample = np.linspace(0, 800 - 1, 200)
col_sample_w = col_sample[1] - col_sample[0]
print(col_sample_w)
pred = np.argmax(pred, axis=0)
loc[pred == 200] = 0
ys = np.array([121, 131, 141, 150, 160, 170, 180, 189, 199, 209, 219, 228, 238, 248, 258, 267, 277, 287])
xs = loc * col_sample_w * show.shape[1] / 800
ys = ys * show.shape[0] / 288
colors = [(0, 0, 255), (0, 255, 0), (0, 255, 0), (0, 0, 255)]
for iline in range(4):
for x, y in zip(xs[:, iline], ys):
if x == 0:
continue
cv2.circle(show, (int(x), int(y)), 5, colors[iline], -1, 16)
cv2.imwrite("lane.jpg", show)
print(pred.shape)
推理结果