看完Cornernet之后,不得不说这篇文章很复杂,可以扣的细节很多,而我自己也是反反复复读了好几遍才理清作者的思路,特此记录下来,以供之后回读。

Cornernet作为one-stage目标检测器,它的的出发点有两个:(1)传统的基于Anchor的目标检测算法需要生成大量的Anchor,但是真正能与Ground-truth有重叠的Anchor却很少,这就造成了正负样本不平衡的问题。(2)基于Anchor的检测算法需要人工设置很多超参数,比如Anchor的长宽比、尺寸大小等,过多的超参数使得调参的过程更加复杂。而Cornernet为了改进这两个方面,提出了目标检测算法的新思路:基于关键点的目标检测。

Cornernet检测的关键点是目标的左上角和右下角的顶点,基于这两个关键点,就可以将一个目标框出来:

那么如何检测到这两个关键点呢?看一下 Cornernet的网络结构:

如图,首先将输入图像经过7*7的卷积和一个步长为2的残差块,得到1/4原图大小的特征图,然后将特征图送入Cornernet的基础网络:沙漏网络(Hourglass Network),这是一个编码解码的网络结构,其输入和输出都是同样尺寸大小的特征图,这样沙漏网络的输出就是1/4原图大小的特征图。

然后,沙漏网络的输出分成了两个之路,这两个之路分别去预测目标的左上角关键点(Top-left Corners)和右下角关键点(Bottom-right Corners),这两个之路在构造上是完全相同的,因此以左上角关键点的支路为例来介绍:

此支路即为网络的预测模块,主要由四个部分构成:Corner Pooling、Heatmap、Embeddings、Offset。下面将会一一介绍这四个部分:

首先是Corner Pooling:

如上图,我们想要检测的关键点是在目标外部的,也就是在背景上的,这样的关键点是不包含目标位置的信息的,而进行Corner Pooling的目的就是希望这两个点可以有目标位置处的信息。通过观察,我们发现左上角的关键点与两条边界线有关,分别是框的上边界和左边界的两条线,右下角的关键点与框的下边界和右边界的两条线有关。如果左上角关键点的位置准确,那这个点向右看去应该是与人的头顶相切,向下看去应该是与人的右手相切。而Corner Pooling就将目标的边缘信息赋给了关键点。

那它具体是怎么做的呢?

如上面这幅图,首先将Corner Pooling的输入分成两个支路,两个之路分别执行“向右看”和“向下看”的操作。第一个支路(向下看):假如左上角关键点的位置是图中的红色点,那么我就将与这个点同一列但是在这个点下面所有点的最大值赋给这个点;第二个支路(向右看):假如左上角关键点的位置是图中的红色点,那么我就将与这个点同一行但是在这个点右面所有点的最大值赋给这个点。最后将这两个支路的值相加,得到Corner Pooling的输出:蓝色点。

再从数字上去理解:

为了方便Corner Pooling的实现,在实际操作时,从整个特征图的最右边一列开始,与左边的一列进行比较,并将两列相邻元素的最大的值赋给左边列的相应位置的元素,一直比较到特征图的最左边一列(向右看);(向下看同理),最后将两部分逐元素相加得到Corner Pooling的输出。这样我们就认为关键点已经包含了目标的边缘信息了。

当然Corner Pooling部分还是有很多争议的,比如如果图像上不只有一个目标,我在做Corner Pooling的时候很可能将其他目标处的像素点的值赋给了关键点。这对于小目标来说尤其明显,后面作者也做了关于Corner Pooling的实验,引入Corner Pooling对于小目标关键点的检测提升确实不明显。(Corner Pooling算是文章最具有创新点的地方了,但是争议也是最大的。)

然后是Heatmap:

Heatmap为关键点热图,Heatmap层的通道数为C,C为目标的类别数目,数据集中的每一个类别都对应一个关键点热图,对应到Heatmap中就是其中的一个通道。Heatmap的大小为H*W,代表了关键点可能存在的H*W个位置,Heatmap中的元素值大小为0-1,代表了关键点可能属于这一类(与通道有关)并且在这个位置(与该通道的h和w有关)的置信度。

