目标检测部分 一、目标检测背景知识 目标检测任务是找出图像或视频中人们感兴趣的物体,并同时检测出它们的位置和大小(Bouding box)。不同于图像分类任务,目标检测不仅要解决分类问题,还要解决定位问题,是属于Multi-Task的问题。 目标检测的发展脉络可以划分为两个周期: 传统目标检测算法时期(1998年-2014年) 基于深度学习的目标检测算法时期(2014年-至今) 传统目标检测算法 不同于现在的卷积神经网络可以自动提取高效特征进行图像表示,以往的传统目标检测算法主要基于手工提取特征。
目标检测任务是找出图像或视频中人们感兴趣的物体,并同时检测出它们的位置和大小(Bouding box)。不同于图像分类任务,目标检测不仅要解决分类问题,还要解决定位问题,是属于Multi-Task的问题。
目标检测的发展脉络可以划分为两个周期:
不同于现在的卷积神经网络可以自动提取高效特征进行图像表示,以往的传统目标检测算法主要基于手工提取特征。传统检测算法流程可概括如下:
基于手工提取特征的传统目标检测算法主要有以下三个缺点:
经典传统目标检测算法:
Viola-Jones(VJ) detector(2001),Histogram of Oriented Gradients (HOG) Detector(2005), Deformable Part-based Model (DPM)(2008,2010)
尽管现在基于深度学习的检测器在精度方面已经远远超过了传统检测器,但在他们身上仍然能看到许多来自传统检测器的影响,例如:混合模型,困难样本挖掘,边界框回归等。
这里主要针对最近几年发展比较快的基于深度学习的目标检测算法。经过近7年的发展,目标检测的算法抽象成三个惯用的组件:Backbone, Neck, Head(DenseHead, RoIHead)。
Faster R-CNN是一种两阶段(two-stage)方法,它提出的RPN网络取代了选择性搜索(Selective search)算法后使检测任务可以由神经网络端到端地完成。
在结构上,Faster RCNN将特征抽取(feature extraction),候选区域提取(Region proposal提取),边框回归(bounding box regression),分类(classification)都整合在了一个网络中,使得综合性能有较大提高,在检测速度方面尤为明显。
首先通过传统的 selective search 算法在图片上预取 2000 个左右 Region Proposal;
接着将这些 Region Proposal 通过前处理统一尺寸输入到 CNN 中进行特征提取;
然后把所提取的特征输入到 SVM 支持向量机中进行分类;
最后对分类后的 Region Proposal 进行 bbox 回归。
此时算法的整个过程较为繁琐,速度也较慢。
faster R-CNN之所以叫做 two-stage 检测器,原因是其包括一个区域提取网络 RPN 和 一个RoI Refine 网络 R-CNN(检测网络),同时为了将 RPN 提取的不同大小的 RoI 特征图组成 batch 输入到后面的 R-CNN 中,在两者中间还插入了一个 RoI Pooling 层,可以保证任意大小特征图输入都可以变成指定大小输出。即在RPN提取ROI区域后,送入检测网络再进行分类和回归。
RPN网络的作用:
RPN网络的实现细节:
1个特征图(Faster RCNN的公共Feature Map)经过sliding window处理,得到256维特征,对每个特征向量做两次全连接操作,一个得到2个分数,一个得到4个坐标{然后通过两次全连接得到结果2k个分数和4k个坐标[k指的是由锚点产生的K个框(K anchor boxes)]}
2个分数,即每个结果都有2个分数,因为RPN是提候选框,还不用判断类别,所以只要求区分是不是物体就行,那么就有两个分数,前景(物体)的分数,和背景的分数;
4个坐标,即每个结果都有4个坐标,这里是指对原图的坐标偏移,一定要记住是原图;
9个anchor,faster R-CNN预先设定好的anchor共有9种组合,所以k等于9,最后我们的结果是针对这9种组合的,所以特征图上有H x W x 9个结果,每个特征点共有18个分数和36个坐标。
RPN的损失函数(多任务损失:二分类损失+SmoothL1损失)
训练RPN网络时,对于每个锚点(anchor)我们定义了一个二分类标签(是该物体或不是)。
以下两种情况我们视锚点为了一个正样本标签时:

