You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
19KB

  1. # 耗时最短代码
  2. import numpy as np
  3. import cv2,time,math
  4. import matplotlib.pyplot as plt
  5. def get_ms(time2, time1):
  6. return (time2-time1)*1000.0
  7. # 计算一点到二次函数曲线的距离,二次函数的表达式为x = a*(y**2) + b*y + c
  8. def point2QF(a, b, c, y, x): # 坐标点(y, x)
  9. distance = abs(x - a*(y**2) - b*y - c) / math.sqrt(1 + ((2*a*y + b)**2))
  10. return distance
  11. # 存储所有speedRoad的contours
  12. def storageRoad(contours, pars):
  13. allRoadCnt = [] # 存储所有speedRoad的contours
  14. for cnt in contours: # 道路
  15. if len(cnt) >= 6:
  16. rect = cv2.minAreaRect(cnt)
  17. if rect[1][0] * rect[1][1] > pars['RoadArea']: # 过滤掉面积小于阈值的speedRoad
  18. allRoadCnt.append(cnt)
  19. return allRoadCnt
  20. # 用于判断lane数量是否大于2,当lane数量大于等于2时,返回laneNumber
  21. def storageLane(contours, pars):
  22. laneNumber = 0
  23. for cnt in contours:
  24. if len(cnt) >= 6:
  25. rect = cv2.minAreaRect(cnt)
  26. if rect[1][0] * rect[1][1] > pars['laneArea'] and min(rect[1]) / max(rect[1]) <= pars['roundness']:
  27. laneNumber += 1
  28. if laneNumber > 2:
  29. break
  30. return laneNumber
  31. # 将contours中顶点数大于等于6的车辆信息(合格vehicle)和顶点数小于6的车辆信息(不合格vehicle)分别保存起来
  32. def vehicleDivide(contours, vehicleBD, normVehicle, dets, count, i, unnormVehicle, normVehicleCOOR, centerCOOR):
  33. if len(contours) >= 6:
  34. vehicleBD.append(contours)
  35. normVehicle.append(dets[count])
  36. normVehicleCOOR.append(centerCOOR)
  37. else:
  38. dets[int(i / 2)].append(0)
  39. dets[int(i / 2)].append(0)
  40. unnormVehicle.append(dets[int(i / 2)])
  41. return vehicleBD, normVehicle, unnormVehicle, normVehicleCOOR
  42. # 存储所有vehicle的信息
  43. def storageVehicle(pars, imgVehicle, dets):
  44. """
  45. 输入
  46. pars:字典名
  47. imgVehicle:分割图,只包含vehicle和背景
  48. dets:是一个list,其中存储检测得到的各vehicle的信息,即[[x0, y0, x1, y1, 车辆得分, cls], ...]
  49. 输出
  50. dets:存储合格vehicle的信息,即[x0, y0, x1, y1, 车辆得分, cls]
  51. vehicleBD:存储合格vehicle的contours
  52. unnormVehicle:存储不合格vehicle的信息,即[x0, y0, x1, y1, 车辆得分, cls]
  53. normVehicleCOOR:存储合格vehicle的中心点坐标
  54. 说明
  55. 合格vehicle:contours中的顶点数大于等于6
  56. 不合格vehicle:contours中的顶点数小于6
  57. """
  58. vehicleBD = [] # 存储一副图像中vehicles的contours
  59. normVehicle = [] # 将合格vehicle的信息存储在normVehicle中
  60. unnormVehicle = [] # 将不合格vehicle的信息存储在unnormVehicle中
  61. normVehicleCOOR = [] # 存储合格vehicle的中心点坐标
  62. img = cv2.cvtColor(imgVehicle, cv2.COLOR_BGR2GRAY)
  63. count = 0
  64. for i in range(0, len(pars['vehicleCOOR']), 2):
  65. y1 = int(pars['vehicleCOOR'][i][1] * pars['ZoomFactor']['y'])
  66. y2 = int(pars['vehicleCOOR'][i + 1][1] * pars['ZoomFactor']['y'])
  67. x1 = int(pars['vehicleCOOR'][i][0] * pars['ZoomFactor']['x'])
  68. x2 = int(pars['vehicleCOOR'][i + 1][0] * pars['ZoomFactor']['x'])
  69. if y1 >= 2:
  70. y1 = y1 - 2
  71. if y2 <= (pars['modelSize'][1] - 2):
  72. y2 = y2 + 2
  73. if x1 >= 2:
  74. x1 = x1 - 2
  75. if x2 <= (pars['modelSize'][0] - 2):
  76. x2 = x2 + 2
  77. centerCOOR = (int((x1 + x2) / 2), int((y1 + y2) / 2))
  78. img1 = img[y1:y2, x1:x2]
  79. up = np.zeros((20, (x2 - x1)), dtype='uint8')
  80. left = np.zeros(((40 + y2 - y1), 20), dtype='uint8')
  81. img1 = np.concatenate((up, img1), axis=0)
  82. img1 = np.concatenate((img1, up), axis=0)
  83. img1 = np.concatenate((left, img1), axis=1)
  84. img2 = np.concatenate((img1, left), axis=1)
  85. contours2, hierarchy = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  86. if len(contours2) != 0:
  87. if len(contours2) > 1:
  88. vehicleArea = [] # 存储vehicle的最小外接矩形的面积
  89. for j in range(len(contours2)):
  90. rect = cv2.minAreaRect(contours2[j])
  91. vehicleArea.append(rect[1][0] * rect[1][1])
  92. maxAreaIndex = vehicleArea.index(max(vehicleArea))
  93. maxAreaContours = contours2[maxAreaIndex]
  94. vehicleBD, normVehicle, unnormVehicle, normVehicleCOOR = vehicleDivide(maxAreaContours, vehicleBD, normVehicle, dets, count, i, unnormVehicle, normVehicleCOOR, centerCOOR)
  95. elif len(contours2) == 1:
  96. vehicleBD, normVehicle, unnormVehicle, normVehicleCOOR = vehicleDivide(contours2[0], vehicleBD, normVehicle, dets, count, i, unnormVehicle, normVehicleCOOR, centerCOOR)
  97. else:
  98. dets[int(i / 2)].append(0)
  99. dets[int(i / 2)].append(0)
  100. unnormVehicle.append(dets[int(i / 2)])
  101. count += 1
  102. dets = normVehicle
  103. return dets, vehicleBD, unnormVehicle, normVehicleCOOR
  104. # 计算违停得分
  105. def IllegalParkScore(vehicleBD, allRoadCnt, dets, laneNumber, unnormVehicle, normVehicleCOOR, a_l, b_l, c_l, a_r, b_r, c_r):
  106. """
  107. 对vehicle是否在speedRoad上进行判断,并计算违章得分
  108. 输出targetList 其格式为:[[cls, x0, y0, x1, y1, score, 违章得分, 违章类别], ...]
  109. """
  110. if len(vehicleBD) != 0:
  111. for i in range(len(vehicleBD)):
  112. rect = cv2.minAreaRect(vehicleBD[i])
  113. center = normVehicleCOOR[i] # vehicle的中心点坐标
  114. if len(allRoadCnt) != 0 and laneNumber >= 2: # 当车道线个数至少有两条时,才计算违章得分
  115. for j in range(len(allRoadCnt)):
  116. # 判断车辆矩形框的中心点坐标是否在道路矩形框的范围内
  117. flag = cv2.pointPolygonTest(allRoadCnt[j], center, False)
  118. if flag >= 0:
  119. dets[i].append(0) # 给违章得分占位
  120. dets[i].append(0) # 给违章类别占位
  121. if center[0] < predict(a_l, b_l, c_l, center[1]):
  122. distance = point2QF(a_l, b_l, c_l, center[1], center[0])
  123. if distance >= min(rect[1]) / 2:
  124. dets[i][6], dets[i][7] = 1, 1
  125. else:
  126. dets[i][6], dets[i][7] = distance / (min(rect[1]) / 2), 1
  127. elif center[0] > predict(a_r, b_r, c_r, center[1]):
  128. distance = point2QF(a_r, b_r, c_r, center[1], center[0])
  129. if distance >= min(rect[1]) / 2:
  130. dets[i][6], dets[i][7] = 1, 1
  131. else:
  132. dets[i][6], dets[i][7] = distance / (min(rect[1]) / 2), 1
  133. else:
  134. dets[i][6], dets[i][7] = 0, 0
  135. break
  136. # 如果分割图像中不存在speedRoad,则无法进行违章判定,将所有车辆的违章类别设为0,即没有违章
  137. if len(dets[i]) < 8:
  138. dets[i].append(0) # 违章得分为0
  139. dets[i].append(0) # 0表示没有违章
  140. targetList = dets
  141. if len(unnormVehicle) != 0:
  142. for i in range(len(unnormVehicle)):
  143. targetList.append(unnormVehicle[i]) # 将所有车辆的信息合并到一起
  144. else:
  145. targetList = unnormVehicle
  146. return targetList
  147. # 找最左侧lane时,将要删除的右侧lane的序号存储在delRightLane。找最右侧lane时,将要删除的左侧lane的序号存储在delLeftLane。
  148. def devideLane(laneInfo, i, m, delRightLane, delLeftLane, y):
  149. index1 = np.where(laneInfo[i][3] == y)
  150. index1 = index1[0].tolist()
  151. index1.sort()
  152. x_1 = laneInfo[i][5][index1[0]][0]
  153. index2 = np.where(laneInfo[m][3] == y)
  154. index2 = index2[0].tolist()
  155. index2.sort()
  156. x_2 = laneInfo[m][5][index2[0]][0]
  157. if x_1 < x_2:
  158. if i not in delLeftLane:
  159. delLeftLane.append(i) # 保留右侧lane
  160. if m not in delRightLane:
  161. delRightLane.append(m)
  162. else:
  163. if m not in delLeftLane:
  164. delLeftLane.append(m)
  165. if i not in delRightLane:
  166. delRightLane.append(i)
  167. return delRightLane, delLeftLane
  168. # 确定最左侧和最右侧的lane簇
  169. def detLine(contours):
  170. """
  171. 输入
  172. contours:各lane的contours
  173. 输出
  174. laneInfo:存储各lane的信息,每条lane的信息为:[contours, y坐标范围, lane序号, arr_y, y坐标范围的长度, cnt]
  175. delRightLane:在确定最左侧lane时,其存储需要删除的lane的序号
  176. delLeftLane:在确定最右侧lane时,其存储需要删除的lane的序号
  177. """
  178. mergList = []
  179. for i in range(len(contours)):
  180. cnt = np.squeeze(contours[i], 1)
  181. arr_y = cnt[:, 1]
  182. arrList = list(set(arr_y))
  183. cnt_y = np.sort(np.array(arrList))
  184. mergList.append([contours[i], cnt_y, i, arr_y, len(cnt_y), cnt])
  185. laneInfo = sorted(mergList, key=(lambda x: x[4])) # [[contours[i], cnt_y, i, arr_y, len(cnt_y)],...]
  186. delRightLane = [] # 求最左侧lane
  187. delLeftLane = [] # 求最右侧lane
  188. laneInfoNew = []
  189. for i in range(len(laneInfo)):
  190. laneInfoNew.append([laneInfo[i][1][0], laneInfo[i][1][-1], i]) # [[y_min, y_max, i],...]
  191. laneInfoNew = np.array(laneInfoNew)
  192. new1 = laneInfoNew[:, np.newaxis, :].repeat(laneInfoNew.shape[0], 1)
  193. new2 = laneInfoNew[np.newaxis, ...].repeat(laneInfoNew.shape[0], 0)
  194. new3 = np.concatenate((new1, new2), axis=2)
  195. y_i_min, y_i_max, y_m_min, y_m_max = new3[..., 0], new3[..., 1], new3[..., 3], new3[..., 4]
  196. mask1 = (y_i_min >= y_m_min) & (y_i_min <= y_m_max) & (y_i_max > y_m_max)
  197. mask2 = (y_i_max >= y_m_min) & (y_i_max <= y_m_max) & (y_i_min < y_m_min)
  198. mask3 = (y_i_min >= y_m_min) & (y_i_max <= y_m_max)
  199. mask4 = (y_i_min < y_m_min) & (y_i_max > y_m_max)
  200. if len(np.nonzero(mask1)[0]) != 0:
  201. mask1 = np.triu(mask1, k=1)
  202. serial_i = new3[mask1][..., 2]
  203. serial_m = new3[mask1][..., 5]
  204. for k in range(len(serial_i)):
  205. if (serial_m[k] not in delLeftLane) or (serial_m[k] not in delRightLane) or (serial_i[k] not in delLeftLane) or (serial_i[k] not in delRightLane):
  206. delRightLane, delLeftLane = devideLane(laneInfo, serial_i[k], serial_m[k], delRightLane, delLeftLane, laneInfo[serial_i[k]][1][0])
  207. if len(np.nonzero(mask2)[0]) != 0:
  208. mask2 = np.triu(mask2, k=1)
  209. serial_i = new3[mask2][..., 2]
  210. serial_m = new3[mask2][..., 5]
  211. for k in range(len(serial_i)):
  212. if (serial_m[k] not in delLeftLane) or (serial_m[k] not in delRightLane) or (serial_i[k] not in delLeftLane) or (serial_i[k] not in delRightLane):
  213. delRightLane, delLeftLane = devideLane(laneInfo, serial_i[k], serial_m[k], delRightLane, delLeftLane, laneInfo[serial_i[k]][1][-1])
  214. if len(np.nonzero(mask3)[0]) != 0:
  215. mask3 = np.triu(mask3, k=1)
  216. serial_i = new3[mask3][..., 2]
  217. serial_m = new3[mask3][..., 5]
  218. for k in range(len(serial_i)):
  219. if (serial_m[k] not in delLeftLane) or (serial_m[k] not in delRightLane) or (serial_i[k] not in delLeftLane) or (serial_i[k] not in delRightLane):
  220. delRightLane, delLeftLane = devideLane(laneInfo, serial_i[k], serial_m[k], delRightLane, delLeftLane, laneInfo[serial_i[k]][1][0])
  221. if len(np.nonzero(mask4)[0]) != 0:
  222. mask4 = np.triu(mask4, k=1)
  223. serial_i = new3[mask4][..., 2]
  224. serial_m = new3[mask4][..., 5]
  225. for k in range(len(serial_i)):
  226. if (serial_m[k] not in delLeftLane) or (serial_m[k] not in delRightLane) or (serial_i[k] not in delLeftLane) or (serial_i[k] not in delRightLane):
  227. delRightLane, delLeftLane = devideLane(laneInfo, serial_i[k], serial_m[k], delRightLane, delLeftLane, laneInfo[serial_m[k]][1][0])
  228. return laneInfo, delRightLane, delLeftLane
  229. # 对lane中的y值坐标进行下采样
  230. def downSample(cnt_y):
  231. # number = len(cnt_y) * 0.0125
  232. # cnt_y = np.random.choice(cnt_y, size=number, replace=False)
  233. if len(cnt_y) >= 1000:
  234. cnt_y = cnt_y[1::80]
  235. elif len(cnt_y) >= 900 and len(cnt_y) < 1000:
  236. cnt_y = cnt_y[1::75]
  237. elif len(cnt_y) >= 800 and len(cnt_y) < 900:
  238. cnt_y = cnt_y[1::70]
  239. elif len(cnt_y) >= 700 and len(cnt_y) < 800:
  240. cnt_y = cnt_y[1::65]
  241. elif len(cnt_y) >= 600 and len(cnt_y) < 700:
  242. cnt_y = cnt_y[1::60]
  243. elif len(cnt_y) >= 500 and len(cnt_y) < 600:
  244. cnt_y = cnt_y[1::55]
  245. elif len(cnt_y) >= 400 and len(cnt_y) < 500:
  246. cnt_y = cnt_y[1::40]
  247. elif len(cnt_y) >= 300 and len(cnt_y) < 400:
  248. cnt_y = cnt_y[1::45]
  249. elif len(cnt_y) >= 200 and len(cnt_y) < 300:
  250. cnt_y = cnt_y[1::40]
  251. elif len(cnt_y) >= 100 and len(cnt_y) < 200:
  252. cnt_y = cnt_y[1::35]
  253. elif len(cnt_y) >= 50 and len(cnt_y) < 100:
  254. cnt_y = cnt_y[1::20]
  255. elif len(cnt_y) >= 20 and len(cnt_y) < 50:
  256. cnt_y = cnt_y[1::6]
  257. else:
  258. cnt_y = cnt_y[1::5]
  259. return cnt_y
  260. # 求最左侧lane或最右侧lane中的各点坐标
  261. def targetCOOR(laneInfo, delLane):
  262. """
  263. 输入
  264. laneInfo:存储各lane的信息,每条lane的信息为:[contours, y坐标范围, lane序号, arr_y, y坐标范围的长度, cnt]
  265. delLane:在确定最左侧lane或最右侧lane时,其存储需要删除的lane的序号。
  266. 输出
  267. laneCOOR:存储最左侧或最右侧lane簇中各点的坐标
  268. """
  269. laneCOOR = [] # 存储lane中各点的坐标
  270. centerSort = [] # 存储各lane按照中心点的y坐标排序后的结果
  271. for j in range(len(laneInfo)):
  272. if j not in delLane:
  273. cnt = laneInfo[j][0]
  274. rect = cv2.minAreaRect(cnt)
  275. cnt = np.squeeze(cnt, 1)
  276. cnt_y = laneInfo[j][1]
  277. cnt_y = downSample(cnt_y)
  278. centerSort.append([rect[0][1], cnt_y, laneInfo[j][3], cnt, j])
  279. centerSort = sorted(centerSort, key=(lambda x: x[0]))
  280. for i in range(len(centerSort)):
  281. centerCoordinate = []
  282. for j in range(len(centerSort[i][1])):
  283. index = np.where(centerSort[i][2] == centerSort[i][1][j])
  284. indexList = index[0].tolist()
  285. indexList.sort()
  286. x = (centerSort[i][3][indexList[0]][0] + centerSort[i][3][indexList[-1]][0]) / 2
  287. y = (centerSort[i][3][indexList[0]][1] + centerSort[i][3][indexList[-1]][1]) / 2
  288. centerCoordinate.append([x, y])
  289. laneCOOR = laneCOOR + centerCoordinate
  290. return laneCOOR
  291. # 二次函数曲线表达式:x = a*(y**2) + b*y + c,根据图像中一点的y坐标求二次曲线中的x坐标
  292. def predict(a, b, c, y):
  293. x = a * (y**2) + b * y + c
  294. return x
  295. def mixNoParking_road_postprocess(dets, mask, pars):
  296. """
  297. 对于字典traffic_dict中的各个键,说明如下:
  298. RoadArea:speedRoad的最小外接矩形的面积
  299. vehicleCOOR:是一个列表,用于存储被检测出的vehicle的坐标(vehicle检测模型)
  300. roundness:圆度 ,lane的长与宽的比率,作为判定是否为车道线的标准之一
  301. laneArea:车道线的最小外接矩形的面积
  302. ZoomFactor:图像在H和W方向上的缩放因子,其值小于1
  303. fitOrder:多点拟合曲线的阶数
  304. 最终输出格式:[[x0, y0, x1, y1, 车辆得分, cls, 违章停车得分, 违章类别], ...]
  305. 违章类别:0表示正常车辆,1表示违章车辆
  306. """
  307. det_cors = []
  308. for bb in dets:
  309. det_cors.append((int(bb[0]), int(bb[1])))
  310. det_cors.append((int(bb[2]), int(bb[3])))
  311. #print('#################line341:',det_cors)
  312. pars['vehicleCOOR'] = det_cors
  313. H, W = mask.shape[0:2] # mask的分辨率为360x640
  314. scaleH = pars['modelSize'][1] / H # 自适应调整缩放比例
  315. scaleW = pars['modelSize'][0] / W
  316. pars['ZoomFactor'] = {'x': scaleW, 'y': scaleH}
  317. new_hw = [int(H * scaleH), int(W * scaleW)]
  318. mask = cv2.resize(mask, (new_hw[1], new_hw[0]))
  319. if len(mask.shape) == 3:
  320. mask = mask[:, :, 0]
  321. t1 = time.time()
  322. imgRoad = mask.copy()
  323. imgVehicle = mask.copy()
  324. lane_line = mask.copy()
  325. # 将vehicle和lane过滤掉,只包含背景和speedRoad
  326. imgRoad[imgRoad == 2] = 1
  327. imgRoad[imgRoad == 3] = 1
  328. # 将speedRoad和lane过滤掉,只保留vehicle和背景
  329. imgVehicle[imgVehicle != 2] = 0
  330. # 将speedRoad和vehicle过滤掉,只保留lane和背景
  331. lane_line[lane_line < 3] = 0
  332. imgRoad = cv2.cvtColor(np.uint8(imgRoad), cv2.COLOR_RGB2BGR) # 道路
  333. imgVehicle = cv2.cvtColor(np.uint8(imgVehicle), cv2.COLOR_RGB2BGR) # 车辆
  334. lane_line = cv2.cvtColor(np.uint8(lane_line), cv2.COLOR_RGB2BGR)
  335. # 对车道线进行膨胀操作
  336. # kernel = np.ones((3, 3), np.uint8) # 膨胀范围
  337. # lane_line = cv2.dilate(lane_line, kernel, iterations=2) # 迭代次数为2
  338. t2 = time.time()
  339. img1 = cv2.cvtColor(imgRoad, cv2.COLOR_BGR2GRAY)
  340. roadContours, hierarchy = cv2.findContours(img1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  341. t3 = time.time()
  342. # 存储所有speedRoad的信息
  343. allRoadCnt = storageRoad(roadContours, pars)
  344. t4 = time.time()
  345. img3 = cv2.cvtColor(lane_line, cv2.COLOR_BGR2GRAY)
  346. laneContours, hierarchy = cv2.findContours(img3, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  347. t5 = time.time()
  348. laneInfo, delRightLane, delLeftLane = detLine(laneContours)
  349. t6 = time.time()
  350. # 存储所有lane的信息
  351. laneNumber = storageLane(laneContours, pars)
  352. t7 = time.time()
  353. # 存储所有vehicle的信息
  354. dets, vehicleBD, unnormVehicle, normVehicleCOOR = storageVehicle(pars, imgVehicle, dets)
  355. t8 = time.time()
  356. leftLaneCOOR = targetCOOR(laneInfo, delRightLane)
  357. rightLaneCOOR = targetCOOR(laneInfo, delLeftLane)
  358. rightLaneCOOR = np.array(rightLaneCOOR)
  359. rightX = rightLaneCOOR[:, 0]
  360. rightY = rightLaneCOOR[:, 1]
  361. leftLaneCOOR = np.array(leftLaneCOOR)
  362. leftX = leftLaneCOOR[:, 0]
  363. leftY = leftLaneCOOR[:, 1]
  364. # a_r,b_r,c_r分别是:最右侧车道线簇拟合的二次函数的二次项系数一次项系数,和常数项
  365. a_r, b_r, c_r = np.polyfit(rightY, rightX, pars['fitOrder'])[0], np.polyfit(rightY, rightX, pars['fitOrder'])[1], np.polyfit(rightY, rightX, pars['fitOrder'])[2]
  366. # a_l,b_l,c_l分别是:最左侧车道线簇拟合的二次函数的二次项系数,一次项系数,和常数项
  367. a_l, b_l, c_l = np.polyfit(leftY, leftX, pars['fitOrder'])[0], np.polyfit(leftY, leftX, pars['fitOrder'])[1], np.polyfit(leftY, leftX, pars['fitOrder'])[2]
  368. """以下四行代码用于在后处理函数外画图"""
  369. finalLane = []
  370. abc = [a_l, b_l, c_l, a_r, b_r, c_r] # abc中存储的是最左侧和最右侧二次函数的各项系数
  371. finalLane.append(rightLaneCOOR)
  372. finalLane.append(leftLaneCOOR)
  373. t9 = time.time()
  374. # 计算违停得分
  375. targetList = IllegalParkScore(vehicleBD, allRoadCnt, dets, laneNumber, unnormVehicle, normVehicleCOOR, a_l, b_l, c_l, a_r, b_r, c_r)
  376. t10 = time.time()
  377. time_infos = 'postTime:%.2f(分割时间:%.2f, findContours:%.2f, ruleJudge:%.2f, storageRoad:%.2f, detLane:%.2f, storageLane:%.2f, storageVehicle:%.2f, fitLine:%.2f, IllegalParkScore:%.2f)' % (
  378. get_ms(t10, t1), get_ms(t2, t1), get_ms(t3, t2), get_ms(t8, t3), get_ms(t4, t3), get_ms(t6, t5), get_ms(t7, t6), get_ms(t8, t7), get_ms(t9, t8), get_ms(t10, t9))
  379. #, finalLane, lane_line, abc
  380. targetList = [ [ *b[0:4],b[6] if b[6]>0 else b[4], b[7] ] for b in targetList ]
  381. #print('---------line415:',targetList)
  382. return targetList, time_infos