背景知識
-
marking line
停車位包括分隔線和進入線,垂直停車位和水平停車位的marking line的長度關系是不一樣的。 -
Directional Marking-Point
Marking-Point
:entrance-lines和separating-lines的相交處:
朝向:
T-shaped:沿着兌成線的方向;
L-shaped:順時針旋轉90°后會和其他marking-line重合的marking-line的指向。
所以一個Directional Marking Point可以用如下向量表示:
其中(x,y)是中心位置,二進制值s表示形狀,\(\theta\)表示極坐標系下朝向角度坐標。
網絡流程
Directional marking-point regression
通過CNN預測一張(6, S, S)的grid cell特征圖,6分別代表:
- (cx, cy):
Directional Marking-Point
的中心點相對cell左上角偏移; - s:形狀
- cos, sin:方向(預測三角函數實現時更加魯棒)
- C:落在該cell內的置信度
S的選取需要考慮到:盡量避免多個DMP落在同時落在一個cell內;計算量不能太大。
Parking-slot inference
利用先驗知識對回歸到的marking-point進行slot匹配,其中先驗知識是指:垂直停車位和水平停車位的進入線的長度最大值和最小值
過濾:
- 距離太遠的匹配;
- 不是鄰接的匹配。
組合: - DMP屬於規定的五類;
- 組合屬於規定的16種。
處理流程:
for i in range(num_detected-1):
for j in range(i+1, num_detected):
# step1:distance
if distance(i, j) not belong to (vertical entrance) and (parallel entrance):
continue
# step2:pass through
if passthrough_third(i, j):
continue
# step3: valid pair
if pair_marking_points(i, j):
slots.append(i, j)
結果展示
利用先驗知識:垂直停車位和水平停車位的分隔線的長度,畫出停車位(只畫兩條分隔線,一條進入線)
訓練
只有marking-point回歸部分需要學習
訓練時懲罰所有gri cell內的置信度,以及有marking point的cell的位置、角度、類別;都采用誤差平方和:
loss = (prediction - objective) ** 2
預測結果匹配之后格式為:
predictions:
[
(image0)[ Slot(conf, [x1,x2,y1,y2]), Slot(), Slot(),...],
(image1)[ Slot(conf, [x1,x2,y1,y2]), Slot(), Slot(),...],
...
]
對於每張圖片:
每個slot依次去和該張圖片預測結果中的所有slot去匹配,將所有匹配到的slot中置信度最高的置為TP。其中匹配規則是二者的(x1, y1)之間的距離和(x2,y2)之間的距離均小於設定值。
未被匹配上的預測slot則為FP。根據TP和FP的置信度計算PR
for img in imgs:
for slot in img_slots:
idx = find_matched_pre(slot, img_pre)
TP.append(idx)
處理細節
CNN輸出處理:[置信度,...,x偏移, y偏移,cos, sin]
for i in range(prediction.shape[1]):
for j in range(prediction.shape[2]):
if prediction[0, i, j] >= thresh:
# 坐標處理
xval = (j + prediction[2, i, j]) / prediction.shape[2] #歸一化
yval = (i + prediction[3, i, j]) / prediction.shape[1]
# 角度處理
cos_value = prediction[4, i, j]
sin_value = prediction[5, i, j]
direction = math.atan2(sin_value, cos_value)
經過NMS處理過后每張圖片得到的預測值為:
# pred_points
[
(0.9991379, MarkingPoint(x=0.40118189714848995, y=0.0956118255853653, direction=-3.0824694541150253, shape=0.00021467496)),
(0.99695575, MarkingPoint(x=0.39340371266007423, y=0.378861726494506, direction=-3.0372144599925375, shape=0.00062975887)),
(0.996929, MarkingPoint(x=0.37662082735914737, y=0.6465909797698259, direction=-3.103863140682919, shape=0.004871699)),
...
]
畫圖時對坐標和角度的處理:預測偏移加上grid cell后除以特征圖歸一化,再乘以原圖得到原圖尺寸
p0_x = width * marking_point.x - 0.5 #600 * 0.4011 -0.5
p0_y = height * marking_point.y - 0.5
cos_val = math.cos(marking_point.direction)
sin_val = math.sin(marking_point.direction)
有了P0和θ角度之后,如果形狀是L形(shape>0.5)則取P2不取P3,否則為T形則取P2-P3,需要注意的是此處先驗為長度均為50