目标板定位模型

代码地址

前言

在17届省赛结束后,因为担心国赛场地光照影响较大,写了这个目标检测算法。但因为时间以及实力不足,算法仅有了个雏形,没能成功部署,非常遗憾。
今年寒假终于有时间将其完善,也算对自己的锻炼。正好在18届的比赛中有无边框图片,发现该算法在无边框定位上也有较好效果,所以将这个算法开源,希望能对大家有所帮助与启发。
因为能力有限,算法还有许多优化空间。这里仅是抛砖引玉,期待大家的完善。

设计思路

在art上部署目标检测,最需要解决的问题是如何保证art那点可怜的算力能流畅运行目标检测模型。所以我们的重点是如何将模型简化。
本算法借鉴了SSD网络的一些思想,在经典的one-stage目标检测网络架构上进行了修改。
严格意义上来说,本算法不是目标检测网络,其仅完成了目标板定位的功能,并没有对目标板进行分类。也就是说,网络仅对背景与目标板两个类别进行分类。
这样做的原因如下:

  • 模型速度与输入尺寸是相矛盾的。因为art的算力有限,要想保证较高的帧率,除了使用轻量化结构降低权重大小外,还需降低输入尺寸。
  • 输入尺寸与分类正确率是矛盾的。我们训练目标板的分类模型会发现,模型输入尺寸至少要达到(64,64,3)才可以有较好的效果。想要提高精确度,在一定范围内,提高输入尺寸是必要手段之一。
  • 我们进行定位的摄像头一般需要视野较广,放在较高的位置,那么我们目标板在整张图片所占的面积可能只有二十分之一左右(以我们的摄像头高度为例,目标板的大小为32x32个像素,art的QQVGA模式图像大小为160x120)。而我们又希望帧率尽量高,那么分辨率就要进一步降低。那么,在无法保证目标清晰的情况下,分类的效果将会非常差。
  • 定位摄像头与识别摄像头通常是分开的。所以将目标检测网络部署在定位摄像头上,将分类网络部署在识别摄像头上,这样的效果可能会比较好。

所以,我们索性删掉进行分类的部分,专注于进行定位,让其起到与art的find_rect函数相同的作用。

为了使得模型更加轻量化,从以下方面简化网络。
首先给出两个前提:

  • 因为摄像头放得较高,所以可以将其与地面接近平行放置。那么由于目标板的尺寸是统一的,所以无论远近其大小都是一样的(在时间训练中会对数据进行增强,实际上允许一定程度的大小不一致)。
  • 目标与目标之间保持一定距离,不会出现目标重叠的情况。(这点可以从逐飞上位机生成的地图得以保证)

我们可以根据以上前提,对经典的目标检测网络作出如下改变:

  • 因为不需要进行分类任务,大幅减少backbone的深度。
  • 因为尺寸统一,我们就不需要多个预测特征层来适应不同大小的目标,仅需要一个就可以。
  • 因为目标板的外接矩形都是正方形,且尺寸基本一样,我们可以舍弃不同尺寸的锚框,用4x3个先验格子进行代替。每个格子负责预测该区域内的目标。
  • 目标检测一般预测(x,y,w,h)四个参数,因为尺寸基本一样我们不预测w和h,仅预测x和y。用一个经验参数r来确定目标外接矩形的边长(r由目标板在摄像头中倾斜45度的外接矩形边长确定)。

通过以上简化,我们的网络在量化后仅有38KB。经过朋友测试,在art连接电脑的情况下可以达到24帧,可以满足定位的需求。

模型结构

backbone

  • 输入需要满足的要求:
    r 3 = 2 n \frac{r}{3}=2^n 3r=2n
    w 4 = 2 n \frac{w}{4}=2^n 4w=2n
    这样的设置是因为art的图像比例为4:3,然后一般进行下采样时是按步长为2进行。所以说可供选择的尺寸仅有(96,128),(48,64),更大或更小可能会出现模型运行速度较慢或精度较低等问题。
  • 考虑到兼容性问题,backbone暂时的保守使用mobilenent v2的bottleneck结构。有关bottleneck的介绍详见我的另一篇文章。你也可以尝试一些比较新的tricks,这样可能会更快。后续我也可能会参考yolo系列做一些优化。

预测特征层

预测特征层只有一个:4x3
在4x3的先验格子中,不会出现两个目标的中心落在一个格子的情况
正样本:4x3格子中有目标的格子
负样本:4x3格子中无目标的格子

分类头和回归头结构

  • 分类头:因为只有目标和背景两类,使用sigmoid激活所以分类头的输出为 (batch size,3,4,1)。
  • 回归头:因为只预测 c x , c y c_x,c_y cx,cy两个值,所以回归头输出为 (batch size,3,4,2)。

目标编码与解码

目标编码

d x = c x − x 0 w d_x = \frac{c_x-x_0}{w} dx=wcxx0
d y = c y − y 0 h d_y = \frac{c_y-y_0}{h} dy=hcyy0
d x , d y 为目标中心相对于先验格子中心偏移量的归一化值。 c x , c y 为目标的中心坐标。 d_x,d_y为目标中心相对于先验格子中心偏移量的归一化值。c_x,c_y为目标的中心坐标。 dx,dy为目标中心相对于先验格子中心偏移量的归一化值。cx,cy为目标的中心坐标。
x 0 , y 0 为先验格子的中心坐标。 w , h 为先验格子的宽和高。 x_0,y_0为先验格子的中心坐标。w,h为先验格子的宽和高。 x0,y0为先验格子的中心坐标。wh为先验格子的宽和高。

