背景知识
-
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