【深度学习】目标检测之YOLOv2算法&6D姿态估计之YOLO-6D算法

深度解析YOLOv2算法原理

网络结构

YOLOv2的网络backbone是Darknet-19(19个卷积层的全卷积网络),Darknet-19网络结构如下(input image size 224 * 224),进行了32倍下采样
在这里插入图片描述YOLOv2在Darknet-19的基础上,做了如下改动:

  1. YOLOv2的网络结构
    在这里插入图片描述上图中有一处错误:
    用于网络结构输出的最后一个卷积层的kernel size不是图中所示的 3 ∗ 3 3 * 3 33,而是 1 ∗ 1 1 * 1 11
    YOLOv2选择416 * 416作为网络的输入size,这样经过32倍下采样后,输出的featuer map的size是13 * 13,是奇数,这是因为考虑到图片一般待检测目标会居中

  2. reorg层的操作
    在这里插入图片描述引入reorg层就是为了将靠前的feature map的信息和靠后的feature map结合起来

  3. 两条branch的结合方法
    将两个width和height相同的tensor,按channel方向拼接在一起

  4. 最后一个卷积层输出channel的含义
    每个cell生成五个anchor,每个anchor对应自己的输出:4(center_x, center_y, width, height) + 1(置信度) + num_classes(和SSD不同,这个num_classes不包括background,SSD就是通过增加一个background起到YOLO中置信度的作用)

anchor的编解码

首先,YOLOv2给出的anchor的width和height的值,是在最后一个13 * 13的feature map上的值。这和SSD中anchor的width和height是不一样的,SSD的anchor的witdh和height都在(0, 1)之间,而YOLOv2的anchor的width和heigth都在(0, 13)之间

在这里插入图片描述

如上图,最后一个13 * 13的feature map,width-height平面上每一个点对应的,5(anchor数量) * [4(center_x, center_y, width, height) + 1(置信度) + num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)],个输出值,以一个位置的一个anchor为例:
先验:

  • 这个anchor的width和height分别是 p w p_w pw p h p_h ph,这是先验
  • 这个位置的坐标(cell的左上点坐标)是 c x c_x cx c y c_y cy,这是先验

输出:

  • 网络的输出4(center_x, center_y, width, height)部分: t x t_x tx t y t_y ty t w t_w tw t y t_y ty
  • 网络的输出 1(置信度)部分: t o t_o to
  • 网络的输出num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)部分:分类结果,num_classes个值

label:

  • 网络的输出4(center_x, center_y, width, height)部分:归一化后的ground truth box中心点坐标 g x g_x gx g y g_y gy和边长 g w g_w gw g h g_h gh
  • 网络的输出 1(置信度)部分: P r ( o b j e c t ) ∗ I O U ( b , o b j e c t ) Pr(object) * IOU(b, object) Pr(object)IOU(b,object)如果这个cell中落入了某一个object,则 P r ( o b j e c t ) = 1 Pr(object)=1 Pr(object)=1,否则 P r ( o b j e c t ) = 0 Pr(object)=0 Pr(object)=0 I O U ( b , o b j e c t ) IOU(b, object) IOU(b,object)是这个cell的这个anchor的 t x t_x tx t y t_y ty t w t_w tw t y t_y ty输出部分编码后所表示的框,和这个object的ground truth box的IOU。如果一个cell落入多个object,那么这个cell的每一个anchor的置信度label取值最大的那么如何判断一个目标落在哪个cell中呢?看 ( i n t ( g x ∗ 13 ) , i n t ( g y ) ∗ 13 ) (int(g_x * 13), int(g_y) * 13) (int(gx13),int(gy)13)等于上图中的哪个坐标,就落入哪个cell。( i n t int int这里表示向下取整)
  • 网络的输出num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)部分:类别 ( 0 , n u m _ c l a s s e s − 1 ) (0, num\_classes-1) (0,num_classes1)经过one-hot

box的编解码方式:

  • b x = S i g m o i d ( t x ) + c x b_x =Sigmoid(t_x) + c_x bx=Sigmoid(tx)+cx
  • b y = S i g m o i d ( t y ) + c y b_y = Sigmoid(t_y) + c_y by=Sigmoid(ty)+cy
  • b w = p w e t w b_w=p_we^{t_w} bw=pwetw
  • b h = p h e t h b_h =p_he^{t_h} bh=pheth
  • b o = S i g m o i d ( t o ) b_o=Sigmoid(t_o) bo=Sigmoid(to)