Heatmap层所对应的损失函数:

N为目标的总数,为关键点热图每个位置的预测值,为每个位置所对应的真实值。是人工设置的超参数,之后会详细说明。

这其实就是一个改进版的focal loss,其目的是改进难样本和易样本不平衡的问题。比如当很接近于0或者很接近于1时,这就是很容易分的样本,而当在0.5左右,这就是很难分的样本,focal loss就是想将易样本的loss比重缩小,从而更关注难样本的训练。

而此处loss的改进之处就在与,他就是为每一个负样本的损失添加了一个权重,如下图,红色框的两个关键点为目标的Ground-truth,绿色虚线框的两个关键点为预测点。我们现在认为如果预测点在真实点附近的话也是可以接受的,我们就将这个预测点处的损失比重降低,而距离真实点更远处的点的损失应该相对来说更大。真实点的附近是根据以真实点为中心,人工设置的半径得到的,文中半径是根据预测框与真实框的IOU为0.3得到的。具体实现的方式就是通过对ground-truth做一个类似于高斯滤波的方式,使得heatmap每一个位置的不再只是0或1。而具体的值通过高斯公式得到:,其中(x,y)表示以关键点为坐标原点,其他位置的相对坐标。取值为1/3的半径。举例:当预测点距离真实点很近时,则很接近1,那么就是很小的值,也就是说它的loss就降低了;而当预测点距离真实点很远时,则很接近0,那么就是很大的值,那么它的loss就相对来说更大一些。

heatmap的loss用到了两个技巧,一个是focal loss,一个是类似于标签高斯平滑的处理,细节满满啊!

接着就是Offset:

Cornernet所预测关键点的Heatmap是1/4原图的大小,那么在将关键点映射回原图的时候就会造成精度损失的问题,如下图:

因为原图中的关键带你在缩小的时候是向下取整,所以Heatmap关键点映射回去的时候就不知道是原图的16个位置的哪一个位置,所以需要加入Offset来对关键点进行微调。Offset的Ground-truth是:

Offset的损失函数为SmoothL1损失:

其中,N为原图中目标的数量,为Offset的预测值。

注意!:在预测Offset的时候,只使用到了N个Ground-truth,另外,Offset那一层的特征图的大小为H*W*2,2代表了Offset有x和y两个方向的大小,Offset对于目标的C个类是共享的。

最后是Embedding:

Embedding的目的是将同一个目标的两个关键点匹配到一起,文章在这里用到了embedding vector,embedding vector的详细内容可以参考这篇论文《Associative Embedding: End-to-End Learning for Joint Detection and Grouping》。具体的做法就是Heatmap的每一个关键点位置都对应着一个embedding vector,同一个目标的两个关键点的embedding vector的距离应该接近,不同目标点的embedding vector应该距离很远,可以用“pull”和“push”两个loss函数来进行约束:

其中,分别是左上角的关键点和右下角的关键点所对应的embedding vector,是这两个embedding vector的均值。“pull”loss可以拉近同目标的embedding vector的距离。“push”loss可以拉远不同目标的embedding vector。

注意!:对于这两个loss来说,它们的Ground-truth就是知道哪两个关键点是匹配的;对于embedding vector来说,值的大小无所谓,重要的是相同目标的emvedding vector的距离接近;文中使用的embedding vector是一维嵌入,也就是说embedding vector是一个标量,因此Embedding这一层的大小为H*W*1。

看一下Cornernet预测模块的详细结构:

首先Backbone的输出分成了三个分支,前两个分支执行Corner Pooling操作(两个方向上),然后第三个分支与前两个分支做一个融合,接着通过Relu-Conv-BN-Relu层,分成三个之路,分别是网络的Heatmap、Offset、Embedding三个部分。

