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.

684 lines
56KB

  1. import numpy as np
  2. import cv2,time,math
  3. def get_ms(time2, time1):
  4. return (time2-time1)*1000.0
  5. # 根据两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0 (a >= 0)
  6. def getLinearEquation(p1x, p1y, p2x, p2y):
  7. sign = 1
  8. a = p2y - p1y
  9. if a < 0:
  10. sign = -1
  11. a = sign * a
  12. b = sign * (p1x - p2x)
  13. c = sign * (p1y * p2x - p1x * p2y)
  14. # y=kx+bb
  15. k = -a/(b+0.0000000001)
  16. bb = -c/(b+0.000000000001)
  17. return k, bb
  18. # 根据多点坐标拟合直线
  19. def best_fit(X, Y):
  20. xbar = sum(X) / len(X)
  21. ybar = sum(Y) / len(Y)
  22. n = len(X) # or len(Y)
  23. numer = sum([xi * yi for xi, yi in zip(X, Y)]) - n * xbar * ybar
  24. denum = sum([xi ** 2 for xi in X]) - n * xbar ** 2
  25. k = numer / denum
  26. b = ybar - k * xbar
  27. # print('best fit line:\ny = {:.2f}x + {:.2f}'.format(k, b))
  28. return k, b
  29. # 对于左侧车道线,返回两车道线中心点连线确定的角度,radian2表示弧度
  30. def calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber):
  31. radian2 = math.atan2(abs(allLaneContent[leftLaneSerialNumber[-1]][4][1] - allLaneContent[leftLaneSerialNumber[0]][4][1]), abs(allLaneContent[leftLaneSerialNumber[-1]][4][0] - allLaneContent[leftLaneSerialNumber[0]][4][0]))
  32. lanesCenterAngle1 = 180 - int(radian2 * 180 / math.pi)
  33. lanesCenterAngle2 = int(radian2 * 180 / math.pi)
  34. return lanesCenterAngle1, lanesCenterAngle2
  35. # 对于右侧车道线,返回两车道线中心点连线确定的角度,radian2表示弧度
  36. def calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber):
  37. radian2 = math.atan2(abs(allLaneContent[rightLaneSerialNumber[-1]][4][1] - allLaneContent[rightLaneSerialNumber[0]][4][1]), abs(allLaneContent[rightLaneSerialNumber[-1]][4][0] - allLaneContent[rightLaneSerialNumber[0]][4][0]))
  38. lanesCenterAngle3 = 180 - int(radian2 * 180 / math.pi)
  39. lanesCenterAngle4 = int(radian2 * 180 / math.pi)
  40. return lanesCenterAngle3, lanesCenterAngle4
  41. # 从所有车道线中确定位于最左侧的车道线簇,并将各车道线对应的序号存储在leftLaneSerialNumber中
  42. def findLeftLanes(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, pars):
  43. for i in range(len(laneXCoordinateMin2MaxSort)): # 求最左侧车道线
  44. if (allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0] > allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0] and allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1] < allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]) or (allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0] < allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0] and allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1] > allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]): # allLaneContent[0][4][0]:中心点x坐标。 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  45. radian1 = math.atan2(abs(allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1] - allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1]), abs(allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0] - allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0]))
  46. lanesCenterAngle1 = 180 - int(radian1 * 180 / math.pi)
  47. if len(leftLaneSerialNumber) == 0: # 刚开始判断
  48. if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  49. if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
  50. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
  51. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  52. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  53. else:
  54. break
  55. else:
  56. if (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  57. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  58. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  59. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  60. else:
  61. break
  62. elif (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  63. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  64. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  65. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  66. else:
  67. break
  68. elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  69. lanesCenterAngle2 = 90
  70. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  71. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  72. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  73. else:
  74. break
  75. elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
  76. lanesCenterAngle2 = 0
  77. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  78. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  79. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  80. else:
  81. break
  82. elif (allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0] < allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0] and allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1] < allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]) or (allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0] > allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0] and allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1] > allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]): # 这种情况对应左上角和右下角的车道线,计算角度
  83. radian1 = math.atan2(abs(allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1] - allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1]), abs(allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0] - allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0]))
  84. lanesCenterAngle1 = int(radian1 * 180 / math.pi)
  85. if len(leftLaneSerialNumber) == 0: # 刚开始判断
  86. if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  87. if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
  88. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
  89. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  90. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  91. else:
  92. break
  93. else:
  94. if (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  95. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  96. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  97. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  98. else:
  99. break
  100. elif (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or ( allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  101. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  102. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  103. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  104. else:
  105. break
  106. elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  107. lanesCenterAngle2 = 90
  108. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  109. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  110. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  111. else:
  112. break
  113. elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
  114. lanesCenterAngle2 = 0
  115. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  116. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  117. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  118. else:
  119. break
  120. elif allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0]: # 两车道线的最小x坐标相同
  121. lanesCenterAngle1 = 90
  122. if len(leftLaneSerialNumber) == 0: # 刚开始判断
  123. if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  124. if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
  125. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
  126. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  127. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  128. else:
  129. break
  130. else:
  131. if (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  132. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  133. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  134. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  135. else:
  136. break
  137. elif (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  138. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  139. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  140. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  141. else:
  142. break
  143. elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  144. lanesCenterAngle2 = 90
  145. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  146. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  147. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  148. else:
  149. break
  150. elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
  151. lanesCenterAngle2 = 0
  152. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  153. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  154. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  155. else:
  156. break
  157. elif allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
  158. lanesCenterAngle1 = 0
  159. if len(leftLaneSerialNumber) == 0: # 刚开始判断
  160. if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  161. if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
  162. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
  163. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  164. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  165. else:
  166. break
  167. else:
  168. if (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  169. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  170. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  171. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  172. else:
  173. break
  174. elif (allLaneContent[leftLaneSerialNumber[0]][4][0] < allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] < allLaneContent[leftLaneSerialNumber[-1]][4][1]) or (allLaneContent[leftLaneSerialNumber[0]][4][0] > allLaneContent[leftLaneSerialNumber[-1]][4][0] and allLaneContent[leftLaneSerialNumber[0]][4][1] > allLaneContent[leftLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  175. if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  176. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  177. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  178. else:
  179. break
  180. elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  181. lanesCenterAngle2 = 90
  182. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  183. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  184. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  185. else:
  186. break
  187. elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
  188. lanesCenterAngle2 = 0
  189. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  190. if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
  191. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
  192. else:
  193. break
  194. return leftLaneSerialNumber
  195. # 从所有车道线中确定位于最右侧的车道线簇,并将各车道线对应的序号存储在rightLaneSerialNumber中
  196. def findRightLanes(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, pars):
  197. for r in range(len(laneXCoordinateMax2MinSort)): # 求最右侧车道线
  198. if (allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0] > allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0] and allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1] < allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]) or (allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0] < allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0] and allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1] > allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]): # allLaneContent[0][4][0]:中心点x坐标。 车辆的相对位置不同,计算角度方法也不同。
  199. radian1 = math.atan2(abs(allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1] - allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1]), abs(allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0] - allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0]))
  200. lanesCenterAngle1 = 180 - int(radian1 * 180 / math.pi)
  201. if len(rightLaneSerialNumber) == 0: # 刚开始判断
  202. if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  203. if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
  204. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
  205. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  206. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  207. else:
  208. break
  209. else:
  210. if (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  211. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  212. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  213. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  214. else:
  215. break
  216. elif (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  217. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  218. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  219. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  220. else:
  221. break
  222. elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  223. lanesCenterAngle2 = 90
  224. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  225. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  226. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  227. else:
  228. break
  229. elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
  230. lanesCenterAngle2 = 0
  231. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  232. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  233. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  234. else:
  235. break
  236. elif (allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0] < allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0] and allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1] < allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]) or (allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0] > allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0] and allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1] > allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]):
  237. radian1 = math.atan2(abs(allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1] - allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1]), abs(allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0] - allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0]))
  238. lanesCenterAngle1 = int(radian1 * 180 / math.pi)
  239. if len(rightLaneSerialNumber) == 0: # 刚开始判断
  240. if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  241. if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
  242. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
  243. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  244. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  245. else:
  246. break
  247. else:
  248. if (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  249. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  250. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  251. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  252. else:
  253. break
  254. elif (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  255. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  256. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  257. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  258. else:
  259. break
  260. elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  261. lanesCenterAngle2 = 90
  262. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  263. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  264. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  265. else:
  266. break
  267. elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
  268. lanesCenterAngle2 = 0
  269. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  270. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  271. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  272. else:
  273. break
  274. elif allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0]:
  275. lanesCenterAngle1 = 90
  276. if len(rightLaneSerialNumber) == 0: # 刚开始判断
  277. if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  278. if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
  279. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
  280. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  281. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  282. else:
  283. break
  284. else:
  285. if (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  286. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  287. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  288. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  289. else:
  290. break
  291. elif (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  292. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  293. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  294. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  295. else:
  296. break
  297. elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  298. lanesCenterAngle2 = 90
  299. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  300. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  301. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  302. else:
  303. break
  304. elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
  305. lanesCenterAngle2 = 0
  306. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  307. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  308. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  309. else:
  310. break
  311. elif allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]:
  312. lanesCenterAngle1 = 0
  313. if len(rightLaneSerialNumber) == 0: # 刚开始判断
  314. if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
  315. if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
  316. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
  317. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  318. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  319. else:
  320. break
  321. else:
  322. if (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  323. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
  324. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  325. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  326. else:
  327. break
  328. elif (allLaneContent[rightLaneSerialNumber[0]][4][0] < allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] < allLaneContent[rightLaneSerialNumber[-1]][4][1]) or (allLaneContent[rightLaneSerialNumber[0]][4][0] > allLaneContent[rightLaneSerialNumber[-1]][4][0] and allLaneContent[rightLaneSerialNumber[0]][4][1] > allLaneContent[rightLaneSerialNumber[-1]][4][1]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
  329. if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
  330. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  331. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  332. else:
  333. break
  334. elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
  335. lanesCenterAngle2 = 90
  336. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  337. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  338. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  339. else:
  340. break
  341. elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
  342. lanesCenterAngle2 = 0
  343. if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
  344. if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
  345. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
  346. else:
  347. break
  348. return rightLaneSerialNumber
  349. # 返回最左侧车道线簇所确定的直线的k和b值,将其存储在leftLaneKB中
  350. def calculateLeftLane_k_b(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, leftLaneBox, leftLaneAbovePoint, leftLaneKB, leftLaneCenterX, leftLaneCenterY, pars):
  351. leftLaneSerialNumber = findLeftLanes(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, pars)
  352. if len(leftLaneSerialNumber) == 0:
  353. leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[0][1]) # leftLaneSerialNumber中存放的是最左侧的车道线簇中的各车道线的序号
  354. if len(leftLaneSerialNumber) == 1:
  355. centerCoordinate = allLaneContent[leftLaneSerialNumber[0]][4] # 最小外接矩形的中心点坐标
  356. box = allLaneContent[leftLaneSerialNumber[0]][5]
  357. leftLaneBox.append([box[0][0], box[0][1]])
  358. leftLaneBox.append([box[1][0], box[1][1]])
  359. leftLaneBox.append([box[2][0], box[2][1]])
  360. leftLaneBox.append([box[3][0], box[3][1]])
  361. for i in range(len(leftLaneBox)):
  362. if leftLaneBox[i][1] < centerCoordinate[1]:
  363. leftLaneAbovePoint.append(leftLaneBox[i])
  364. point1_l = [(leftLaneAbovePoint[0][0] + leftLaneAbovePoint[1][0]) / 2, (leftLaneAbovePoint[0][1] + leftLaneAbovePoint[1][1]) / 2]
  365. point2_l = [centerCoordinate[0], centerCoordinate[1]]
  366. k_l, b_l = getLinearEquation(point1_l[0], point1_l[1], point2_l[0], point2_l[1])
  367. leftLaneKB.append(k_l)
  368. leftLaneKB.append(b_l)
  369. else:
  370. for i in range(len(leftLaneSerialNumber)):
  371. leftLaneCenterX.append(allLaneContent[leftLaneSerialNumber[i]][4][0]) # leftLaneCenterX中存储的是各车道线中心点的x坐标
  372. leftLaneCenterY.append(allLaneContent[leftLaneSerialNumber[i]][4][1]) # leftLaneCenterY中存储的是各车道线中心点的y坐标
  373. k_l, b_l = best_fit(leftLaneCenterX, leftLaneCenterY)
  374. leftLaneKB.append(k_l)
  375. leftLaneKB.append(b_l)
  376. return leftLaneKB
  377. # 返回最右侧车道线簇所确定的直线的k和b值,将其存储在rightLaneKB中
  378. def calculateRightLane_k_b(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, rightLaneBox, rightLaneAbovePoint, rightLaneKB, rightLaneCenterX, rightLaneCenterY, pars):
  379. rightLaneSerialNumber = findRightLanes(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, pars)
  380. if len(rightLaneSerialNumber) == 0:
  381. rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[0][1]) # rightLaneSerialNumber中存放的是最右侧的车道线簇中的各车道线的序号
  382. if len(rightLaneSerialNumber) == 1:
  383. centerCoordinate = allLaneContent[rightLaneSerialNumber[0]][4] # 最小外接矩形的中心点坐标
  384. box = allLaneContent[rightLaneSerialNumber[0]][5]
  385. rightLaneBox.append([box[0][0], box[0][1]])
  386. rightLaneBox.append([box[1][0], box[1][1]])
  387. rightLaneBox.append([box[2][0], box[2][1]])
  388. rightLaneBox.append([box[3][0], box[3][1]])
  389. for i in range(len(rightLaneBox)):
  390. if rightLaneBox[i][1] < centerCoordinate[1]:
  391. rightLaneAbovePoint.append(rightLaneBox[i])
  392. point1_r = [(rightLaneAbovePoint[0][0] + rightLaneAbovePoint[1][0]) / 2, (rightLaneAbovePoint[0][1] + rightLaneAbovePoint[1][1]) / 2]
  393. point2_r = [centerCoordinate[0], centerCoordinate[1]]
  394. k_r, b_r = getLinearEquation(point1_r[0], point1_r[1], point2_r[0], point2_r[1])
  395. rightLaneKB.append(k_r)
  396. rightLaneKB.append(b_r)
  397. else:
  398. for i in range(len(rightLaneSerialNumber)):
  399. rightLaneCenterX.append(allLaneContent[rightLaneSerialNumber[i]][4][0]) # rightLaneCenterX中存储的是各车道线中心点的x坐标
  400. rightLaneCenterY.append(allLaneContent[rightLaneSerialNumber[i]][4][1]) # rightLaneCenterY中存储的是各车道线中心点的y坐标
  401. k_r, b_r = best_fit(rightLaneCenterX, rightLaneCenterY)
  402. rightLaneKB.append(k_r)
  403. rightLaneKB.append(b_r)
  404. return rightLaneKB
  405. def mixNoParking_road_postprocess(dets, mask, pars):
  406. """
  407. 对于字典traffic_dict中的各个键,说明如下:
  408. speedRoadArea:speedRoad的最小外接矩形的面积
  409. vehicleCoordinate:是一个列表,用于存储被检测出的vehicle的坐标(vehicle检测模型)
  410. roundness:圆度 ,lane的长与宽的比率,作为判定是否为车道线的标准之一
  411. 'cls':类别号
  412. vehicleArea:vehicle的最小外接矩形的面积
  413. laneLineArea:车道线的最小外接矩形的面积
  414. laneAngleCha:车道线的角度差值阈值
  415. contoursNum:counters中的顶点个数
  416. ZoomFactor:图像在H和W方向上的缩放因子,其值小于1
  417. 最终输出格式:[[cls, x0, y0, x1, y1, 车辆得分, 违章停车得分, 违章类别], ...]
  418. 违章类别:0表示正常车辆,1表示违章车辆
  419. """
  420. det_cors = []
  421. for bb in dets:
  422. det_cors.append((int(bb[1]), int(bb[2])))
  423. det_cors.append((int(bb[3]), int(bb[4])))
  424. pars['vehicleCoordinate'] = det_cors
  425. H, W = mask.shape[0:2]
  426. scaleH = pars['modelSize'][1] / H # 自适应调整缩放比例
  427. scaleW = pars['modelSize'][0] / W
  428. pars['ZoomFactor'] = {'x': scaleH, 'y': scaleW}
  429. new_hw = [int(H * scaleH), int(W * scaleW)]
  430. mask = cv2.resize(mask, (new_hw[1], new_hw[0]))
  431. if len(mask.shape) == 3:
  432. mask = mask[:, :, 0]
  433. t3 = time.time()
  434. vehicleContours = [] # 存储一副图像中vehicles的contours
  435. image_speedRoad = mask.copy()
  436. image_vehicle = mask.copy()
  437. lane_line = mask.copy()
  438. image_speedRoad[image_speedRoad == 2] = 0 # 将vehicle过滤掉,只包含背景和speedRoad
  439. image_vehicle[image_vehicle == 1] = 0 # 将speedRoad过滤掉,只包含背景和vehicle
  440. lane_line[lane_line < 3] = 0
  441. image_speedRoad = cv2.cvtColor(np.uint8(image_speedRoad), cv2.COLOR_RGB2BGR) # 道路
  442. image_vehicle = cv2.cvtColor(np.uint8(image_vehicle), cv2.COLOR_RGB2BGR) # 车辆
  443. lane_line = cv2.cvtColor(np.uint8(lane_line), cv2.COLOR_RGB2BGR) #
  444. t4 = time.time()
  445. img1 = cv2.cvtColor(image_speedRoad, cv2.COLOR_BGR2GRAY)
  446. contours, hierarchy = cv2.findContours(img1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  447. t5 = time.time()
  448. # 创建列表
  449. singleSpeedRoadContent, allSpeedRoadContent, complianceVehicle, NonComplianceVehicle, singleLaneContent, allLaneContent, laneMinXCoordinate, laneMaxXCoordinate, leftLaneSerialNumber, leftLaneBox, leftLaneAbovePoint, leftLaneKB, leftLaneCenterX, leftLaneCenterY, rightLaneSerialNumber, rightLaneBox, rightLaneAbovePoint, rightLaneKB, rightLaneCenterX, rightLaneCenterY = ([] for t in range(20))
  450. """
  451. 列表说明如下:
  452. singleSpeedRoadContent = [] # 过渡使用
  453. allSpeedRoadContent = [] # 存放speedRoad坐标(Xmin,Xmax,Ymin,Ymax)、speedRoadAngle和speedRoad的宽高
  454. complianceVehicle = [] # 将符合标准的vehicle信息存储在complianceVehicle中
  455. NonComplianceVehicle = [] # 将不符合标准的vehicle信息存储在NonComplianceVehicle中
  456. singleLaneContent = [] # 存储单个车道线的相关信息
  457. allLaneContent = [] # 将singleLaneContent中的车道线存储在allLaneContent中
  458. laneMinXCoordinate = [] # 存储车道线的最小x坐标
  459. laneMaxXCoordinate = [] # 存储车道线的最大x坐标
  460. leftLaneSerialNumber = [] # 左侧车道线簇中的车道线序号
  461. leftLaneBox = [] # 当左侧车道线簇中只有一个车道线时,该车道线的最小外接矩形对应的box
  462. leftLaneAbovePoint = [] # 当左侧车道线簇中只有一个车道线时,该车道线的最小外接矩形最上方的两个顶点坐标
  463. leftLaneKB = [] # 存储最左侧车道线簇所确定的直线的k和b值
  464. leftLaneCenterX = [] # 左侧车道线簇中各车道线中心点的x坐标
  465. leftLaneCenterY = [] # 左侧车道线簇中各车道线中心点的y坐标
  466. rightLaneSerialNumber = [] # 右侧车道线簇中的车道线序号
  467. rightLaneBox = [] # 当右侧车道线簇中只有一个车道线时,该车道线的最小外接矩形对应的box
  468. rightLaneAbovePoint = [] # 当右侧车道线簇中只有一个车道线时,该车道线的最小外接矩形最上方的两个顶点坐标
  469. rightLaneKB = [] # 存储最左侧车道线簇所确定的直线的k和b值
  470. rightLaneCenterX = [] # 右侧车道线簇中各车道线中心点的x坐标
  471. rightLaneCenterY = [] # 右侧车道线簇中各车道线中心点的y坐标
  472. """
  473. """ 将speedRoad最小外接矩形的四个顶点(Xmin,Xmax,Ymin,Ymax)、其最小外接矩形与水平方向的夹角、其最小外接矩形的宽高存储在singleSpeedRoadContent中 """
  474. for cnt in contours: # 道路
  475. if len(cnt) >= 6:
  476. rect = cv2.minAreaRect(cnt)
  477. if rect[1][0] * rect[1][1] > pars['speedRoadArea']: # 过滤掉面积小于阈值的speedRoad
  478. box = cv2.boxPoints(rect).astype(np.int32)
  479. speedRoadXmin = min(box[0][0], box[1][0], box[2][0], box[3][0])
  480. speedRoadXmax = max(box[0][0], box[1][0], box[2][0], box[3][0])
  481. speedRoadYmin = min(box[0][1], box[1][1], box[2][1], box[3][1])
  482. speedRoadYmax = max(box[0][1], box[1][1], box[2][1], box[3][1])
  483. singleSpeedRoadContent.append(speedRoadXmin)
  484. singleSpeedRoadContent.append(speedRoadXmax)
  485. singleSpeedRoadContent.append(speedRoadYmin)
  486. singleSpeedRoadContent.append(speedRoadYmax)
  487. if rect[1][0] <= rect[1][1]:
  488. if rect[2] >= 0 and rect[2] < 90:
  489. speedRoadAngle = rect[2] + 90
  490. elif rect[2] == 90:
  491. speedRoadAngle = 0
  492. else:
  493. if rect[2] >= 0 and rect[2] <= 90:
  494. speedRoadAngle = rect[2]
  495. singleSpeedRoadContent.append(speedRoadAngle)
  496. singleSpeedRoadContent.append(rect[1])
  497. allSpeedRoadContent.append(singleSpeedRoadContent)
  498. singleSpeedRoadContent = []
  499. img3 = cv2.cvtColor(lane_line, cv2.COLOR_BGR2GRAY)
  500. contours, hierarchy = cv2.findContours(img3, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  501. """ 将车道线最小外接矩形四个顶点(Xmin,Xmax,Ymin,Ymax)、车道线最小外接矩形的中心点坐标,车道线矩形框与水平方向的夹角,存储在singleLaneContent中 """
  502. for cnt in contours: # 车道线
  503. if len(cnt) >= 6:
  504. if rect[1][0] * rect[1][1] > pars['laneLineArea'] and min(rect[1]) / max(rect[1]) <= pars['roundness']:
  505. rect = cv2.minAreaRect(cnt)
  506. box = cv2.boxPoints(rect).astype(np.int32)
  507. box = np.array(box)
  508. laneXmin, laneXmax = np.min( box[:,0] ),np.max( box[:,0] )
  509. laneYmin, laneYmax = np.min( box[:,1] ),np.max( box[:,1] )
  510. #laneXmin = min(box[0][0], box[1][0], box[2][0], box[3][0])
  511. #laneXmax = max(box[0][0], box[1][0], box[2][0], box[3][0])
  512. #laneYmin = min(box[0][1], box[1][1], box[2][1], box[3][1])
  513. #laneYmax = max(box[0][1], box[1][1], box[2][1], box[3][1])
  514. singleLaneContent.append(laneXmin) # 将车道线矩形框四个顶点的Xmin,Xmax,Ymin,Ymax存储在singleLaneContent中
  515. singleLaneContent.append(laneXmax)
  516. singleLaneContent.append(laneYmin)
  517. singleLaneContent.append(laneYmax)
  518. if rect[1][0] <= rect[1][1]:
  519. if rect[2] >= 0 and rect[2] < 90:
  520. laneLineAngle = rect[2] + 90
  521. elif rect[2] == 90:
  522. laneLineAngle = 0
  523. else:
  524. if rect[2] >= 0 and rect[2] <= 90:
  525. laneLineAngle = rect[2]
  526. singleLaneContent.append(rect[0]) # 将车道线的中心点坐标存储在singleLaneContent中
  527. singleLaneContent.append(box) # 将车道线的最小外接矩形的顶点坐标存储在singleLaneContent中
  528. singleLaneContent.append(laneLineAngle) # 将车道线矩形框与水平方向的夹角存储在singleLaneContent中
  529. allLaneContent.append(singleLaneContent) # 将车道线存储在allLaneContent中
  530. singleLaneContent = []
  531. if len(allSpeedRoadContent) != 0 and len(allLaneContent) >= 2: # 图像中存在speedRoad且车道线的个数大于等于2
  532. for i in range(len(allLaneContent)):
  533. laneMinXCoordinate.append([allLaneContent[i][0], i]) # 存储车道线的最小x坐标
  534. laneMaxXCoordinate.append([allLaneContent[i][1], i]) # 存储车道线的最大x坐标
  535. laneXCoordinateMin2MaxSort = sorted(laneMinXCoordinate, key=(lambda x: x[0])) # laneXCoordinateMin2MaxSort中存储的是各车道线的x的最小值从小到大排列,后面跟车道线的序号
  536. laneXCoordinateMax2MinSort = sorted(laneMaxXCoordinate, key=(lambda x: x[0]), reverse=True) # laneXCoordinateMax2MinSort中存储的是各车道线的x的最大值从大到小排列,后面跟车道线的序号
  537. # 计算最左侧车道线簇所确定的直线的k和b值,将其存储在leftLaneKB中
  538. leftLaneKB = calculateLeftLane_k_b(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, leftLaneBox, leftLaneAbovePoint, leftLaneKB, leftLaneCenterX, leftLaneCenterY, pars)
  539. # 计算最右侧车道线簇所确定的直线的k和b值,将其存储在rightLaneKB中
  540. rightLaneKB = calculateRightLane_k_b(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, rightLaneBox, rightLaneAbovePoint, rightLaneKB, rightLaneCenterX, rightLaneCenterY, pars)
  541. count = 0
  542. for i in range(0, len(pars['vehicleCoordinate']), 2):
  543. vehicleAreaList = []
  544. mask = np.zeros(image_vehicle.shape[:2], dtype="uint8")
  545. x0 = int(pars['vehicleCoordinate'][i][0] * pars['ZoomFactor']['x'])
  546. y0 = int(pars['vehicleCoordinate'][i][1] * pars['ZoomFactor']['y'])
  547. x1 = int(pars['vehicleCoordinate'][i + 1][0] * pars['ZoomFactor']['x'])
  548. y1 = int(pars['vehicleCoordinate'][i + 1][1] * pars['ZoomFactor']['y'])
  549. cv2.rectangle(mask, (x0, y0), (x1, y1), 255, -1, lineType=cv2.LINE_AA)
  550. image_vehicle_masked = cv2.bitwise_and(image_vehicle, image_vehicle, mask=mask)
  551. img2 = cv2.cvtColor(image_vehicle_masked, cv2.COLOR_BGR2GRAY)
  552. contours2, hierarchy2 = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
  553. """ 将符合标准的vehicle信息存储在complianceVehicle中,将不符合标准的vehicle信息存储在NonComplianceVehicle中 """
  554. ##主要做面积的过滤。
  555. if len(contours2) != 0:
  556. if len(contours2) > 1: # 这里我通过比较同一检测框内各个contours对应的最小外接矩形的面积,来剔除那些存在干扰的contours,最终只保留一个contours
  557. for j in range(len(contours2)):
  558. contours_j = contours2[j]
  559. rect = cv2.minAreaRect(contours_j)
  560. vehicleAreaList.append(rect[1][0] * rect[1][1])
  561. if max(vehicleAreaList) >= pars['vehicleArea']:
  562. maxAreaIndex = vehicleAreaList.index(max(vehicleAreaList))
  563. maxAreacontours = contours2[maxAreaIndex]
  564. if len(maxAreacontours) >= 6:
  565. vehicleContours.append(maxAreacontours)
  566. complianceVehicle.append(dets[count])
  567. else:
  568. dets[int(i / 2)].append(0)
  569. dets[int(i / 2)].append(0)
  570. NonComplianceVehicle.append(dets[int(i / 2)])
  571. else:
  572. dets[int(i / 2)].append(0)
  573. dets[int(i / 2)].append(0)
  574. NonComplianceVehicle.append(dets[int(i / 2)])
  575. elif len(contours2) == 1:
  576. contours_j = contours2[0]
  577. rect = cv2.minAreaRect(contours_j)
  578. if rect[1][0] * rect[1][1] >= pars['vehicleArea']:
  579. if len(contours_j) >= 6:
  580. vehicleContours.append(contours_j)
  581. complianceVehicle.append(dets[count])
  582. else:
  583. dets[int(i / 2)].append(0)
  584. dets[int(i / 2)].append(0)
  585. NonComplianceVehicle.append(dets[int(i / 2)])
  586. else:
  587. dets[int(i / 2)].append(0)
  588. dets[int(i / 2)].append(0)
  589. NonComplianceVehicle.append(dets[int(i / 2)])
  590. else:
  591. dets[int(i/2)].append(0)
  592. dets[int(i/2)].append(0)
  593. NonComplianceVehicle.append(dets[int(i/2)])
  594. count += 1
  595. dets = complianceVehicle
  596. """ 对vehicle是否在speedRoad上进行判断,并计算违章得分 """
  597. if len(vehicleContours) != 0:
  598. for i in range(len(vehicleContours)):
  599. rect = cv2.minAreaRect(vehicleContours[i])
  600. if len(allSpeedRoadContent) != 0:
  601. for j in range(len(allSpeedRoadContent)):
  602. # 判断车辆矩形框的中心点坐标是否在道路矩形框Xmin,Xmax,Ymin和Ymax的范围内;
  603. if (rect[0][0] > allSpeedRoadContent[j][0] and rect[0][0] < allSpeedRoadContent[j][1]) and (rect[0][1] > allSpeedRoadContent[j][2] and rect[0][1] < allSpeedRoadContent[j][3]):
  604. # 将Box2D结构作为输入并返回4个角点。
  605. box = cv2.boxPoints(rect).astype(np.int32)
  606. # 比较车辆矩形框四个顶点的坐标是否都在道路矩形框Xmin,Xmax,Ymin和Ymax的范围内,若都在,则说明该车辆在这条道路上。
  607. if (box[0][0] >= allSpeedRoadContent[j][0] and box[0][0] <= allSpeedRoadContent[j][1] and box[0][1] >= allSpeedRoadContent[j][2] and box[0][1] <= allSpeedRoadContent[j][3]) and (box[1][0] >= allSpeedRoadContent[j][0] and box[1][0] <= allSpeedRoadContent[j][1] and box[1][1] >= allSpeedRoadContent[j][2] and box[1][1] <= allSpeedRoadContent[j][3]) and (box[2][0] >= allSpeedRoadContent[j][0] and box[2][0] <= allSpeedRoadContent[j][1] and box[2][1] >= allSpeedRoadContent[j][2] and box[2][1] <= allSpeedRoadContent[j][3]) and (box[3][0] >= allSpeedRoadContent[j][0] and box[3][0] <= allSpeedRoadContent[j][1] and box[3][1] >= allSpeedRoadContent[j][2] and box[3][1] <= allSpeedRoadContent[j][3]):
  608. dets[i].append(0) # 给违章得分占位
  609. dets[i].append(0) # 给违章类别占位
  610. # 当车道线个数至少有两条时,才计算违章得分
  611. if len(allLaneContent) >= 2:
  612. if rect[0][1] < leftLaneKB[0] * rect[0][0] + leftLaneKB[1]:
  613. distanceCenterToLine = abs(leftLaneKB[0] * rect[0][0] - rect[0][1] + leftLaneKB[1]) / math.sqrt(leftLaneKB[0] * leftLaneKB[0] + 1)
  614. if distanceCenterToLine >= min(rect[1]) / 2:
  615. dets[i][6] = 1
  616. dets[i][7] = 1
  617. else:
  618. score4 = distanceCenterToLine / (min(rect[1]) / 2)
  619. dets[i][6] = score4
  620. dets[i][7] = 1
  621. elif rect[0][1] < rightLaneKB[0] * rect[0][0] + rightLaneKB[1]:
  622. distanceCenterToLine = abs(rightLaneKB[0] * rect[0][0] - rect[0][1] + rightLaneKB[1]) / math.sqrt(rightLaneKB[0] * rightLaneKB[0] + 1)
  623. if distanceCenterToLine >= min(rect[1]) / 2:
  624. dets[i][6] = 1
  625. dets[i][7] = 1
  626. else:
  627. score4 = distanceCenterToLine / (min(rect[1]) / 2)
  628. dets[i][6] = score4
  629. dets[i][7] = 1
  630. break
  631. # 如果分割图像中不存在speedRoad,则无法进行违章判定,将所有车辆的违章类别设为0,即没有违章
  632. if len(dets[i]) < 8:
  633. dets[i].append(0) # 违章得分为0
  634. dets[i].append(0) # 0表示没有违章
  635. targetList = dets
  636. for i in range(len(NonComplianceVehicle)):
  637. targetList.append(NonComplianceVehicle[i]) # 将所有车辆的信息合并到一起
  638. # 目标对象, [[cls, x0, y0, x1, y1, score, 违章得分, 违章类别], ...]
  639. else:
  640. targetList = NonComplianceVehicle
  641. t6 = time.time()
  642. time_infos = 'postTime:%.2f (分割时间:%.2f, findContours:%.2f ruleJudge:%.2f)' % (
  643. get_ms(t6, t3), get_ms(t4, t3), get_ms(t5, t4), get_ms(t6, t5))
  644. targetList = [ [ b[7] ,*b[1:5],b[6] if b[6]>0 else b[5]] for b in targetList ]
  645. #最终输出格式:[[cls, x0, y0, x1, y1, 车辆得分, 违章停车得分, 违章类别], ...]
  646. return targetList, time_infos