深度学习物体检测:CornerNet

CornerNet是一种创新的物体检测方法,使用热图预测边界框的左上角和右下角,无需依赖锚框。文章深入解析CornerNet的原理,包括CornerPooling、Embedding和Offsets的使用,以及与传统锚框方法的对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深度学习物体检测:CornerNet

https://blog.youkuaiyun.com/linmingan/article/details/82786516

很有意思的一篇文章,使用热图来预测bbox的左上角和右下角,这两个边角点的坐标,而不依赖于anchor box。在人体姿态检测和人脸特征点识别领域里面,有不少论文都是使用热图来表示坐标点。由于bbox也是一组坐标点,所以在物体检测应当也可以使用热图来做,该论文便是一个很好的思路。论文的基础网络使用的是HG网络(漏斗网络),并且又两个HG网络堆叠起来,因此模型还是很大的。根据作者提供的训练好的模型文件,有768M(https://drive.google.com/uc?id=1UHjVzSG27Ms0VfSFeGYJ2h2AYZ6d4Le_&export=download), 在titanX上的平均预测速度是244ms每张图片。论文的检测结果会比一阶段的方法好,并且也比一些二阶段的检测方法要好,但是速度上却没那么令人满意。个人猜测应该是HG网络引起的,因为HG网络会对特征图进行下采样,然后再上采样;同时cornerNet的输入是511*511,输出是128*128,这使得cornerNet的基础网络所需的计算量太大了。所以不要看到cornerNet这么慢,就觉得这个方法不行,后续的改进空间还是很大的。

先简单回忆一下anchor box。利用anchor box进行bbox检测时,我们一般是对大小为W*H的网格进行操作的。网格中的每个位置作为多个anchor box(比如faster rcnn中每个点有9个anchor box)的中心点,然后预测每个anchor box的中心点x,y坐标偏移量和宽高缩放尺度。这样就得到了最后的bbox。

那么,anchor box有什么问题呢?作者认为有两个问题:
1、anchor box的数量实在太多了,比如DSSD有40K个,RetinaNet有100K个。在那么多的anchor box里面,正负样本的比例严重失衡。并且使得训练速度很慢。(然而由于cornerNet的基础网络太大,训练起来也是很慢)
2、anchor box 的超参数太多了,比如要选多少个box啊,他们的size是多少啊,以及宽高比怎么设置啊。当与多尺度检测结合起来,这些超参数的设置就更复杂了。

CornerNet的方法为啥比基于anchor box的方法更牛逼?作者认为有两个原因:
第一个、预测anchor box的中心点坐标要考虑四个方向的因素,左、右、上和下。而cornerNet在定位边角点时只要考虑两个方向的因素,比如要定位左上边角点,我们只需要观察物体的最上边点边界和最左边的边界。
第二个、用边界点来表示bbox,会更高效:因为只使用O(wh)O(wh)O(wh)量级的边角点,就可以表示O(w2h2)O(w^2h^2)O(w2h2)量级的anchor box。

扯了那么多,我们开始cornerNet的具体内容吧。

概览

先看论文最先给出的一张整体构架图:
在这里插入图片描述

说实在的,第一次看到这张图,内心是,WTF???这是在说什么,是我太菜了吗,原谅我,看不懂!!!那个热图我知道什么意思,可是那个embedding是什么鬼,热图和embedding怎么搞在一块,然后输出坐标的?不过,我们还是能知道网络预测的是bbox的左上角点和右下角点。
所以,不看这张图了,看论文中的另一张图:
在这里插入图片描述
输入图片经过HG基础网络后,得到一个特征图,然后将该特征图作为两个Prediction模块的输入,分别是Top-left corners和Bottom-right corners。在每个预测模块里面,先经过Corner Pooling,然后输出Heatmaps,Embeddings,Offsets分支。我们先不管Corner Pooling了,先认为是一个普通的Pooling,只是这个Pooling不改变特征图尺寸。

Heatmaps的大小是128*128,通道为80(coco数据,80类),所以Heatmaps是一个大小为128*128*80的张量。以Top-left corners模块中的Heatmaps为例,其每个通道代表coco数据中的80个类别,每个通道的128*128网格中的每个点的输出表示该点是一个左上角点的概率。并且该通道预测出来的所有左上角点对应的所有bbox的物体类别都一样。举个例子,假设在通道编号为10(假设物体类别是dog)的128*128热图里面,预测出了3个左上角点,也就是有3个bbox,那么这3个bbox的物体类别都是dog。

Offsets大小为128*128,通道为2(分别为边角点x,y的偏移量)。由于用热图来表示某一点的xy坐标,会损失精度。因此cornerNet还对每个边角点预测其真实位置的偏移量。举个例子,假设通过热图预测出某一左上角点的坐标是(50,50),该坐标的对应尺度是热图的128*128,而真实的坐标从网络的输入尺度511*511,映射到128*128时是(50.2,50.6)这样就损失了精度了。现在cornerNet为(50,50)预测了偏移量为(0.3,0.5),那么可以计算出网络最终的预测坐标为(50.3,50.5)。尽管比真正的坐标(50.2,50.6)差了一点,但比(50,50)还是精确了许多。

Embedding大小为128*128,通道为1。这个Embedding的作用是什么呢?现在假设两个预测模块已经分别预测出了100个左上角点,和100个右下角点。那么有个问题,怎么知道哪一个左上角点和哪一个右上角点是属于同一个bbox呢?解决方法就是使用这个Embedding。Top-left预测模块和Bottom-right预测模块都有一个128*128的Embedding,简单来说,这两个Embedding中的每个值相当于一个标签。假设在Top-left预测模块里的Embedding的(50,50)位置的值是10(这个值是多少无所谓),那么其表示Top-left位置为(50,50)的左上角点的标签是10。如果,在Bottom-right预测模块里的Embedding的(100,100)位置的值也是10。那么就认为左上角坐标(50,50)和右下角坐标(100,100)属于同一个bbox。在实际应用中,属于同一个bbox的左上角和右下角的embedding值一般不会完全一样(到后面的Emdedding学习就可以知道为啥了),所以论文在判断左上角点和右上角点是否属于同一bbox的时是通过判断两个点所对应的embedding值的距离。

那么,整个检测过程大致如下:cornerNet分别输出左上角预测模块和右下角预测模块的Heatmaps、Embeddings和Offsets后。首先利用各自的Heatmaps计算出xy坐标,然后利用各自的Offsets修正xy坐标。接着利用各自的Embeddings信息收集同一bbox的左上角点和右下角点。

接下来详细看看每个模块的内容。

边角点检测

cornerNet在预测左上角点和右上角点时,首先会分别生成大小为W*H*C的热图。其中C表示通道,其值等于物体检测的物体类别数,比如coco的80个类别。

正常情况下,可以不使用热图,而是每一通道中的W*H矩阵中每个位置要么是0要么是1,1表示该位置是一个边角点。但是这样一来,由于bbox比较少,也就是在W*H的矩阵中值为1的位置会很少,而0会很多。即正位置很少,负位置很多。在训练过程中,不会对所有的负位置采用同样的惩罚权重,而是在正位置附近的负位置减少惩罚权重。相当于,在预测的时候将正位置附近的负位置认为是正位置也是可接受的。那么这个附近点怎么确定呢?这时候热图就起作用了。热图的生成利用的是2D高斯函数,exp(x2+y22σ2)\exp(-\frac{x^2+y^2}{2\sigma^2})exp(2σ2x2+y2)(这是一个没有归一化的高斯函数),x,y是正位置的领域点的坐标,正位置的领域点一般是取某一半径范围内的点。这个半径可以根据物体大小来确定,具体可以参考作者提供的代码。σ\sigmaσ是半径值的三分之一。

作者使用了一个变种的focal loss作为损失函数:
在这里插入图片描述
其中pcijp_{cij}pcij表示类别c并且位置为(i,j)是边角点的概率。ycijy_{cij}ycij是真实标签,如果某一真实bbox的边角点的位置是(i
,j)并且物体类别是c那么ycij=1y_{cij}=1ycij=1。N是所有的真实bbox个数。α,β\alpha,\betaα,β 是超参数。

上面的公式中,当ycij!=1y_{cij}!=1ycij!=1时,也就是负位置时,前面加多了 1ycij1-y_{cij}1ycij,这个就是用来减少正位置附近的位置的惩罚权重。

在前面的概览中,提到了offsets。offsets就是为了避免将真实边角点坐标用热图表示而引起精度损失而引入的。假设第k个真实的边角点的位置为xk,ykx_k,y_kxk,yk,可以计算其偏移量为:在这里插入图片描述
其中n表示网络输入尺寸与网络输出尺寸的比值,或者说下采样因子。在实际使用中,所有类别的边角点都共用一个offsets。在训练的时候采用smooth L1损失函数:
在这里插入图片描述

边角点聚集

由于在一张图片中有可能有多个物体,这时候就会检测出来多个左上角点和右下角点。那么就需要确定某一对左下角点和右下角点对是否属于同一个bbox。这位问题在概览中的embedding已经有了一定的描述。这边主要看是如何学习embedding的。根据两个embedding的功能,希望网络输出的两个embedding中,属于同一bbox的左上角点和右下角点的embdding值应该是要很相近的。为此,可以使用以下损失函数:
在这里插入图片描述
k表示第k个bbox,etkebke_{tk}、e_{bk}etkebk分别表示第k个bbox左上角点的embedding值和右下角点的embedding值。而eke_kek则是etke_{tk}etkebke_{bk}ebk的均值。LpullL_{pull}Lpull目的是使属于同一bbox的边角点的embedding值尽量一样。LpushL_{push}Lpush目的是使不同的bbox的embedding值要有区分度。

Corner Pooling

在确定一个像素是否是左上角点时,需要在水平方向上往右看,在竖直方向上往下看。在确定是否时右下角点时,则需要在水平方向上往左看,在竖直方向上往上看。因此作者提出了corner polling。具体如下图:
在这里插入图片描述
上图展示的时top-left corner poolling,对于左上角的corner pooling根据一开始的分析,需要分别往下扫描和往右扫描,然后分别取最大值,最后相加。下图是一个实际的例子:

在这里插入图片描述

预测模块结构

预测模块的结构图如下:
在这里插入图片描述

Backbone是基础网络部分,后面就是预测部分,感觉没啥好说的,具体还是看代码为主。

实验结果

作者不仅跟之前的物体检测方法做了对比,还对corner pooling、负位置损失函数权重减小以及有没有加offsets进行了详细的实验。这里只贴出跟其他方法对比的结果。相对于一阶段的方法,cornerNet还是完胜的,同时还是比一些二阶段的效果要好不少。
在这里插入图片描述

转载于:https://www.cnblogs.com/yumoye/p/10964986.html

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值