写在前面:此文只记录了下本人感觉需要注意的地方,不全且不一定准确。详细内容可以参考文中帖的链接,比较好!!!
RCNN系列
1.R-CNN
- 通过选择性搜索在原图上来获取候选区域(region proposal,2000个),再对每个ROI进行CNN,再通过SVM和线性回归来分类和预测
- 选择性搜索:以每个像素为一组,计算每一组的纹理,合并最接近的;然后对融合后的小组在进行分组…至整张图片所有区域都结合在一起
- 缺点:2000个ROI会有很多重复的,重复提取特征,很慢
2.Fast R-CNN
- 通过CNN提取原图片特征得到feature map,在feature map上选择性搜索得到ROI,将ROI和feature map送入ROI pooling得到最后特征,再进行分类和回归
- 缺点:ROI选取方法采用选择性搜索,在cpu上运行很慢,约2秒一张图
3.Faster R-CNN
- 在Fast R-CNN基础上,采用RPN网络代替selective search来提取ROI,时间也就从2s缩减到了10ms,更快更准
Faster rcnn源码解读记录
- shared convolutional layers
【输入图片大小: 600 ∗ 800 600*800 600∗800,输出feature map 大小: 38 ∗ 50 38*50 38∗50】
使用ResNet的conv1到conv4_x部分,提取输入图片特征,得到的conv_feat特征将输入至RPN网络和ROI Pooling。 - RPN layers
【输入feature map: 38 ∗ 50 38*50 38∗50, 输出分为2个支路,一条用来预测proposal的坐标偏置: 1 ∗ 36 ∗ 38 ∗ 50 1*36*38*50 1∗36∗38∗50,一条用来预测proposal的标签: 1 ∗ 18 ∗ 38 ∗ 50 1*18*38*50 1∗18∗38∗50】
a. 首先说明一下anchor 和 proposal的区别:anchor是固定不变的,给定一个feature map的点能固定出对应的anchor,其标签通过和gt计算的IOU得到,也是固定的;而proposal是模型预测的框(RPN的目的就是输出proposal,要尽可能与gt接近)。但anchor和proposal不是相互独立的,一个anchor对应一个proposal。
b. RPN网络结构:首先采用一个 3 ∗ 3 3*3 3∗3卷积核进行sliding window操作,目的是将每个feature map的点额外加入周围的空间信息;然后基于该卷积层的输出引出两条支路,一条用来预测proposal的标签,一条用来预测proposal的坐标偏置 - classification & bounding box regression
分类采用cross entropy损失函数、回归采用smoothl1损失函数。虽然输入该层的anchor有$ 38 *50 9 $ =17100个,但是实际训练只用到了256个(根据IOU排序选的)来训练网络;在回归时,rpn_bbox_target是根据初始anchor和ground truth计算出来的offset,因此RPN预测的值也不是预测框的坐标,而是预测的proposal与anchor的offset(偏移量) - ROI proposal
【输出:proposal的得分类别概率(1,18,38,50)、proposal的坐标偏置(1,36,38,50),输出:rois(2000,5)】
a. 这一部分的最终目的是对前面RPN网络生成的proposal(17100个)做过滤,因为proposal总数较多,而且多数proposal之间都是相互重叠的,因此考虑到效率,需要对proposal做过滤。
b. 首先通过RPN中对proposal的分类对foreground的得分进行排序,从17100筛选至12000个;然后通过NMS算法(阈值0.7),计算剩下的proposal的重叠率筛选为2000个,最后该层的输出roi的维度是2000*5(第一参数是batch的index,2-4是对应在原图片上的框的坐标,左上角和右下角) - ROI proposal target
【输入:rois(2000,5)、gt_boxes(x,5,x表示图中object数量),输出:group】
将2000个rois结合gt后下降到128个rois,这里介绍一下group(结果集合),group[0]是rois,维度是128*5,这个128是默认的roi的batch size,要注意5列中除了4个坐标列外,另一列是index,而不是标签。group[1]是label,也就是roi对应的标签。group[2]是bbox_target,是坐标回归的目标,维度是(128,84)。group[3]是bbox_weight,是坐标回归时候的权重,维度是(128,84),这个权重对于foreground都是1,对于backgroud都是0。【这块默认rois的个数可以决定测试阶段每张图检测出多少个框吧?】 - ROI Pooling
【输入:feature map ( 1 , 1024 , 38 , 50 ) 、 r o i s ( 128 , 5 ) (1,1024,38,50)、rois(128,5) (1,1024,38,50)、rois(128,5),输出:roi_pool(128,1024,14,14)】
目的在于将大小不一的roi处理成统一的大小。首先将rois在原图中框的位置映射至feature map上得到相对应的框,然后根据指定的pool_w(14)、pool_h(14)等分feature map上的框,每一个网格做pool. - ResNet conv5
【输入:roi_pool(128,1024,14,14),输出:pool1(128,2048,1,1)】 - classification & bounding box regression
【输入:pool1(128,2048,1,1),输出:cls_score(128,21)、bbox_pred(128,84)】
分类采用cross entropy损失函数、回归采用smoothl1损失函数。
4.Mask R-CNN
- 在Faster R-CNN基础上,考虑到ROI Pooling操作会产生严重的量化误差,导致结果有误差(更主要体现在一些分割任务上)。提出了一种ROI Align的方法代替ROI Pooling。
主要说一下ROI Align与ROI Pooling的区别
如上图所示,RoI Pooling和RoIAlign最大的区别是:前者使用了两次量化操作,而后者并没有采用量化操作,使用了线性插值算法。
- ROI Pooling的局限性
如上图所示,为了得到固定大小(7X7)的feature map,我们需要做两次量化操作:1)图像坐标 → feature map,2)feature map → RoI feature。我们来说一下具体的细节,如图我们输入的是一张800x800的图像,在图像中有两个目标(猫和狗),狗的BB大小为665x665,经过VGG16网络后,我们可以获得对应的feature map,如果我们对卷积层进行Padding操作,我们的图片经过卷积层后保持原来的大小,但是由于池化层的存在,我们最终获得feature map 会比原图缩小一定的比例,这和Pooling层的个数和大小有关。在该VGG16中,我们使用了5个池化操作,每个池化操作都是2x2Pooling,因此我们最终获得feature map的大小为800/32 x 800/32 = 25x25(是整数),但是将狗的BB对应到feature map上面,我们得到的结果是665/32 x 665/32 = 20.78 x 20.78,结果是浮点数,含有小数,但是我们的像素值可没有小数,那么作者就对其进行了量化操作(即取整操作),即其结果变为20 x 20,在这里引入了第一次的量化误差;然而我们的feature map中有不同大小的ROI,但是我们后面的网络却要求我们有固定的输入,因此,我们需要将不同大小的ROI转化为固定的ROI feature,在这里使用的是7x7的ROI feature,那么我们需要将20 x 20的ROI映射成7 x 7的ROI feature,其结果是 20 /7 x 20/7 = 2.86 x 2.86,同样是浮点数,含有小数点,我们采取同样的操作对其进行取整吧,在这里引入了第二次量化误差。其实,这里引入的误差会导致图像中的像素和特征中的像素的偏差,即将feature空间的ROI对应到原图上面会出现很大的偏差。原因如下:比如用我们第二次引入的误差来分析,本来是2,86,我们将其量化为2,这期间引入了0.86的误差,看起来是一个很小的误差呀,但是你要记得这是在feature空间,我们的feature空间和图像空间是有比例关系的,在这里是1:32,那么对应到原图上面的差距就是0.86 x 32 = 27.52。这个差距不小吧,这还是仅仅考虑了第二次的量化误差。这会大大影响整个检测算法的性能,因此是一个严重的问题。
- RoIAlign
如上图所示,为了得到为了得到固定大小(7X7)的feature map,RoIAlign技术并没有使用量化操作,即没有引入量化误差。具体流程如下:
1)Conv layers使用的是VGG16,feat_stride=32(即表示,经过网络层后图片缩小为原图的1/32),原图800x800,最后一层特征图feature map大小:25x25
2)假定原图中有一region proposal,大小为665 x 665,这样,映射到特征图中的大小:665/32=20.78,即20.78 x 20.78,此时,没有像RoiPooling那样就行取整操作,保留浮点数
3)假定pooled_w=7,pooled_h=7,即pooling后固定成7 x 7大小的特征图,所以,将在 feature map上映射的20.78 x 20.78的region proposal 划分成49个同等大小的小区域,每个小区域的大小20.78/7=2.97,即2.97 x 2.97
4)假定采样点数为4,即表示,对于每个2.97 x 2.97的小区域,平分四份,每一份取其中心点位置,而中心点位置的像素,采用双线性插值法进行计算,这样,就会得到四个点的像素值,如下图
注,上图中四个红色叉叉‘×’的像素值是通过双线性插值算法计算得到的
5)取四个像素值中最大值作为这个小区域(即:2.97 x 2.97大小的区域)的像素值,如此类推,同样是49个小区域得到49个像素值,组成7 x 7大小的feature map
参考1:RCNN系列
参考2:一文读懂faster rcnn
参考3:Faster rcnn代码详解
参考4:Mask RCNN 论文详解
参考5:目标检测综述
YOLO系列
1.YOLO_v1
参考:YOLO v1算法详解
1.1 优缺点
优点:
- YOLO的速度非常快,bboxes数量少。
- YOLO是基于图像的全局信息进行预测,不像faster rcnn等是基于proposal的,因此可以降低误测方面(指将背景检测为物体)的错误率。
- YOLO用一个网络可以直接预测bboxes和类别
缺点:
- 位置精确性差
- 对小目标物体及密集物体的检测不好
- 误测的错误率降低的同时,伴随的是召回率的降低
1.2 细节阅读
- 首先将输入的图片划分成
S
∗
S
S * S
S∗S 的格子(grid cells)
a. 对每个格子(grid cell)预测B个bounding boxes,每个bbox包含5个值(x, y, w, h, score);其中 bbox 的 score 计算规则如下:若bbox对应的grid cell里没有object,则为0,若有则为gt与grid cell的IOU值;判断grid cell是否有object的规则如下:gt的中心点坐标是否在grid cell里。
b. 每个grid cell 对应C个类别的概率,表示一个cell在包含object条件下属于各类别的概率
注:论文中S = 7, B = 2, C = 20 (VOC数据集)
此时维度为:(7,7, 30),30 = (5 + 5 + 20)
- 计算bboxes对应属于哪一类的score:
对于每一个bbox,将其score与对应的grid cell的类别概率相乘得到。也就是说最后会得到一个矩阵(20,7,7,2) = (20,98)的score矩阵。针对每一个类别,即矩阵每一行,首先将score分数小于0.2的置于0,然后将剩下得分从大到小排序,最后用NMS算法去掉重复率较大的bboxes。(NMS算法:选择得分最大的bbox,计算它和其他bbox的IOU,如果大于0.5,将bbox对应的score置于0.接下来在选择次大的score,使用NMS算法去掉重复率较大的bboxes,重复该过程至结束。 - 最后对于每个bbox,取20个score中最大为该bbox对应的score,如果score小于0,说明bbox为背景,否则score对应的类别为该bbox对应的类别
- 再说一下损失函数
作者采用sum-squared error的方式把localization error(bounding box的坐标误差)和classificaton error整合在一起。但是如果二者的权值一致,容易导致模型不稳定,训练发散。因为很多grid cell是不包含物体的,这样的话很多grid cell的confidence score为0。所以采用设置不同权重方式来解决,一方面提高localization error的权重,另一方面降低没有object的box的confidence loss权值,loss权重分别是5和0.5。而对于包含object的box的confidence loss权值还是原来的1。
在loss function中,前面两行表示localization error(即坐标误差),第一行是box中心坐标(x,y)的预测,第二行为宽和高的预测。这里注意用宽和高的开根号代替原来的宽和高,这样做主要是因为相同的宽和高误差对于小的目标精度影响比大的目标要大。举个例子,原来w=10,h=20,预测出来w=8,h=22,跟原来w=3,h=5,预测出来w1,h=7相比,其实前者的误差要比后者小,但是如果不加开根号,那么损失都是一样:4+4=8,但是加上根号后,变成0.15和0.7。第三、四行表示bounding box的confidence损失,就像前面所说的,分成grid cell包含与不包含object两种情况。这里注意下因为每个grid cell包含两个bounding box,所以只有当ground truth 和该网格中的某个bounding box的IOU值最大的时候,才计算这项。第五行表示预测类别的误差,注意前面的系数只有在grid cell包含object的时候才为1。
1.3 具体实现过程
训练的时候:输入N个图像,每个图像包含M个objec,每个object包含4个坐标(x,y,w,h)和1个label。然后通过网络得到7730大小的三维矩阵。每个1*30的向量前5个元素表示第一个bounding box的4个坐标和1个confidence,第6到10元素表示第二个bounding box的4个坐标和1个confidence。最后20个表示这个grid cell所属类别。注意这30个都是预测的结果。然后就可以计算损失函数的第一、二 、五行。至于第三四行,confidence可以根据ground truth和预测的bounding box计算出的IOU和是否有object的0,1值相乘得到。真实的confidence是0或1值,即有object则为1,没有object则为0。 这样就能计算出loss function的值了。
测试的时候:输入一张图像,跑到网络的末端得到7730的三维矩阵,这里虽然没有计算IOU,但是由训练好的权重已经直接计算出了bounding box的confidence。然后再跟预测的类别概率相乘就得到每个bounding box属于哪一类的概率。
2. YOLO_V3
YOLO_v3参考1
YOLO_v3参考2
YOLO_v3源码
模型结构图:
2.1 总结
- 多尺度训练:该网络输出了3个不同尺度的feature map ,深度均为255,边长规律是13:26:52,如图所示。每一个grid cell 预测3个bboxes,每个bboes都有5个基本参数(x,y,w,h,score)及80个类别的概率,所以深度为255【3 *(5+80)】
(注,YOLO多尺度的feature map 与 SSD得到方式不同,SSD是直接使用网络的部分输出作为feature map,而YOLO是将网络的部分输出与其他输出进行融合) - 与v2相比,v3全程没有pool层,在v2中改变feature大小是用的pool,而在v3中均使用的卷积核
- 加入了9个 b-box priors,与faster rcnn的anchor机制不同的是,预测的时候只使用score最高的,以此节省计算量
- 损失函数方面:几个关键信息 ( x , y ) , ( w , h ) , c l a s s , c o n f i d e n c e (x,y),(w,h),class,confidence (x,y),(w,h),class,confidence,其中(w, h)用均方误差,其他用交叉熵,然后所有损失加权,分类将softmax改成logistic。
- 此代的特征提取网络使用的Darknet53(精度较准,速度较慢),官方提供换用tiny-darknet网络(速度相对较快)。
SSD系列
1.SSD_v1
1.1 总结
- 采用多尺度feature map
- 借助faster rcnn的anchor机制
- 借鉴YOLO,将分类回归放到一起
RetianNet
RetianNet是基于 ResNet、FPN以及利用 Focal loss 构建的 。
- Focal loss
目的:对容易分类的样本加上低权重,对于难分类样本加上大权重。样本难易的定义就是p_t大的样本是易分类的样本,p_t小的样本是难分类样本
个人理解:rcnn系列与yolo、ssd关键区别在于,提供了准确的roi,可以更准(原因:faster rcnn在第一步RPN部分,选择出比anchor更准确的proposal(因为anchor是定的,而proposal是预测的,更灵活大小左右都可改变),在第二步根据proposal在feature map上的对应,可以得到更好的feature map区域(而不是固定卷积后的网格点),再进一步去做分类和回归,效果肯定好)