|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- import numpy as np
- import cv2,time,math
-
- def get_ms(time2, time1):
- return (time2-time1)*1000.0
-
-
- # 根据两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0 (a >= 0)
- def getLinearEquation(p1x, p1y, p2x, p2y):
- sign = 1
- a = p2y - p1y
- if a < 0:
- sign = -1
- a = sign * a
- b = sign * (p1x - p2x)
- c = sign * (p1y * p2x - p1x * p2y)
- # y=kx+bb
- k = -a/(b+0.0000000001)
- bb = -c/(b+0.000000000001)
- return k, bb
-
-
- # 根据多点坐标拟合直线
- def best_fit(X, Y):
- xbar = sum(X) / len(X)
- ybar = sum(Y) / len(Y)
- n = len(X) # or len(Y)
- numer = sum([xi * yi for xi, yi in zip(X, Y)]) - n * xbar * ybar
- denum = sum([xi ** 2 for xi in X]) - n * xbar ** 2
- k = numer / denum
- b = ybar - k * xbar
- # print('best fit line:\ny = {:.2f}x + {:.2f}'.format(k, b))
- return k, b
-
-
- # 对于左侧车道线,返回两车道线中心点连线确定的角度,radian2表示弧度
- def calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber):
- 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]))
- lanesCenterAngle1 = 180 - int(radian2 * 180 / math.pi)
- lanesCenterAngle2 = int(radian2 * 180 / math.pi)
- return lanesCenterAngle1, lanesCenterAngle2
-
-
- # 对于右侧车道线,返回两车道线中心点连线确定的角度,radian2表示弧度
- def calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber):
- 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]))
- lanesCenterAngle3 = 180 - int(radian2 * 180 / math.pi)
- lanesCenterAngle4 = int(radian2 * 180 / math.pi)
- return lanesCenterAngle3, lanesCenterAngle4
-
-
- # 从所有车道线中确定位于最左侧的车道线簇,并将各车道线对应的序号存储在leftLaneSerialNumber中
- def findLeftLanes(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, pars):
- for i in range(len(laneXCoordinateMin2MaxSort)): # 求最左侧车道线
- 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坐标。 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- 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]))
- lanesCenterAngle1 = 180 - int(radian1 * 180 / math.pi)
- if len(leftLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- 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]): # 这种情况对应左上角和右下角的车道线,计算角度
- 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]))
- lanesCenterAngle1 = int(radian1 * 180 / math.pi)
- if len(leftLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][0] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle1 = 90
- if len(leftLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[laneXCoordinateMin2MaxSort[i][1]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle1 = 0
- if len(leftLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMin2MaxSort[i][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i][1])
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateLeftLanesAngle(allLaneContent, leftLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][0] == allLaneContent[leftLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- elif allLaneContent[leftLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMin2MaxSort[i + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMin2MaxSort[i + 1][1] not in leftLaneSerialNumber:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[i + 1][1])
- else:
- break
- return leftLaneSerialNumber
-
-
- # 从所有车道线中确定位于最右侧的车道线簇,并将各车道线对应的序号存储在rightLaneSerialNumber中
- def findRightLanes(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, pars):
- for r in range(len(laneXCoordinateMax2MinSort)): # 求最右侧车道线
- 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坐标。 车辆的相对位置不同,计算角度方法也不同。
- 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]))
- lanesCenterAngle1 = 180 - int(radian1 * 180 / math.pi)
- if len(rightLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- 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]):
- 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]))
- lanesCenterAngle1 = int(radian1 * 180 / math.pi)
- if len(rightLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][0] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][0]:
- lanesCenterAngle1 = 90
- if len(rightLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[laneXCoordinateMax2MinSort[r][1]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]:
- lanesCenterAngle1 = 0
- if len(rightLaneSerialNumber) == 0: # 刚开始判断
- if abs(allLaneContent[laneXCoordinateMax2MinSort[r][1]][6] - lanesCenterAngle1) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r][1])
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- else:
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[0]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- 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]): # 车辆的相对位置不同,计算角度方法也不同。这种情况对应右上角和左下角的车道线,计算角度
- if abs(lanesCenterAngle1 - calculateRightLanesAngle(allLaneContent, rightLaneSerialNumber)[1]) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][0] == allLaneContent[rightLaneSerialNumber[-1]][4][0]: # 两车道线的最小x坐标相同
- lanesCenterAngle2 = 90
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- elif allLaneContent[rightLaneSerialNumber[0]][4][1] == allLaneContent[laneXCoordinateMax2MinSort[r + 1][1]][4][1]: # 两车道线的y坐标相同
- lanesCenterAngle2 = 0
- if abs(lanesCenterAngle1 - lanesCenterAngle2) <= pars['laneAngleCha']:
- if laneXCoordinateMax2MinSort[r + 1][1] not in rightLaneSerialNumber:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[r + 1][1])
- else:
- break
- return rightLaneSerialNumber
-
-
- # 返回最左侧车道线簇所确定的直线的k和b值,将其存储在leftLaneKB中
- def calculateLeftLane_k_b(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, leftLaneBox, leftLaneAbovePoint, leftLaneKB, leftLaneCenterX, leftLaneCenterY, pars):
- leftLaneSerialNumber = findLeftLanes(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, pars)
- if len(leftLaneSerialNumber) == 0:
- leftLaneSerialNumber.append(laneXCoordinateMin2MaxSort[0][1]) # leftLaneSerialNumber中存放的是最左侧的车道线簇中的各车道线的序号
- if len(leftLaneSerialNumber) == 1:
- centerCoordinate = allLaneContent[leftLaneSerialNumber[0]][4] # 最小外接矩形的中心点坐标
- box = allLaneContent[leftLaneSerialNumber[0]][5]
- leftLaneBox.append([box[0][0], box[0][1]])
- leftLaneBox.append([box[1][0], box[1][1]])
- leftLaneBox.append([box[2][0], box[2][1]])
- leftLaneBox.append([box[3][0], box[3][1]])
- for i in range(len(leftLaneBox)):
- if leftLaneBox[i][1] < centerCoordinate[1]:
- leftLaneAbovePoint.append(leftLaneBox[i])
- point1_l = [(leftLaneAbovePoint[0][0] + leftLaneAbovePoint[1][0]) / 2, (leftLaneAbovePoint[0][1] + leftLaneAbovePoint[1][1]) / 2]
- point2_l = [centerCoordinate[0], centerCoordinate[1]]
- k_l, b_l = getLinearEquation(point1_l[0], point1_l[1], point2_l[0], point2_l[1])
- leftLaneKB.append(k_l)
- leftLaneKB.append(b_l)
- else:
- for i in range(len(leftLaneSerialNumber)):
- leftLaneCenterX.append(allLaneContent[leftLaneSerialNumber[i]][4][0]) # leftLaneCenterX中存储的是各车道线中心点的x坐标
- leftLaneCenterY.append(allLaneContent[leftLaneSerialNumber[i]][4][1]) # leftLaneCenterY中存储的是各车道线中心点的y坐标
- k_l, b_l = best_fit(leftLaneCenterX, leftLaneCenterY)
- leftLaneKB.append(k_l)
- leftLaneKB.append(b_l)
- return leftLaneKB
-
-
- # 返回最右侧车道线簇所确定的直线的k和b值,将其存储在rightLaneKB中
- def calculateRightLane_k_b(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, rightLaneBox, rightLaneAbovePoint, rightLaneKB, rightLaneCenterX, rightLaneCenterY, pars):
- rightLaneSerialNumber = findRightLanes(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, pars)
- if len(rightLaneSerialNumber) == 0:
- rightLaneSerialNumber.append(laneXCoordinateMax2MinSort[0][1]) # rightLaneSerialNumber中存放的是最右侧的车道线簇中的各车道线的序号
- if len(rightLaneSerialNumber) == 1:
- centerCoordinate = allLaneContent[rightLaneSerialNumber[0]][4] # 最小外接矩形的中心点坐标
- box = allLaneContent[rightLaneSerialNumber[0]][5]
- rightLaneBox.append([box[0][0], box[0][1]])
- rightLaneBox.append([box[1][0], box[1][1]])
- rightLaneBox.append([box[2][0], box[2][1]])
- rightLaneBox.append([box[3][0], box[3][1]])
- for i in range(len(rightLaneBox)):
- if rightLaneBox[i][1] < centerCoordinate[1]:
- rightLaneAbovePoint.append(rightLaneBox[i])
- point1_r = [(rightLaneAbovePoint[0][0] + rightLaneAbovePoint[1][0]) / 2, (rightLaneAbovePoint[0][1] + rightLaneAbovePoint[1][1]) / 2]
- point2_r = [centerCoordinate[0], centerCoordinate[1]]
- k_r, b_r = getLinearEquation(point1_r[0], point1_r[1], point2_r[0], point2_r[1])
- rightLaneKB.append(k_r)
- rightLaneKB.append(b_r)
- else:
- for i in range(len(rightLaneSerialNumber)):
- rightLaneCenterX.append(allLaneContent[rightLaneSerialNumber[i]][4][0]) # rightLaneCenterX中存储的是各车道线中心点的x坐标
- rightLaneCenterY.append(allLaneContent[rightLaneSerialNumber[i]][4][1]) # rightLaneCenterY中存储的是各车道线中心点的y坐标
- k_r, b_r = best_fit(rightLaneCenterX, rightLaneCenterY)
- rightLaneKB.append(k_r)
- rightLaneKB.append(b_r)
- return rightLaneKB
-
-
- def mixNoParking_road_postprocess(dets, mask, pars):
- """
- 对于字典traffic_dict中的各个键,说明如下:
- speedRoadArea:speedRoad的最小外接矩形的面积
- vehicleCoordinate:是一个列表,用于存储被检测出的vehicle的坐标(vehicle检测模型)
- roundness:圆度 ,lane的长与宽的比率,作为判定是否为车道线的标准之一
- 'cls':类别号
- vehicleArea:vehicle的最小外接矩形的面积
- laneLineArea:车道线的最小外接矩形的面积
- laneAngleCha:车道线的角度差值阈值
- contoursNum:counters中的顶点个数
- ZoomFactor:图像在H和W方向上的缩放因子,其值小于1
- 最终输出格式:[[cls, x0, y0, x1, y1, 车辆得分, 违章停车得分, 违章类别], ...]
- 违章类别:0表示正常车辆,1表示违章车辆
- """
- det_cors = []
- for bb in dets:
- det_cors.append((int(bb[1]), int(bb[2])))
- det_cors.append((int(bb[3]), int(bb[4])))
- pars['vehicleCoordinate'] = det_cors
-
- H, W = mask.shape[0:2]
- scaleH = pars['modelSize'][1] / H # 自适应调整缩放比例
- scaleW = pars['modelSize'][0] / W
- pars['ZoomFactor'] = {'x': scaleH, 'y': scaleW}
- new_hw = [int(H * scaleH), int(W * scaleW)]
- mask = cv2.resize(mask, (new_hw[1], new_hw[0]))
- if len(mask.shape) == 3:
- mask = mask[:, :, 0]
-
- t3 = time.time()
- vehicleContours = [] # 存储一副图像中vehicles的contours
- image_speedRoad = mask.copy()
- image_vehicle = mask.copy()
- lane_line = mask.copy()
- image_speedRoad[image_speedRoad == 2] = 0 # 将vehicle过滤掉,只包含背景和speedRoad
- image_vehicle[image_vehicle == 1] = 0 # 将speedRoad过滤掉,只包含背景和vehicle
- lane_line[lane_line < 3] = 0
- image_speedRoad = cv2.cvtColor(np.uint8(image_speedRoad), cv2.COLOR_RGB2BGR) # 道路
- image_vehicle = cv2.cvtColor(np.uint8(image_vehicle), cv2.COLOR_RGB2BGR) # 车辆
- lane_line = cv2.cvtColor(np.uint8(lane_line), cv2.COLOR_RGB2BGR) #
-
- t4 = time.time()
- img1 = cv2.cvtColor(image_speedRoad, cv2.COLOR_BGR2GRAY)
- contours, hierarchy = cv2.findContours(img1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
- t5 = time.time()
-
- # 创建列表
- 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))
-
- """
- 列表说明如下:
- singleSpeedRoadContent = [] # 过渡使用
- allSpeedRoadContent = [] # 存放speedRoad坐标(Xmin,Xmax,Ymin,Ymax)、speedRoadAngle和speedRoad的宽高
- complianceVehicle = [] # 将符合标准的vehicle信息存储在complianceVehicle中
- NonComplianceVehicle = [] # 将不符合标准的vehicle信息存储在NonComplianceVehicle中
- singleLaneContent = [] # 存储单个车道线的相关信息
- allLaneContent = [] # 将singleLaneContent中的车道线存储在allLaneContent中
- laneMinXCoordinate = [] # 存储车道线的最小x坐标
- laneMaxXCoordinate = [] # 存储车道线的最大x坐标
- leftLaneSerialNumber = [] # 左侧车道线簇中的车道线序号
- leftLaneBox = [] # 当左侧车道线簇中只有一个车道线时,该车道线的最小外接矩形对应的box
- leftLaneAbovePoint = [] # 当左侧车道线簇中只有一个车道线时,该车道线的最小外接矩形最上方的两个顶点坐标
- leftLaneKB = [] # 存储最左侧车道线簇所确定的直线的k和b值
- leftLaneCenterX = [] # 左侧车道线簇中各车道线中心点的x坐标
- leftLaneCenterY = [] # 左侧车道线簇中各车道线中心点的y坐标
- rightLaneSerialNumber = [] # 右侧车道线簇中的车道线序号
- rightLaneBox = [] # 当右侧车道线簇中只有一个车道线时,该车道线的最小外接矩形对应的box
- rightLaneAbovePoint = [] # 当右侧车道线簇中只有一个车道线时,该车道线的最小外接矩形最上方的两个顶点坐标
- rightLaneKB = [] # 存储最左侧车道线簇所确定的直线的k和b值
- rightLaneCenterX = [] # 右侧车道线簇中各车道线中心点的x坐标
- rightLaneCenterY = [] # 右侧车道线簇中各车道线中心点的y坐标
- """
-
- """ 将speedRoad最小外接矩形的四个顶点(Xmin,Xmax,Ymin,Ymax)、其最小外接矩形与水平方向的夹角、其最小外接矩形的宽高存储在singleSpeedRoadContent中 """
- for cnt in contours: # 道路
- if len(cnt) >= 6:
- rect = cv2.minAreaRect(cnt)
- if rect[1][0] * rect[1][1] > pars['speedRoadArea']: # 过滤掉面积小于阈值的speedRoad
- box = cv2.boxPoints(rect).astype(np.int32)
- speedRoadXmin = min(box[0][0], box[1][0], box[2][0], box[3][0])
- speedRoadXmax = max(box[0][0], box[1][0], box[2][0], box[3][0])
- speedRoadYmin = min(box[0][1], box[1][1], box[2][1], box[3][1])
- speedRoadYmax = max(box[0][1], box[1][1], box[2][1], box[3][1])
- singleSpeedRoadContent.append(speedRoadXmin)
- singleSpeedRoadContent.append(speedRoadXmax)
- singleSpeedRoadContent.append(speedRoadYmin)
- singleSpeedRoadContent.append(speedRoadYmax)
- if rect[1][0] <= rect[1][1]:
- if rect[2] >= 0 and rect[2] < 90:
- speedRoadAngle = rect[2] + 90
- elif rect[2] == 90:
- speedRoadAngle = 0
- else:
- if rect[2] >= 0 and rect[2] <= 90:
- speedRoadAngle = rect[2]
- singleSpeedRoadContent.append(speedRoadAngle)
- singleSpeedRoadContent.append(rect[1])
- allSpeedRoadContent.append(singleSpeedRoadContent)
- singleSpeedRoadContent = []
-
- img3 = cv2.cvtColor(lane_line, cv2.COLOR_BGR2GRAY)
- contours, hierarchy = cv2.findContours(img3, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
-
- """ 将车道线最小外接矩形四个顶点(Xmin,Xmax,Ymin,Ymax)、车道线最小外接矩形的中心点坐标,车道线矩形框与水平方向的夹角,存储在singleLaneContent中 """
- for cnt in contours: # 车道线
- if len(cnt) >= 6:
- if rect[1][0] * rect[1][1] > pars['laneLineArea'] and min(rect[1]) / max(rect[1]) <= pars['roundness']:
- rect = cv2.minAreaRect(cnt)
- box = cv2.boxPoints(rect).astype(np.int32)
- box = np.array(box)
- laneXmin, laneXmax = np.min( box[:,0] ),np.max( box[:,0] )
- laneYmin, laneYmax = np.min( box[:,1] ),np.max( box[:,1] )
-
- #laneXmin = min(box[0][0], box[1][0], box[2][0], box[3][0])
- #laneXmax = max(box[0][0], box[1][0], box[2][0], box[3][0])
- #laneYmin = min(box[0][1], box[1][1], box[2][1], box[3][1])
- #laneYmax = max(box[0][1], box[1][1], box[2][1], box[3][1])
- singleLaneContent.append(laneXmin) # 将车道线矩形框四个顶点的Xmin,Xmax,Ymin,Ymax存储在singleLaneContent中
- singleLaneContent.append(laneXmax)
- singleLaneContent.append(laneYmin)
- singleLaneContent.append(laneYmax)
- if rect[1][0] <= rect[1][1]:
- if rect[2] >= 0 and rect[2] < 90:
- laneLineAngle = rect[2] + 90
- elif rect[2] == 90:
- laneLineAngle = 0
- else:
- if rect[2] >= 0 and rect[2] <= 90:
- laneLineAngle = rect[2]
- singleLaneContent.append(rect[0]) # 将车道线的中心点坐标存储在singleLaneContent中
- singleLaneContent.append(box) # 将车道线的最小外接矩形的顶点坐标存储在singleLaneContent中
- singleLaneContent.append(laneLineAngle) # 将车道线矩形框与水平方向的夹角存储在singleLaneContent中
- allLaneContent.append(singleLaneContent) # 将车道线存储在allLaneContent中
- singleLaneContent = []
-
- if len(allSpeedRoadContent) != 0 and len(allLaneContent) >= 2: # 图像中存在speedRoad且车道线的个数大于等于2
- for i in range(len(allLaneContent)):
- laneMinXCoordinate.append([allLaneContent[i][0], i]) # 存储车道线的最小x坐标
- laneMaxXCoordinate.append([allLaneContent[i][1], i]) # 存储车道线的最大x坐标
- laneXCoordinateMin2MaxSort = sorted(laneMinXCoordinate, key=(lambda x: x[0])) # laneXCoordinateMin2MaxSort中存储的是各车道线的x的最小值从小到大排列,后面跟车道线的序号
- laneXCoordinateMax2MinSort = sorted(laneMaxXCoordinate, key=(lambda x: x[0]), reverse=True) # laneXCoordinateMax2MinSort中存储的是各车道线的x的最大值从大到小排列,后面跟车道线的序号
-
- # 计算最左侧车道线簇所确定的直线的k和b值,将其存储在leftLaneKB中
- leftLaneKB = calculateLeftLane_k_b(allLaneContent, laneXCoordinateMin2MaxSort, leftLaneSerialNumber, leftLaneBox, leftLaneAbovePoint, leftLaneKB, leftLaneCenterX, leftLaneCenterY, pars)
- # 计算最右侧车道线簇所确定的直线的k和b值,将其存储在rightLaneKB中
- rightLaneKB = calculateRightLane_k_b(allLaneContent, laneXCoordinateMax2MinSort, rightLaneSerialNumber, rightLaneBox, rightLaneAbovePoint, rightLaneKB, rightLaneCenterX, rightLaneCenterY, pars)
-
- count = 0
- for i in range(0, len(pars['vehicleCoordinate']), 2):
- vehicleAreaList = []
- mask = np.zeros(image_vehicle.shape[:2], dtype="uint8")
- x0 = int(pars['vehicleCoordinate'][i][0] * pars['ZoomFactor']['x'])
- y0 = int(pars['vehicleCoordinate'][i][1] * pars['ZoomFactor']['y'])
- x1 = int(pars['vehicleCoordinate'][i + 1][0] * pars['ZoomFactor']['x'])
- y1 = int(pars['vehicleCoordinate'][i + 1][1] * pars['ZoomFactor']['y'])
- cv2.rectangle(mask, (x0, y0), (x1, y1), 255, -1, lineType=cv2.LINE_AA)
- image_vehicle_masked = cv2.bitwise_and(image_vehicle, image_vehicle, mask=mask)
- img2 = cv2.cvtColor(image_vehicle_masked, cv2.COLOR_BGR2GRAY)
- contours2, hierarchy2 = cv2.findContours(img2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
-
- """ 将符合标准的vehicle信息存储在complianceVehicle中,将不符合标准的vehicle信息存储在NonComplianceVehicle中 """
- ##主要做面积的过滤。
- if len(contours2) != 0:
- if len(contours2) > 1: # 这里我通过比较同一检测框内各个contours对应的最小外接矩形的面积,来剔除那些存在干扰的contours,最终只保留一个contours
- for j in range(len(contours2)):
- contours_j = contours2[j]
- rect = cv2.minAreaRect(contours_j)
- vehicleAreaList.append(rect[1][0] * rect[1][1])
- if max(vehicleAreaList) >= pars['vehicleArea']:
- maxAreaIndex = vehicleAreaList.index(max(vehicleAreaList))
- maxAreacontours = contours2[maxAreaIndex]
- if len(maxAreacontours) >= 6:
- vehicleContours.append(maxAreacontours)
- complianceVehicle.append(dets[count])
- else:
- dets[int(i / 2)].append(0)
- dets[int(i / 2)].append(0)
- NonComplianceVehicle.append(dets[int(i / 2)])
- else:
- dets[int(i / 2)].append(0)
- dets[int(i / 2)].append(0)
- NonComplianceVehicle.append(dets[int(i / 2)])
- elif len(contours2) == 1:
- contours_j = contours2[0]
- rect = cv2.minAreaRect(contours_j)
- if rect[1][0] * rect[1][1] >= pars['vehicleArea']:
- if len(contours_j) >= 6:
- vehicleContours.append(contours_j)
- complianceVehicle.append(dets[count])
- else:
- dets[int(i / 2)].append(0)
- dets[int(i / 2)].append(0)
- NonComplianceVehicle.append(dets[int(i / 2)])
- else:
- dets[int(i / 2)].append(0)
- dets[int(i / 2)].append(0)
- NonComplianceVehicle.append(dets[int(i / 2)])
- else:
- dets[int(i/2)].append(0)
- dets[int(i/2)].append(0)
- NonComplianceVehicle.append(dets[int(i/2)])
- count += 1
- dets = complianceVehicle
-
- """ 对vehicle是否在speedRoad上进行判断,并计算违章得分 """
- if len(vehicleContours) != 0:
- for i in range(len(vehicleContours)):
- rect = cv2.minAreaRect(vehicleContours[i])
- if len(allSpeedRoadContent) != 0:
- for j in range(len(allSpeedRoadContent)):
- # 判断车辆矩形框的中心点坐标是否在道路矩形框Xmin,Xmax,Ymin和Ymax的范围内;
- 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]):
- # 将Box2D结构作为输入并返回4个角点。
- box = cv2.boxPoints(rect).astype(np.int32)
- # 比较车辆矩形框四个顶点的坐标是否都在道路矩形框Xmin,Xmax,Ymin和Ymax的范围内,若都在,则说明该车辆在这条道路上。
- 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]):
- dets[i].append(0) # 给违章得分占位
- dets[i].append(0) # 给违章类别占位
- # 当车道线个数至少有两条时,才计算违章得分
- if len(allLaneContent) >= 2:
- if rect[0][1] < leftLaneKB[0] * rect[0][0] + leftLaneKB[1]:
- distanceCenterToLine = abs(leftLaneKB[0] * rect[0][0] - rect[0][1] + leftLaneKB[1]) / math.sqrt(leftLaneKB[0] * leftLaneKB[0] + 1)
- if distanceCenterToLine >= min(rect[1]) / 2:
- dets[i][6] = 1
- dets[i][7] = 1
- else:
- score4 = distanceCenterToLine / (min(rect[1]) / 2)
- dets[i][6] = score4
- dets[i][7] = 1
- elif rect[0][1] < rightLaneKB[0] * rect[0][0] + rightLaneKB[1]:
- distanceCenterToLine = abs(rightLaneKB[0] * rect[0][0] - rect[0][1] + rightLaneKB[1]) / math.sqrt(rightLaneKB[0] * rightLaneKB[0] + 1)
- if distanceCenterToLine >= min(rect[1]) / 2:
- dets[i][6] = 1
- dets[i][7] = 1
- else:
- score4 = distanceCenterToLine / (min(rect[1]) / 2)
- dets[i][6] = score4
- dets[i][7] = 1
- break
- # 如果分割图像中不存在speedRoad,则无法进行违章判定,将所有车辆的违章类别设为0,即没有违章
- if len(dets[i]) < 8:
- dets[i].append(0) # 违章得分为0
- dets[i].append(0) # 0表示没有违章
- targetList = dets
- for i in range(len(NonComplianceVehicle)):
- targetList.append(NonComplianceVehicle[i]) # 将所有车辆的信息合并到一起
- # 目标对象, [[cls, x0, y0, x1, y1, score, 违章得分, 违章类别], ...]
- else:
- targetList = NonComplianceVehicle
-
- t6 = time.time()
- time_infos = 'postTime:%.2f (分割时间:%.2f, findContours:%.2f ruleJudge:%.2f)' % (
- get_ms(t6, t3), get_ms(t4, t3), get_ms(t5, t4), get_ms(t6, t5))
-
- targetList = [ [ b[7] ,*b[1:5],b[6] if b[6]>0 else b[5]] for b in targetList ]
- #最终输出格式:[[cls, x0, y0, x1, y1, 车辆得分, 违章停车得分, 违章类别], ...]
-
-
- return targetList, time_infos
|