其中 t_i 和t^*_i分别为网络的预测值和回归的目标
在训练RPN时需要准备好目标t*。它是通过ground-truth box(目标真实box)和anchor box(按一定规则生成的anchor box)计算得出的,代表的是ground-truth box与anchor box之间的转化关系。用这个来训练rpn,那么rpn最终学会输出一个良好的转化关系t。而这个t,是predicted box与anchor box之间的转化关系。通过这个t和anchor box,可以计算出预测框box的真实坐标
RPN中的anchor box是怎么选取的?
滑窗的中心在原像素空间的映射点称为anchor,以此anchor为中心,生成k(paper中default k=9, 3 scales and 3 aspect ratios/不同尺寸和不同长宽比)个proposals。三个面积尺寸128^2,256^2,512^2),然后在每个面积尺寸下,取三种不同的长宽比例(1:1,1:2,2:1)
为什么提出anchor box?<蘑菇街-一面(2018)>
主要有两个原因:一个窗口只能检测一个目标、无法解决多尺度问题。
目前anchor box尺寸的选择主要有三种方式:
(1)人为经验选取
(2)k-means聚类
(3)作为超参数进行学习
为什么使用不同尺寸和不同长宽比?
为了得到更大的交并比(IOU)。
RoI Pooling的过程就是将一个个大小不同的box矩形框,都映射成大小固定(w * h)的矩形框
这样可以从不同大小的方框得到固定大小的相应的feature maps。值得一提的是,输出的feature maps的大小不取决于ROI和卷积feature maps大小。ROI pooling 最大的好处就在于极大地提高了处理速度。
(在Pooling的过程中需要计算Pooling后的结果对应到feature map上所占的范围,然后在那个范围中进行取max或者取average)
优点:
(1)允许我们对CNN中的feature map进行reuse;
(2)可以显著加速training和testing速度;
(3)允许end-to-end的形式训练目标检测系统。
缺点
由于 RoIPooling 采用的是最近邻插值(即INTER_NEAREST) ,在resize时,对于缩放后坐标不能刚好为整数的情况,采用了粗暴的舍去小数,相当于选取离目标点最近的点,损失一定的空间精度。
两次整数化(量化)过程:
1.region proposal的xywh通常是小数,但是为了方便操作会把它整数化。
2.将整数化后的边界区域平均分割成 k x k 个单元,对每一个单元边界进行整数化。
(经过上述两次整数化,此时的候选框已经和最开始回归出来的位置有一定的偏差,这个偏差会影响检测或者分割的准确度)
怎么做的映射:
映射规则:
ROI Align:
ROI Align的思路很简单:取消量化操作,使用双线性内插的方法获得坐标为浮点数的像素点上的图像数值,从而将整个特征聚集过程转化为一个连续的操作;
1.遍历每一个候选区域,保持浮点数边界不做量化。
2.将候选区域分割成k x k个单元,每个单元的边界也不做量化。
3.在每个单元中计算固定四个坐标位置,用双线性内插的方法计算出这四个位置的值,然后进行最大池化操作。
区别:
ROI Align相比RoI Pooling舍去了近似像素取整数的量化方法,改用双线性插值的方法确定特征图坐标对应于原图中的像素位置.
ROI Align很好地解决了ROI Pooling操作中两次量化造成的区域不匹配(mis-alignment)的问题。
对于检测图片中大目标物体时,两种方案的差别不大,而如果是图片中有较多小目标物体需要检测,则优先选择RoiAlign,更精准些。
RoI Align中双线性插值计算像素值的具体方法
在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。
https://www.aiknowledge.cn/images/面经,内容包括机器学习,CV,NLP,推荐,开发/双线性插值.webp
假如我们想得到未知函数 f 在点 P = (x, y) 的值,假设我们已知函数 f 在 Q_{11} = (x_1, y_1)、Q_{12} = (x_1, y_2), Q_{21} = (x_2, y_1) 以及 Q_{22} = (x_2, y_2) 四个点的值。最常见的情况,f就是一个像素点的像素值。首先在 x 方向进行线性插值,得到
然后在 y 方向进行线性插值,得到:
综合起来就是双线性插值最后的结果:
由于图像双线性插值只会用相邻的4个点,因此上述公式的分母都是1。
每个采样点的特征值由其相邻的4个整型特征点的像素值通过双线性差值得到。
限制正负样本比例为1:1,如果正样本不足,就用负样本补充,这种方法后面研究工作用的不多。通常针对类别不平衡问题可以从调整样本数或修改loss weight两方面去解决,常用的方法有OHEM、OHNM、class balanced loss和Focal loss。
给两种锚点分配一个正标签:
(i)具有与实际边界框的重叠最高交并比(IoU)的锚点,
(ii)具有与实际边界框的重叠超过0.7 IoU的锚点。
负标签:IoU比率低于0.3。
其中x,y,w,h分别为bbox的中心点坐标,宽与高。x, x_{a}, x^{*}分别是预测box、anchor box、真实box。
前两行是预测的box关于anchor的offset与scales,后两行是真实box与anchor的offset与scales。那回归的目的很明显,即使t_{i}, t_{i}^{*}得尽可能相近。回归损失函数利用的是Fast-RCNN中定义的smooth L1函数,对外点更不敏感:
损失函数优化权重W,使得测试时bbox经过W运算后可以得到一个较好的平移量(offsets)与尺度(scales),利用这个平移量(offsets)与尺度(scales)可在原预测bbox上微调,得到更好的预测结果。
为什么要做Bounding-box regression?
边框回归用来微调候选区域/框,使微调后的框更Ground Truth更接近。
前向计算过程:
输入一张待检测图片
vgg16网络(或者其他网络,例如:resnet50)conv layers提取整张图片的特征,输出feature map分别输入到RPN和Fast RCNN网络开头
RPN网络得出region proposal,将这些候选框信息送入到Fast RCNN网络开头
利用候选框在之前送到的feature map提取特征,并通过ROI Pooling层得到规定大小的feature map
将这些feature map送入Fast RCNN网络中进行分类和回归坐标,最终得到需检测物体的坐标。
简述faster rcnn训练步骤:
训练RPN,该网络用ImageNet预训练的模型初始化,并端到端微调,用于生成region proposal;
训练Fast R-CNN,由imageNet model初始化,利用第一步的RPN生成的region proposals作为输入数据,训练Fast R-CNN一个单独的检测网络,这时候两个网络还没有共享卷积层;
调优RPN,用第二步的fast-rcnn model初始化RPN再次进行训练,但固定共享的卷积层,并且只微调RPN独有的层,现在两个网络共享卷积层了;
调优Fast R-CNN,由第三步的RPN model初始化fast-RCNN网络,输入数据为第三步生成的proposals。保持共享的卷积层固定,微调Fast R-CNN的fc层。这样,两个网络共享相同的卷积层,构成一个统一的网络。
Mask rcnn网络是基于faster rcnn网络架构提出的新的目标检测网络。该网络可以在有效地完成目标检测的同时完成实例分割。
Mask RCNN主要的贡献在于如下:
改用可学习的 RPN 网络替换selective search 算法进行 Region Proposal 的预取;
总结来说,mask rcnn的主要贡献就是采用了ROI Align以及加了一个mask分支。
YOLO系列算法是一类典型的one-stage目标检测算法,其利用anchor box将分类与目标定位的回归问题结合起来,从而做到了高效、灵活和泛化性能好。
YOLOv1: YOLOv1的核心思想就是利用整张图作为网络的输入,直接在输出层回归 bounding box(边界框) 的位置及其所属的类别。
YOLOv1的基本思想: 把一副图片,首先reshape成448×448大小(由于网络中使用了全连接层,所以图片的尺寸需固定大小输入到CNN中),然后将划分成SxS个单元格(原文中S=7),以每个格子所在位置和对应内容为基础,来预测检测框和每个框的Confidence以及每个格子预测一共C个类别的概率分数。
创新点:
损失函数设计细节:YOLOv1对位置坐标误差,IoU误差,分类误差均使用了均方差作为损失函数。激活函数(最后一层全连接层用线性激活函数,其余层采用leak RELU)
缺点:
YOLOv2: YOLOv2又叫YOLO9000,其能检测超过9000种类别的物体。相比v1提高了训练图像的分辨率;引入了faster rcnn中anchor box的思想,对网络结构的设计进行了改进,输出层使用卷积层替代YOLO的全连接层,联合使用coco物体检测标注数据和imagenet物体分类标注数据训练物体检测模型。相比YOLO,YOLO9000在识别种类、精度、速度、和定位准确性等方面都有大大提升。
**相比于v1的改进: **
YOLOv3: YOLOv3总结了自己在YOLOv2的基础上做的一些尝试性改进,有的尝试取得了成功,而有的尝试并没有提升模型性能。其中有两个值得一提的亮点,一个是使用残差模型,进一步加深了网络结构;另一个是使用FPN架构实现多尺度检测。
改进点:
(x,y,w,h)
由于卷积神经网络具有平移不变性,且anchor boxes的位置被每个栅格固定,因此我们只需要通过k-means计算出anchor boxes的width和height即可
K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
由于从标记文件的width,height计算出的anchor boxes的width和height都是相对于整张图片的比例,特征金字塔上的长宽:
yolov3通过聚类的方式自定义anchor box的大小,在一定程度上,这可以提高定位的准确率。
缺点: 识别物体位置精准性差,召回率低(在每个网格中预测两个bbox这种约束方式减少了对同一目标的多次检测)
SSD网络的特点是对不同尺度下的feature map中的每一个点都设置一些default box,这些default box有不同的大小和横纵比例,对这些default box进行分类和边框回归的操作。SSD的核心是对固定设置的default box(不同尺度feature map中每一个空间位置都设置一组default box,这里只考虑空间位置,不考虑feature的通道个数)计算属于各类物体的概率以及坐标调整的数值。这个计算方式是对每层的feature map做卷积操作,卷积核设定为3*3,卷积核的个数是与default box个数相关。
优点: SSD的优点是运行速度超过yolo,精度在一定条件下超过faster rcnn。缺点是需要人工设置先验框(prior box)和min_size,max_size和长宽比(aspect_ratio)值,网络中default_box的基础大小和形状不能直接通过学习获得,而是需要手工设置,虽然使用了图像金字塔的思路,但是对小目标的recall(召回率)依然一般
SSD有什么致命缺点,如何改进?<长虹AI lab-一面(2020)>
SSD主要缺点:SSD对小目标的检测效果一般,作者认为小目标在高层没有足够的信息,
对小目标检测的改进可以从下面几个方面考虑:
RetinaNet的作者对one-stage检测器准确率不高的问题原因进行探究,发现主要问题在于正负类别不均衡,提出Focal Loss来解决类别不平衡问题。目的是通过减少易分类样本的权重,从而使得模型在训练时更注重于难分类的样本。
RetinaNet网络的结构可归纳为:
RetinaNet由backbone网络和两个子任务网络组成,backbone网络负责计算feature map,子任务网络一个负责目标分类,一个负责bbox回归,网络的loss使用Focal loss。
总的来说,RetinaNet 有两个大创新:
对代码运行流程描述为:
总结:FPN 模块接收 c3, c4, c5 三个特征图,输出 P2-P7 五个特征图,通道数都是 256, stride 为 (8,16,32,64,128),其中大 stride (特征图小)用于检测大物体,小 stride (特征图大)用于检测小物体。
P6 和 P7 目的:
提供一个大感受野强语义的特征图,有利于大物体和超大物体检测。
Cascade R-CNN 主要针对 Faster R-CNN 中 R-CNN 部分 IoU 阈值选取对最终检测 bbox 质量有重大影响,而提出一种级联 R-CNN 结构,不同级采用不同 IoU 阈值来进行重新计算正负样本和采样策略来逐渐提高 bbox 质量。
FPN网络直接在Faster R-CNN单网络上做修改,每个分辨率的 feature map 引入后一分辨率缩放两倍的 feature map 做 element-wise 相加的操作。通过这样的连接,每一层预测所用的 feature map 都融合了不同分辨率、不同语义强度的特征,融合的不同分辨率的 feature map 分别做对应分辨率大小的物体检测。这样保证了每一层都有合适的分辨率以及强语义(rich semantic)特征。同时,由于此方法只是在原网络基础上加上了额外的跨层连接,在实际应用中几乎不增加额外的时间和计算量。
假设两路输入来说,如果是通道数相同且后面带卷积的话,add等价于concat之后对应通道共享同一个卷积核。FPN里的金字塔,是希望把分辨率最小但语义最强的特征图增加分辨率,从性质上是可以用add的。如果用concat,因为分辨率小的特征通道数更多,计算量是一笔不小的开销。所以FPN里特征融合使用相加操作可以理解为是为了降低计算量。
低层的特征语义信息比较少,但是目标位置准确;高层的特征语义信息比较丰富,但是目标位置比较粗略。原来多数的object detection算法都是只采用顶层特征做预测。FPN同时利用低层特征高分辨率和高层特征的高语义信息,通过融合这些不同特征层的特征达到预测的效果。并且预测是在每个融合后的特征层上单独进行的。所以可以提升小目标的准确率。
在FPN的每个预测层上都接一个RPN子网,确定RPN子网的正负anchor box样本,再计算各预测层上RPN的anchor box分类和回归损失,利用BP将梯度回传更新权值
SSD的基础网络是VGG,且SSD在使用多层feature map时只是简单的在不同层的feature map上放default box,并没有真正将低维度特征和高维度特征进行融合。且SSD网络中使用的控制正负样本数量比的方法是难样本挖掘方法,loss是分类+回归的loss。而RetinaNet网络的基础网络是resnet+FPN,是真正将低维度的特征和高维度的特征进行了特征融合后再来做检测的。且控制正负样本的方法是使用Focal Loss。
针对之前RCNN系列selective search的方法导致算法没有实时性,所以faster rcnn提出RPN网络来取代之前的方法,可以理解为fasterrcnn=fast rcnn+rpn网络,且rpn网络和fast rcnn的分类,回归网络共用特征提取层,这样使得引入RPN网络不会增加太多计算量。整体流程为先使用RPN网络找出可能存在object的区域,再将这些区域送入fast rcnn中进一步定位和分类。所以faster rcnn是典型的Two stage算法。因为faster rcnn中包含了两次定位,所以其精度一般高于YOLO和SSD算法,所以速度一般慢于YOLO和SSD。
YOLO算法的特点是将检测问题转换成回归问题,即YOLO直接通过回归一次既产生坐标,又产生每种类别的概率。YOLO中将每张图分成7*7的网格,每个网格默认可能属于2个object,即在一张图片上提取98个region proposal,相比于faster rcnn使用Anchor机制提取20k个anchor再从中提取最终的300个region proposal,所以faster rcnn的精度比YOLO要高,但是由于需要处理更多region proposal,所以faster rcnn的速度要比YOLO慢。
SSD相比于faster rcnn使用了多层网络特征,而不仅仅使用最后一层feature map。SSD还借鉴了YOLO算法中将检测任务转换为回归任务的思想,且SSD也借鉴了faster rcnn中的anchor机制,只是SSD的anchor不是每个位置的精调,而是类似于YOLO那样在feature map上分割出网格,在网格上产生anchor。但是SSD和YOLO不需要selective search步骤,所以SSD和YOLO同属于One-Stage算法。
SSD,YOLO等单阶段多尺度算法,小目标检测需要较高的分辨率,SSD对于高分辨的低层特征没有再利用,而这些层对于检测小目标很重要。按SSD的设计思想,其实SSD对小目标应该有比较好的效果,但是需要重新精细设计SSD中的default box,比如重新设计min_sizes参数,扩大小default box的数量来cover住小目标。但是随着default box数量的增加,网络速度也会降低。YOLO网络可以理解为是强行把图片分割成7*7个网格,每个网格预测2个目标,相当于只有98个anchor,所以不管是小目标,还是大目标,YOLO的表现都不是很理想,但是由于只需处理少量的anchor,所以YOLO的速度上有很大优势。
Faster rcnn系列对小目标检测效果不好的原因是faster rcnn只用卷积网络的最后一层,但是卷积网络的最后一层往往feature map太小,导致之后的检测和回归无法满足要求。甚至一些小目标在最后的卷积层上直接没有特征点了。所以导致faster rcnn对小目标检测表现较差。
目标检测中的损失函数通常由两部分组成:classification loss 和 bounding box regression loss。
ps: focal loss出来之后,不少loss基于focal loss延伸
回归损失:
其中,ρ表示预测框和标注框中心端的距离,p和g是两个框的中心点。c表示两个框的最小包围矩形框的对角线长度。当两个框距离无限远时,中心点距离和外接矩形框对角线长度无限逼近,R→1
Focal loss主要是为了解决one-stage目标检测中正负样本比例严重失衡的问题。该损失函数降低了大量简单负样本在训练中所占的权重,也可理解为一种困难样本挖掘
添加参数γ,当γ大于0时,对于易分的正样本或负样本,权重小,而对于难区分的样本则权重大,避免让简单样本主导loss,γ越大,困难样本的权重越大
添加参数α,用来平衡正负样本本身的比例不均
其中,文中参数是**α=0.25,γ=2**
数据和标签
数据分类标注是否准确?数据是否干净?数据库太小一般不会带来不收敛的问题,只要你一直在train总会收敛(rp问题跑飞了不算)。反而不收敛一般是由于样本的信息量太大导致网络不足以fit住整个样本空间。样本少只可能带来过拟合的问题
学习率设定不合理
在自己训练新网络时,可以从0.1开始尝试,如果loss不下降的意思,那就降低,除以10,用0.01尝试,一般来说0.01会收敛,不行的话就用0.001. 学习率设置过大,很容易震荡。不过刚刚开始不建议把学习率设置过小,尤其是在训练的开始阶段。在开始阶段我们不能把学习率设置的太低否则loss不会收敛。我的做法是逐渐尝试,从0.1,0.08,0.06,0.05 ......逐渐减小直到正常为止,
网络设定不合理
如果做很复杂的分类任务,却只用了很浅的网络,可能会导致训练难以收敛,换网络换网络换网络,重要的事情说三遍,或者也可以尝试加深当前网络。
数据集label的设置
检查lable是否有错,有的时候图像类别的label设置成1,2,3正确设置应该为0,1,2。
改变图片大小
改变图片大小有时可以解决收敛问题
数据归一化
神经网络中对数据进行归一化是不可忽略的步骤,网络能不能正常工作,还得看你有没有做归一化,一般来讲,归一化就是减去数据平均值除以标准差,通常是针对每个输入和输出特征进行归一化
计算IOU非常简单,有两种方法:
两个矩形的宽之和减去组合后的矩形的宽就是重叠矩形的宽,重叠矩形的高计算同宽
右下角的min(x)减去左上角的max(x)就是重叠矩形的宽,重叠矩形的高计算同宽
然后 IOU = 重叠面积 / (两矩形面积之和 — 重叠面积)
参考代码(第二种方法):
# IOU计算 # 假设box1维度为[N,4] box2维度为[M,4] def iou(self, box1, box2): N = box1.size(0) M = box2.size(0) lt = torch.max( # 左上角的点 box1[:, :2].unsqueeze(1).expand(N, M, 2), # [N,2]->[N,1,2]->[N,M,2] box2[:, :2].unsqueeze(0).expand(N, M, 2), # [M,2]->[1,M,2]->[N,M,2] ) rb = torch.min( box1[:, 2:].unsqueeze(1).expand(N, M, 2), box2[:, 2:].unsqueeze(0).expand(N, M, 2), ) wh = rb - lt # [N,M,2] wh[wh < 0] = 0 # 两个box没有重叠区域 inter = wh[:,:,0] * wh[:,:,1] # [N,M] area1 = (box1[:,2]-box1[:,0]) * (box1[:,3]-box1[:,1]) # (N,) area2 = (box2[:,2]-box2[:,0]) * (box2[:,3]-box2[:,1]) # (M,) area1 = area1.unsqueeze(1).expand(N,M) # (N,M) area2 = area2.unsqueeze(0).expand(N,M) # (N,M) iou = inter / (area1+area2-inter) return iou
其实就是多尺度的滑动窗口
两者都可以理解为整合特征图信息。concat是通道数的增加;add是特征图相加,通道数不变。
add是描述图像的特征下的信息量增多了,但是描述图像的维度本身并没有增加,只是每一维下的信息量在增加,这显然是对最终的图像的分类是有益的。而concat是通道数的合并,也就是说描述图像本身的特征数(通道数)增加了,而每一特征下的信息是没有增加。
concat每个通道对应着对应的卷积核。 而add形式则将对应的特征图相加,再进行下一步卷积操作,相当于加了一个先验:对应通道的特征图语义类似,从而对应的特征图共享一个卷积核(对于两路输入来说,如果是通道数相同且后面带卷积的话,add等价于concat之后对应通道共享同一个卷积核)。因此add可以认为是特殊的concat形式。但是add的计算量要比concat的计算量小得多。
map计算方法
首先计算某一类别的AP值。不同数据集的某类别的AP计算方法大同小异,主要分为三种:
(1)在VOC2010以前,只需要选取当Recall >= 0, 0.1, 0.2, ..., 1共11个点时的Precision最大值,然后AP就是这11个Precision的平均值,map就是所有类别AP值的平均。
(2)在VOC2010及以后,需要针对每一个不同的Recall值(包括0和1),选取其大于等于这些Recall值时的Precision最大值,然后计算PR曲线下面积作为AP值,map就是所有类别AP值的平均。
(3)COCO数据集,设定多个IOU阈值(0.5-0.95,0.05为步长),在每一个IOU阈值下都有某一类别的AP值,然后求不同IOU阈值下的AP平均,就是所求的最终的某类别的AP值。
最后,mAP值即:所有类的AP值平均值。
速度指标
一般来说目标检测中的速度评价指标有:
(1)FPS,检测器每秒能处理图片的张数
(2)检测器处理每张图片所需要的时间
FLOPs的定义:
FLOPS(全大写): 是floating point operations per second的缩写,意指每秒浮点运算次数,理解为计算速度,是一个衡量硬件性能的指标。
FLOPs(s小写): 是floating point operations的缩写(s表复数),意指浮点运算数,理解为计算量,可以用来衡量算法/模型的复杂度
同一硬件情况下,它的最大FLOPS是相同的,不同网络,处理每张图片所需的FLOPs(浮点运算次数)是不同的,所以同一硬件处理相同图片所需的FLOPs越小,相同时间内,就能处理更多的图片,速度也就越快。
处理每张图片所需的FLOPs与许多因素有关,比如你的网络层数,参数量,选用的激活函数等等,这里仅谈一下网络的参数量对其的影响,一般来说参数量越低的网络,FLOPs会越小,保存模型所需的内存小,对硬件内存要求比较低,因此比较对嵌入式端较友好。
FLOPs计算(以下计算FLOPs不考虑激活函数的运算)
标准卷积层的FLOPs
FLOPs=(2*C_{in}*k^2 - 1)*H*W*C_{out}(不考虑bias)
FLOPs=(2*C_{in}*k^2)*H*W*C_{out}(考虑bias)
C_{in}为输入特征图通道数,K为卷积核边长,H,W,C_{out}分别为输出特征图的高,宽和通道数。
深度可分离卷积的FLOPs
深度可分离卷积分成两部分,一部分是分通道卷积,另一部分是1*1卷积。(可大大减少计算量的卷积方法)
讨论以考虑bias为准:
最终结果: FLOPs = FLOPs_1 + FLOPs_2
池化层的FLOPS
这里又分为全局池化和一般池化两种情况:(注意:池化层的C_{in}=C_{out})
全局池化:
针对输入所有值进行一次池化操作,不论是max、sum还是avg,都可以简单地看做是只需要对每个值算一次。
所以结果为:FLOPs = H_{in}*W_{in}*C_{in}
一般池化:
结果为FLOPs=(k^2)*H_{out}*W_{out}*C_{out}
全连接层的FLOPs
考虑bias:(2*C_{in})*C_{out}
不考虑bias:(2*C_{in} - 1)*C_{out}
激活层的FLOPs
ReLU:
ReLU一般都是跟在卷积层的后面,这里假设卷积层的输出为H_{out}*W_{out}*C_{out}因为ReLU函数的计算只涉及到一个判断,因此计算量就是:H_{out}*W_{out}*C_{out}
Sigmoid
根据sigmoid的公式可以知道,每个输入都需要经历4次运算,因此计算量是:H_{out}*W_{out}*C_{out}*4
标准卷积层的参数量
不考虑bias: (C_{in}*k^2)*C_{out}
考虑bias: (C_{in}*k^2+1)*C_{out}
深度可分离卷积的参数量
深度可分离卷积分成两部分,一部分是分通道卷积,另一部分是1*1卷积。(可大大减少计算量的卷积方法)
这里不考虑bias为准:
池化层的参数量
池化层没有需要学习的参数,所以参数量为0。
全连接层的参数量
考虑bias:C_{in}*C_{out} + 1
简介: k-means算法是一种聚类算法,所谓聚类,即根据相似性原则,将具有较高相似度的数据对象划分至同一类簇,将具有较高相异度的数据对象划分至不同类簇。聚类与分类最大的区别在于,聚类过程为无监督过程,即待处理数据对象没有任何先验知识,而分类过程为有监督过程,即存在有先验知识的训练数据集。
K-means算法原理: K-means算法中的k代表类簇个数,means代表类簇内数据对象的均值(这种均值是一种对类簇中心的描述),因此,k-means算法又称为k-均值算法。k-means算法是一种基于划分的聚类算法,以距离作为数据对象间相似性度量的标准,即数据对象间的距离越小,则它们的相似性越高,则它们越有可能在同一个类簇。数据对象间距离的计算有很多种,k-means算法通常采用欧氏距离来计算数据对象间的距离。算法详细的流程描述如下:
k-means算法优缺点分析:
用处: 本质是搜索局部极大值,抑制非极大值元素。
原理: NMS为非极大值抑制,用来抑制检测时冗余的框。
大致算法流程为:
1.对所有预测框的置信度降序排序
2.选出置信度最高的预测框,确认其为正确预测,并计算他与其他预测框的IOU
3.根据2中计算的IOU去除重叠度高的,IOU>threshold阈值就删除
4.剩下的预测框返回第1步,直到没有剩下的为止
(需要注意的是:Non-Maximum Suppression一次处理一个类别,如果有N个类别,Non-Maximum Suppression就需要执行N次)
假设两个目标靠的很近,则会识别成一个bbox,会有什么问题,怎么解决?
当两个目标靠的非常近时,置信度低的会被置信度高的框抑制掉,从而两个目标靠的非常近时会被识别成一个bbox。为了解决这个问题,可以使用soft-NMS(基本思想:用稍低一点的分数来代替原有的分数,而不是直接置零)
参考代码:
# bboxes维度为[N,4],scores维度为[N,], 均为tensor def nms(self, bboxes, scores, threshold=0.5): x1 = bboxes[:,0] y1 = bboxes[:,1] x2 = bboxes[:,2] y2 = bboxes[:,3] areas = (x2-x1)*(y2-y1) # [N,] 每个bbox的面积 _, order = scores.sort(0, descending=True) # 降序排列 keep = [] while order.numel() > 0: # torch.numel()返回张量元素个数 if order.numel() == 1: # 保留框只剩一个 i = order.item() keep.append(i) break else: i = order[0].item() # 保留scores最大的那个框box[i] keep.append(i) # 计算box[i]与其余各框的IOU(思路很好) xx1 = x1[order[1:]].clamp(min=x1[i]) # [N-1,] yy1 = y1[order[1:]].clamp(min=y1[i]) xx2 = x2[order[1:]].clamp(max=x2[i]) yy2 = y2[order[1:]].clamp(max=y2[i]) inter = (xx2-xx1).clamp(min=0) * (yy2-yy1).clamp(min=0) # [N-1,] iou = inter / (areas[i]+areas[order[1:]]-inter) # [N-1,] idx = (iou <= threshold).nonzero().squeeze() # 注意此时idx为[N-1,] 而order为[N,] if idx.numel() == 0: break order = order[idx+1] # 修补索引之间的差值 return torch.LongTensor(keep) # Pytorch的索引值为LongTensor
拓展:手撕soft-nms
小目标难以检测的原因: 分辨率低,图像模糊,携带的信息少。
借鉴FPN的思想,在FPN之前目标检测的大多数方法都是和分类一样,使用顶层的特征来进行处理。虽然这种方法只是用到了高层的语义信息,但是位置信息却没有得到,尤其在检测目标的过程中,位置信息是特别重要的,而位置信息又是主要在网络的低层。因此FPN采用了多尺度特征融合的方式,采用不同特征层特征融合之后的结果来做预测。
要让输入的分布尽可能地接近模型预训练的分布。先用ImageNet做预训练,之后使用原图上采样得到的图像来做微调,使用微调的模型来预测原图经过上采样的图像。该方法提升效果比较显著。
采用多尺度输入训练方式来训练网络;
借鉴Cascade R-CNN的设计思路,优化目标检测中Two-Stage方法中的IOU阈值。检测中的IOU阈值对于样本的选取是至关重要的,如果IOU阈值过高,会导致正样本质量很高,但是数量会很少,会出现样本比例不平衡的影响;如果IOU阈值较低,样本数量就会增加,但是样本的质量也会下降。如何选取好的IOU,对于检测结果来说很重要。
采用分割代替检测方法,先分割,后回归bbox来检测微小目标。
输入图片的尺寸对检测模型的性能影响相当明显,事实上,多尺度是提升精度最明显的技巧之一。在基础网络部分常常会生成比原图小数十倍的特征图,导致小物体的特征描述不容易被检测网络捕捉。通过输入更大、更多尺寸的图片进行训练,能够在一定程度上提高检测模型对物体大小的鲁棒性,仅在测试阶段引入多尺度,也可享受大尺寸和多尺寸带来的增益。
检测网络SSD中最后一层是由多个尺度的feature map一起组成的。FPN网络中采用多尺度feature map分层融合,分层预测的方法可以提升小目标的检测效果。
图像金字塔: 人脸检测的MTCNN就是图像金字塔,使用多种分辨率的图像送到网络中识别,时间复杂度高,因为每幅图都要用多种scale去检测。
特征金字塔: FPN网络属于采用了特征金字塔的网络,一次特征提取产生多个feature map即一次图像输入完成,所以时间复杂度并不会增加多少
anchors: faster rcnn多个anchor带来的多种尺寸的roi可以算muti scale思想的应用。
小目标不好检测的两大原因:
改进方法:
RRPN也是基于Faster R-CNN,引入RPN,它对比CTPN加入了旋转信息(即:通过生成更加密集的旋转Anchor 来适应旋转框检测的任务)。CTPN只能检测水平文本,而RRPN可以检测任意方向的文本,因为CTPN的提议框是水平的,而RRPN的提议框带有旋转角度。
为什么提出旋转的提议框呢?
因为水平提议框在检测倾斜文本的时候会带有一些冗余(非文本部分)
1.https://mp.weixin.qq.com/s/b40PdGB7o95jmPMEIICBUQ
2.https://zhuanlan.zhihu.com/p/349807581
3.https://zhuanlan.zhihu.com/p/7030601
4.https://zhuanlan.zhihu.com/p/346198300
5.https://blog.csdn.net/gaoyi135/article/details/105912701
6.https://zhuanlan.zhihu.com/p/51680715
7.https://www.nowcoder.com/discuss/515113
8.https://www.nowcoder.com/discuss/181413
9.https://zhuanlan.zhihu.com/p/89450552
10.https://blog.csdn.net/liuxiao214/article/details/83043197
11.https://www.nowcoder.com/discuss/267852
12.https://blog.csdn.net/qq_33638791/article/details/79802934
13.https://www.nowcoder.com/discuss/245668
13.https://www.nowcoder.com/discuss/250532
14.https://www.nowcoder.com/discuss/238556
15.https://blog.csdn.net/qq_42109740/article/details/105740704
16.https://zhuanlan.zhihu.com/p/360952172
17.https://zhuanlan.zhihu.com/p/346198300
18.https://zhuanlan.zhihu.com/p/54709759
19.https://blog.csdn.net/weixin_43750248/article/details/116656242
20.https://blog.csdn.net/qq_24502469/article/details/105121529
21.https://baijiahao.baidu.com/s?id=1622412414004300046&wfr=spider&for=pc