b x 、 b y 、 b w 、 b h 、 b o b_x、b_y、b_w、b_h、b_o bxbybwbhbo分别是 t x 、 t y 、 t w 、 t h 、 t o t_x、t_y 、t_w、t_h、t_o txtytwthto编码后的结果。为什么使用 S i g m o i d Sigmoid Sigmoid函数,是因为 S i g m o i d Sigmoid Sigmoid函数的输出值范围是 ( 0 , 1 ) (0, 1) (0,1),这样 b x 、 b y b_x、b_y bxby就保持在cell中

损失函数

当一个object落入某个cell后,要选择哪个anchor负责这个object,选择方法如下:
将anchor的中心和ground truth box(width * 13、height * 13)的中心重合,计算两者的IOU,IOU最大的那个anchor负责这个cell对这个object的预测

在这里插入图片描述YOLOv2的loss计算公式如上:

在训练过程中,计算loss之前,先选定每一个object用哪个cell的哪个anchor负责

每一个cell的不负责的anchor,计算 P r ( o b j e c t ) ∗ I O U ( b , o b j e c t ) Pr(object) * IOU(b, object) Pr(object)IOU(b,object)如果计算结果大于0.6,则这个不负责预测的anchor不计入置信度损失的计算。因为如果这类anchor负责,结果也准确,但是没有用它,因此这部分并不是重点需要优化的对象

  • 第一项:所有负责预测目标的anchor的坐标损失( b x 、 b y 、 b w 、 b h b_x、b_y、b_w、b_h bxbybwbh)。label是 g x g_x gx g y g_y gy g w g_w gw g h g_h gh(注意计算loss之前要乘13)衡量目标定位准确度前面的系数设置为1
  • 第二项:不负责预测目标的anchor的坐标损失( b x 、 b y 、 b w 、 b h b_x、b_y、b_w、b_h bxbybwbh)。label是 c e l l 的 左 上 点 x 、 c e l l 的 左 上 点 y cell的左上点x、cell的左上点y cellxcelly a n c h o r 的 w i d t h 、 a n c h o r 的 h e i g t h anchor的width、anchor的heigth anchorwidthanchorheigth因为这样的label对应的实际输出是零前面的系数设置为1
  • 第三项:负责预测目标的anchor的confidence损失 b o b_o bolabel是 P r ( o b j e c t ) ∗ I O U ( b , o b j e c t ) Pr(object) * IOU(b, object) Pr(object)IOU(b,object)衡量可能有目标的准确度前面的系数设置为5
  • 第四项:不负责预测目标的anchor的confidece损失 b o b_o bo。计算 P r ( o b j e c t ) ∗ I O U ( b , o b j e c t ) Pr(object) * IOU(b, object) Pr(object)IOU(b,object)如果计算结果小于0.6label是零前面的系数设置为1
  • 第五项:负责预测目标的anchor的类别损失。输出经过softmax后,分类label经过one-hot编码处理,计算的是L2损失

注意前几个epoch不计算置信度损失

Darknet 框架实现的YOLOv2

https://pjreddie.com/darknet/yolov2/

深度解析YOLO-6D算法原理

什么是6D姿态估计

在这里插入图片描述像素坐标系下的点,经过内参矩阵转换到相机坐标系相机坐标系下的点,经过外参矩阵转换到世界坐标系

YOLO-6D输出目标在像素坐标系下的9个key points,结合这9个key points在世界坐标系下的坐标,以及已知的相机内参矩阵,通过PnP算法,得到外参矩阵。为了方便得到key points在世界坐标系下的坐标,这9个key points选定为目标质心点和3Dbounding box的八个角点在二维图像上的投影。

网络结构

将YOLOv2的最后一个卷积层的输出channel数由,5(anchor数量) * [4(center_x, center_y, width, height) + 1(置信度) + num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)],改为:5(anchor数量) * [18(9个key points在像素坐标系下的坐标) + 1(置信度) + num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)],其余和YOLOv2的结构相同。