编码后的label长度为36,其中前24项为12个先验格子中的回归坐标偏移量,剩下的12项为12个格子中是否有目标的置信度。

目标与先验格子的匹配策略

相邻的两个格子中心的距离为32,一个格子的大小为40。也就是说,相邻两个格子会有相交的区域。
对于目标与先验格子的匹配,遵循以下两条原则:

  • 第一原则:目标中心与某个格子中心距离小于16,那么这个格子与目标匹配。
  • 第二原则:若格子尚未被匹配,则选取处于格子范围内且离格子中心最近的目标进行匹配。

第一原则保证了每个目标都能与先验格子进行匹配,第二原则增加了正样本数,且避免了边界效应。
注意:上述所有具体数值可以根据模型输入大小已经模型结构等因素进行调整,比如输入为(48,64,3)的模型只要将上述的参数全部除以2就行。

解码与后处理

解码就是对模型输出做编码的逆运算,这样会得出一个坐标序列。然后对坐标做非极大值抑制。

损失函数

将总体的目标损失函数定义为 定位损失(loc)和置信度损失(conf)的加权和:
L ( x , c , l , g ) = 1 N ( L c o n f ( x , c ) + α L l o c ( x , l , g ) ) \begin{equation} L(x,c,l,g) = \frac{1}{N}(L_{conf}(x,c)+\alpha L_{loc} (x,l,g)) \end{equation} L(x,c,l,g)=N1(Lconf(x,c)+αLloc(x,l,g))
其中 N 为真实值中有目标的格子数,如果 N = 0 ,则将损失设为 0 ; 其中N为真实值中有目标的格子数,如果N=0,则将损失设为0; 其中N为真实值中有目标的格子数,如果N=0,则将损失设为0
而 α 参数用于调整置信度损失和定位损失之间的比例,默认 α = 1 。 而 α 参数用于调整置信度损失和定位损失之间的比例,默认 α=1。 α参数用于调整置信度损失和定位损失之间的比例,默认α=1

置信度损失

因为为sigmoid激活后的二分类任务,使用交叉熵损失函数
L c o n f ( x , c ) = − ∑ (   y l o g ( c i ^ ) + ( 1 − y ) l o g ( c i ^ )   ) \begin{equation} % L_{conf}(x,c) = -\sum_{i \in Pos}^N log(\hat{c}_{i}) - \sum_{i \in Neg}^M log(\hat{c}_{i}) L_{conf}(x,c) = -\sum (\ ylog(\hat{c_i}) +(1-y)log(\hat{c_i}) \ ) \end{equation} Lconf(x,c)=( ylog(ci^)+(1y)log(ci^) )
c i ^ = S i g m o i d ( c i ) \hat{c_i} = Sigmoid(c_i) ci^=Sigmoid(ci)

y = { 1 , 0 } , 当标签上有目标时为 1 ,无目标时为零。其实就是 B i n a r y   C r o s s e n t r o p y 损失。 y=\left\{1,0\right\},当标签上有目标时为1,无目标时为零。其实就是Binary \ Crossentropy 损失。 y={10},当标签上有目标时为1,无目标时为零。其实就是Binary Crossentropy损失。

位置损失

当且仅当预测与真实图片在某个格子内有目标时才进行计算(回归结果不在格子内也算,这就体现出Smooth L1 的价值了)。
偏差为与格子中心进行归一化后的偏差(除以格子的边长)。
使用Smooth L1 loss
生成的标签为目标中心相对于格子中心的偏差。
L l o c ( x , l , g ) = ∑ i ∈ P o s N ∑ m ∈ { c x , c y } x i s m o o t h L 1 ( l i m − g ^ i m ) \begin{equation} L_{loc}(x,l,g) = \sum_{i \in Pos }^N \sum_{m \in \left\{c_x,c_y\right\}} x_i smooth_{L1}(l_i^{m}- \hat{g}_i^{m}) \end{equation} Lloc(x,l,g)=iPosNm{cx,cy}xismoothL1(limg^im)
其中 l 为预测值的回归偏移量归一化值, g ^ 为真实值的回归偏移量归一化值。 其中l为预测值的回归偏移量归一化值,\hat{g}为真实值的回归偏移量归一化值。 其中l为预测值的回归偏移量归一化值,g^为真实值的回归偏移量归一化值。
x i = { 1 , 0 } ,当且仅当标签与预测都有目标时为 1 。 x_i=\left\{1,0\right\},当且仅当标签与预测都有目标时为1。 xi={10},当且仅当标签与预测都有目标时为1

正负样本比例

ssd中利用Hard negative mining方法得到1:3的正负样本比例。这里为了方便,直接利用数据生成器生产1:3正负样本比例的数据集,暂时不在损失函数部分实现Hard negative mining。

部署

模型的部署不需要标签文件,但需要后处理函数。后处理包括解码以及非极大值抑制。因为现在手上没有art,所以这里暂时不提供脚本。可以参考utils.target_utils下的target_decoder类进行改写。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