LaneATT调试笔记

代码地址为 https://github.com/lucastabelini/LaneATThttps://github.com/lucastabelini/LaneATT

首先说这个Label,因为input肯定是一张图片,这个毫无疑问,这个Label的构建主要是在LaneDataset中,该类首先构建一个dataset,比如我这里是TuSimple,其数据集的Label是车道线的坐标点,不过是十行(像素)取一个x点的坐标,所以lane就是x点坐标,而h_samples就是y的坐标,主要也就是一个json文件,这部分还好理解
然后这个lane不是直接传进去训练的,会把lane再处理成label,核心是lane_dataset中的transform_annotation函数,其会调用sample_lane来把lane处理成label,
这个label中是不包含y坐标的,只有x坐标,y坐标是通过一个超参数S=72计算出来的,也就是大概整个画面会横切为72份,然后对应的x的坐标,就是label,这一部分也不难理解,
但是会产生一个问题,是不是每条线都有72个x坐标?答案是否定的,因为画面的上方,其实就是驾驶员的远方,是天空,天空这部分画面肯定是没有车道线的,所以也就没有x坐标,

那上面部分缺失,近处部分就是完整的呢?答案也是否定的,因为画面的左侧或右侧,紧邻的还能看见,但左侧车道的左侧车道线,可能就切割了,右侧车道的右侧车道线也一样,所以,y的起点也未必是画面的最下方,那么在label中如何体现车道线是否完整呢?
函数sample_lane中,是把近处的车道线补全了,

extrap = np.polyfit(two_closest_points[:, 1], two_closest_points[:, 0], deg=1)


利用已知坐标点,拟合出了未知坐标点,那这部分坐标点,其实是在画面外,但这部分坐标点也作为了label的一部分进行训练,所以label中x坐标的起点,是画面的最下方,尽管其中包含了超出画面部分的x,然后label中会记录下来有几个点在画面外,以此为开始就是真实的车道线label
 

lanes[lane_idx, 2] = len(xs_outside_image) / self.n_strips

搞懂了label,那就回过头来看model
model就是class LaneATT,backbone是resnet34,然后,forward中,x的shape为[8, 3, 360, 640],当然8是batchsize,后面是图片尺寸,
feature_extractor之后的batch_features的shape是[8, 512, 12, 20],就是压缩了32倍,后面又跟了一个conv,变为了[8, 64, 12, 20],

下面先停一下,看一下anchor,这里当然主要是anchor点,他是依次沿画面左侧,再依次遍历left_angles的角度,所得出的点的坐标,那么,我们可以想象,得出的坐标点,是有可能在画面外的;同样的,也沿画面右侧,遍历right_angles的角度,也得出一堆anchor,再遍历画面底部,遍历bottom_angles的角度,再得出一堆anchor,
这样得出的anchor有一大堆,left_anchors有[432, 77],right_anchors有[432, 77],bottom_anchors有[1920, 77],最后cat一起有,[2784, 77],当然这里面有大量的点是离谱了,比如从左上角向左划一条线,这个就没太大意义,所以这里面会有一个mask, anchors_freq_path就是'data/tusimple_anchors_freq.pt',这个文件是工程中自带的,应该是统计出来的,各个line的有效性的次数,然后用该mask来提取出有效性最高的topk_anchors根线,也就是1000根线,最终self.anchors的尺寸为[1000, 77],
而self.anchors_cut,我没看出来与self.anchors的区别,目前感觉就是切的stride不一样,anchors是切72刀,而 anchors_cut 是切10刀,

下面是计算切片索引,也就是cut_xs,cut_ys,cut_zs,cut_zs就比较简单,就是0-63重复了11编,再重复一千遍,就是64*11*1000个数,cut_ys也比较简单,就是0-10重复64 * 1000 遍,总共也就是 11 * 64 * 1000 个数, cut_xs 是吧 anchors_cut 中的数据 [1000, 11] 重复了64遍

然后回到上面, 用 cut_xs,cut_ys,cut_zs 来采样 [8, 64, 12, 20] 的 feature, 得到 batch_anchor_features 的 shape 为 [8, 1000, 64, 11, 1], 然后进行了一下维度变换,变为了 [8000, 704], 后面经过一个 attention,注意力机制,生成 attention_features,[8, 1000, 704],batch_anchor_features也resize回[8000, 704],cat一下变成[8000, 1408],
把1408送到1408*2的全连接层,进行分类,得到 cls_logits [8000, 2],然后reshape为 [8, 1000, 2]
把1408送到1408*73的全连接层,进行分类,得到 reg [8000, 73],然后reshape为 [8, 1000, 73]

然后构建 reg_proposals,把 self.anchors, cls_logits, reg都合并到一块去,

最后送到nms去,不过这个nms会调用cpp的代码的nms,所以暂未debug,

后面计算损失,中间一大部分应该是匹配正负样本的,看的有点迷糊,总之,最后会匹配到一些正样本和负样本,损失大概分为两部分,一部分是坐标部分,另一部分是二分类部分,坐标部分的损失是l1 loss,就是差值的绝对值,求和,二分类用的是focal_loss

最后,分类损失会乘以一个系数10,和坐标部分的loss相加,得到总的损失,

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值