key point的编解码

和YOLOv2相同,以一个位置的一个anchor为例:
先验:

  • 这个anchor的width和height分别是 p w p_w pw p h p_h ph,这是先验
  • 这个位置的坐标(cell的左上点坐标)是 c x c_x cx c y c_y cy,这是先验

输出:

  • 网络的输出18(9个key points在像素坐标系下的坐标)部分: t x c e n t e r t^{center}_x txcenter t y c e n t e r t^{center}_y tycenter t x 1 t^1_x tx1 t y 1 t^1_y ty1、…、 t x 8 t^8_x tx8 t y 8 t^8_y ty8
  • 网络的输出 1(置信度)部分: t o t_o to
  • 网络的输出num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)部分:分类结果,num_classes个值

label:

  • 网络的输出18(9个key points在像素坐标系下的坐标)部分:归一化后的key points坐标 g x c e n t e r g^{center}_x gxcenter g y c e n t e r g^{center}_y gycenter g x 1 g^1_x gx1 g y 1 g^1_y gy1、… g x 8 g^8_x gx8 g y 8 g^8_y gy8
  • 网络的输出 1(置信度)部分:置信度label的计算方式是YOLO-6D相比YOLOv2改动的很重要的部分。YOLO-6D的置信度计算函数图像如下:
    对于九个key points中的一个 d t h d_{th} dth是设置的像素坐标的欧式距离阈值,默认为80。当这个key points的输出 t x t_x tx t y t_y ty经过编码后所表示的点的绝对坐标值(乘图像的width或heigth后)和 g x g_x gx g y g_y gy的绝对坐标值(乘图像的width或heigth后)的欧式距离 D T ( x ) D_{T(x)} DT(x),大于 d t h d_{th} dth,则置信度的label设置为0。如果 D T ( x ) D_{T(x)} DT(x)小于 d t h d_{th} dth,则置信度的label按如下公式计算求得:
    e α ( 1 − D T ( x ) d t h ) − 1 e α − 1 \dfrac{e^{\alpha(1-\dfrac{D_{T(x)}}{d{th}})}-1}{e^\alpha - 1} eα1eα(1dthDT(x))1 α \alpha α默认设置为 2 2 2
    最后这个cell的这个anchor的置信度label是9个key points的置信度label的平均值。
    在这里插入图片描述
  • 网络的输出num_classes(和SSD不同,这个num_classes不包括backgrund,SSD就是通过增加一个background起到YOLO中置信度的作用)部分:类别 ( 0 , n u m _ c l a s s e s − 1 ) (0, num\_classes-1) (0,num_classes1)经过one-hot

box的编解码方式:

  • b x c e n t e r = ( S i g m o i d ( t x c e n t e r ) + c x ) / 13 b^{center}_x = (Sigmoid(t^{center}_x) + c_x)/13 bxcenter=(Sigmoid(txcenter)+cx)/1313是最后一个feature map的size
  • b y c e n t e r = ( S i g m o i d ( t y c e n t e r ) + c y ) / 13 b^{center}_y = (Sigmoid(t^{center}_y) + c_y)/13 bycenter=(Sigmoid(tycenter)+cy)/13center的点经过sigmoid,是为了将中心点控制在cell中
  • b x 1 = ( t x 1 + c x ) / 13 b^1_x = (t^1_x + c_x)/13 bx1=(tx1+cx)/13
  • b y 1 = ( t y 1 + c y ) / 13 b^1_y=(t^1_y+c_y)/13 by1=(ty1+cy)/13
  • b x 8 = ( t x 8 + c x ) / 13 b^8_x=(t^8_x + c_x)/13 bx8=(tx8+cx)/13
  • b y 8 = ( t y 8 + c y ) / 13 b^8_y=(t^8_y+c_y)/13 by8=(ty8+cy)/13
  • b o = S i g m o i d ( t o ) b_o=Sigmoid(t_o) bo=Sigmoid(to)

损失函数

和YOLOv2的loss相同,在训练过程中,计算loss之前,先选定每一个object用哪个cell的哪个anchor负责
选择方法和YOLOv2相同,这也是为什么YOLO-6D也需要二维ground truth box的label信息