网络的主体结构就介绍完了,除此之外,还有一些网络训练和测试的细节:

Intermediate supervision:

如上图,网络在连接两个沙漏模块时,将第一个沙漏模块的输出经过卷积与它的经过卷积的输入逐元素相加,然后经过卷积后作为第二个沙漏模块的输入,两个沙漏模块都能得到输出,在进行Backward时,将两个输出的loss相加一起回传损失,但是测试的时候只是用最后一个输出。

使用中继监督的好处是网络可以更好地更新浅层的网络参数,因为对于深层网络来说,最后的输出的loss经过反向传播之后,对应到网络浅层的梯度可能就很小了,这是深度网络训练的一个技巧吧。

还有就是测试和解码的过程:

网络测试得到的Heatmap先于Offset相加,然后人工设置一个Embedding的阈值,一般是一范数约束,当两个关键点的embedding vector的距离小于这个阈值的时候就认为这两个点对应的是同一个目标,除此之外还有一些判决条件:比如两个关键点必须对应同一类目标(在相同序列的通道中),右下角的点必须要在左上角点的位置的右下方。之后再经过nms处理就可以得到网络的预测框了。

论文的实验部分:

首先是比较Corner Pooling的影响:

先说一下COCO数据集的一些评判标准:AP:在测试时,IOU设置从0.5到0.9,步长为0.05,最后取平均的结果;AP50:IOU设置为0.5的结果;AP75:IOU设置为0.75的结果;APs:小目标的AP;APm:中目标的AP;APl:大目标的AP。具体的大小是有一个范围,这个可以去查看COCO数据集的详细的判决标准。

可以看到corner pooling对于小目标来说提升并不是很明显,但是对于大目标来说,提升还是很大的。

然后是对于Heatmap做高斯平滑处理时的半径的取值:

表格第一行是不采用高斯平滑,第二行是对所有的目标都去相同的固定的半径值,第三行是半径根据目标的大小来决定的。

表格3是使用Ground-truth代替预测值来做了进一步的探讨:

第一行是不使用Ground-truth,第二行是Heatmap用Ground-truth来代替,可以看到提升是非常巨大的,第三行是进一步将Offset也用Ground-truth来代替,也是有提升的,但是没有Heatmap的提升明显。

然后就是将Cornernet与目前的目标检测算法做一个比较:

可以看到Cornernet已经达到了one-stage检测器最好的结果,与two-stage检测器也有一战之力!

总结:

Cornernet借鉴了姿态估计的关键点检测的思想,并且成功迁移到物体检测的做法上来,这是一种思路上的创新,给了我们很大的启发,我们是不是也可以考虑借鉴其他任务的思想来做目标检测呢?从做法上来说,Cornernet最具有创新点的地方就是Corner Pooling,而其他的细节都是它所用到的技巧,因此从原理上分析关键点检测比SSD、YOLO这些传统的检测算法好的本质在哪里很模糊,另外Cornernet使用的基础网络是Hourglass,基础网络所带来的性能的提升有多大的影响文章也没有做实验。但是总的来说,思路上给人眼前一亮的感觉,希望这条路能出现更多优秀的算法,让目标检测的做法更丰富!