每一个cell的不负责的anchor,计算置信度label,如果计算结果大于0.6,则这个不负责预测的anchor不计入置信度损失的计算。因为如果这类anchor负责,结果也准确,但是没有用它,因此这部分并不是重点需要优化的对象

不同的是,YOLO-6D的loss只有四项:

  • 第一项:所有负责预测目标的anchor的key points损失( b x c e n t e r b^{center}_x bxcenter b y c e n t e r b^{center}_y bycenter b x 1 b^1_x bx1 b y 1 b^1_y by1、…、 b x 8 b^8_x bx8 b y 8 b^8_y by8)。label是 g x c e n t e r g^{center}_x gxcenter g y c e n t e r g^{center}_y gycenter g x 1 g^1_x gx1 g y 1 g^1_y gy1、…、 g x 8 g^8_x gx8 g y 8 g^8_y gy8衡量目标定位准确度前面的系数设置为1。仍然是L2损失。
torch.nn.MSELoss(size_average=False)

不负责预测目标的anchor不计入key points损失的计算

  • 第二项:负责预测目标的anchor的confidence损失 b o b_o bolabel是计算的置信度label衡量可能有目标的准确度前面的系数设置为5。仍然是L2损失。
torch.nn.MSELoss(size_average=False)
  • 第三项:不负责预测目标的anchor的confidece损失 b o b_o bo。计算置信度label,如果计算结果小于0.6label是零前面的系数设置为1。仍然是L2损失。
torch.nn.MSELoss(size_average=False)
  • 第四项:负责预测目标的anchor的类别损失。前面的系数设置为2输出经过softmax后,分类label经过one-hot编码处理,计算的是交叉熵损失
torch.nn.CrossEntropyLoss(size_average=False)

注意前几个epoch不计算置信度损失

单目标6D姿态估计精度统计指标

所谓单目标,是指分类label只有一类,且图像中只有一个目标的情况(注意这种情况不计算分类loss)

Mean Corner Error

测试集中的每一个样本,其9个key points的网络输出值和ground truth的像素级欧式距离求平均值。然后再将测试集所有样本求平均。

2D Projection

默认像素阈值:px_threshold=5

  1. 使用像素坐标系下9个key points的坐标(ground truth),相机内参,以及世界坐标系下9个key points的坐标,通过PnP算法,计算得到相机外参矩阵Rt_gt
  2. 使用像素坐标系下9个key points的坐标(网络输出),相机内参,以及世界坐标系下9个key points的坐标,通过PnP算法,计算得到相机外参矩阵Rt_pr
  3. 通过相机内参和Rt_gt计算所有世界坐标系中的点云点,在像素坐标系下的坐标proj_2d_gt
  4. 通过相机内参和Rt_pr计算所有世界坐标系中的点云点,在像素坐标系下的坐标proj_2d_pred
  5. 计算每一对转换过来的像素坐标系下的点的欧式距离,其均值小于px_threshold,则算估计正确
  6. 所有估计正确的数量 / 总数量

3D Transformation

默认体素阈值:vx_threshold=0.1 * 目标直径(米)

  1. 使用像素坐标系下9个key points的坐标(ground truth),相机内参,以及世界坐标系下9个key points的坐标,通过PnP算法,计算得到相机外参矩阵Rt_gt
  2. 使用像素坐标系下9个key points的坐标(网络输出),相机内参,以及世界坐标系下9个key points的坐标,通过PnP算法,计算得到相机外参矩阵Rt_pr
  3. 通过Rt_gt计算所有世界坐标系中的点云点,在相机坐标系下的坐标transform_3d_gt
  4. 通过Rt_pr计算所有世界坐标系中的点云点,在相机坐标系下的坐标transform_3d_pred
  5. 计算每一对转换过来的相机坐标系下的点的欧式距离,其均值小于vx_threshold,则算估计正确
  6. 所有估计正确的数量 / 总数量

Pytorch实现的YOLO-6D

https://github.com/Microsoft/singleshotpose/

结语

如果您有修改意见或问题,欢迎留言或者通过邮箱和我联系。
手打很辛苦,如果我的文章对您有帮助,转载请注明出处。

  • 8
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值