CornerNet: Detecting Objects as Paired Keypoints论文笔记(详细)相关推荐

  1. CornerNet: Detecting Objects as Paired Keypoints 论文笔记

    CornerNet: Detecting Objects as Paired Keypoints 论文链接: https://arxiv.org/abs/1808.01244 一. Problem S ...

  2. 【目标检测】CornerNet: Detecting Objects as Paired Keypoints论文理解

    文章目录 摘要 1 引言 2 相关工作 2.1 两阶段检测器 2.2 单阶段检测器 2.3 anchor free的检测器 3 CornerNet 3.1 概述 3.2 检测角点 3.3 分组角点 3 ...

  3. 【论文笔记】:CornerNet: Detecting Objects as Paired Keypoints

    &Title: CornerNet: Detecting Objects as Paired Keypoints CornerNet: Detecting Objects as Paired ...

  4. 论文笔记:CornerNet—Detecting Objects as Paired Keypoints

    CornerNet: Detecting Objects as Paired Keypoints 1.摘要 2.细节 2.1.概览 2.2.检测角点 2.3.角点分组 2.4.角点池化 2.5.Hou ...

  5. CornerNet论文详解CornerNet: Detecting Objects as Paired Keypoints

    一.论文相关信息 ​ 1.论文题目:CornerNet: Detecting Objects as Paired Keypoints ​ 2.发表时间:2018 ​ 3.文献地址:https://op ...

  6. ECCV2018 | 论文阅读CornerNet: Detecting Objects as Paired Keypoints

    CornerNet论文阅读--CornerNet: Detecting Objects as Paired Keypoints 文章目录 CornerNet论文阅读--CornerNet: Detec ...

  7. 论文阅读笔记五十:CornerNet: Detecting Objects as Paired Keypoints(ECCV2018)

    论文原址:https://arxiv.org/pdf/1808.01244.pdf github:https://github.com/princeton-vl/CornerNet 摘要 本文提出了目 ...

  8. 论文解读 | CornerNet: Detecting Objects as Paired Keypoints

    https://blog.csdn.net/weixin_40414267/article/details/82379793 论文链接:https://arxiv.org/abs/1808.01244 ...

  9. CornerNet:Detecting Objects as Paired Keypoints

    论文思想 将检测问题建模成关键点检测问题,通过检测左上.右下两个关键点来回归出检测框,是一种anchor free 的目标检测算法.主要解决了anchor based方法的两大问题: anchor b ...

最新文章

  1. 2542513 - AS Java fails to start - Initialization of destination UMEBackendConnection failed
  2. 麦肯锡报告摘译:未来成功城市的14个特征
  3. Android 保存图片到系统及相关问题的解决方案
  4. Javascript基础与面向对象基础~第六讲 Javascript中的事件机制
  5. javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/
  6. SpringBatch 配置并行启动Job详解 (八)
  7. 如何隐藏地址栏中的真实地址_Firefox推出Private Relay插件:可隐藏真实邮箱地址...
  8. 【带着canvas去流浪(5)】绘制K线图
  9. python接口自动化(十七)--Json 数据处理---一次爬坑记(详解)
  10. 如何将Oracle中同一列的多行记录拼接成一个字符串 十一__262 | 浏览 8183 次 推荐于2016-01-25 17:34:18 最佳答案 需要用wm_concat函数来实现。
  11. 2017年3月21日
  12. Kotlin 或将取代 Java —— 《Java 编程思想》作者 Bruce Eckel
  13. RuntimeError: context has already been set(multiprocessing)
  14. vue的nxut框架生命周期触发两遍的问题
  15. sublime text3 boxy主题 (本地 压缩包 安装)
  16. 解决Android studio 导入工程慢的方法
  17. 支付接口的API什么?SDK是什么?
  18. Android Studio 之 Live Templates 高效利用
  19. Array与ArrayList有什么区别
  20. 数据结构——通俗讲解关于任一二叉树n0=n2+1的证明

热门文章

  1. 超文本标记语言(英语:HyperText Markup Language,简称:HTML)
  2. 小学二年级计算机课游戏,小学二年级适合玩的课堂游戏
  3. 碧水风荷录-第一章(未完,正在整理中……)
  4. string转wchar_t*和QString转wchar_t*
  5. 概率论02-概率,古典概型
  6. notifyDataSetInvalidated()和notifyDataSetChanged()有什么区别
  7. hey 安装_HEY(可能)不是您一直在寻找的电子邮件服务
  8. 基于以太坊ICO的安全合约架构
  9. 【图像增强】基于Step和Polynomial 滤波实现图像增强附matlab代码
  10. 哪个牌子的充电宝转化率高?转化率高的充电宝推荐