我是靠谱客的博主 机智柚子,最近开发中收集的这篇文章主要介绍目标检测阅读总结(一)之RCNN以及NMS,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

开始看目标检测方面论文,里面有很多经典,会在这儿记录下论文中的优点和代码中的问题,也会把别人blog比较好的观点总结。

阅读顺序差不多按照: https://github.com/amusi/awesome-object-detection

R-CNN

参考:https://blog.csdn.net/shenxiaolu1984/article/details/51066975

https://blog.csdn.net/briblue/article/details/82012575

 

pipeline:

1. 使用selective search生成1k-2k个候选框;

2. 对于候选区域,提取cnn特征(4096-dim),这里是裁剪出来然后做一个16的padding,然后resize到227*227。(为了让bounding box拥有上下文内容context。)

3. 对于正负样本的分类,对于4096-dim feature接一个svm进行分类。

4. 为了减少识别的错误,在用一个线性回归模型对框进行微调。

4.1. 一个scale变换,对于中心点以及长宽;

4.2 这里的L2正则化很关键;

4.3 组的pair对很重要,不然会导致a hopeless learning problem。这里使用的iou阈值为0.6。

 

3.1. 由于负样本很多,所以会对于负样本使用hard negative mining。

hard negative mining 

R-CNN引用了这篇文章 “Object Detection with Discriminatively Trained Part Based Models.”

由于训练的阶段负样本过多,超过1w个,对于模型来说使用全部的负样本是不可行的,所以需要构建一个既有负样本又有hard negative的样本集合。

Bootstrapping methods:先用负样本组成集合训练,然后收集那些被错误分类的例子,去训练新的模型,这样重复几次。

proposed data-mining methods:为了找到一个属于训练集的小子集,初始的时候用原始的作为一个cache,每一次迭代会移除一些比较简单的样本,增加一些新的比较难的样本。

具体流程如下

1. 先初始一个$c_{t}$ subseteq $d$, 这里的 D是原来的训练集。

2. 训练,直到参数稳定分出两个集合,一个是错误分类的,一个是正确分类的。

3. 缩小c_{t}, 去除那些被正确分类的,得到集合c_{t^{'}}

4. 增大c_{t+1},把 c_{t^{'}}和一些属于 d的样本形成并集,得到新一轮的子集c_{t+1}

Non-Maximum-Suppression

非极大值抑制,在目标检测,回归了很多bounding boxes出来之后,要最终确定哪一个是最终使用的时候,需要用nms进行bounding boxes的剔除。

具体过程:对于图片每一个类别,先找到置信度(网络predict的概率)最大的值,先对于这一类别的其他框做iou的操作,然后有一个nms的iou超参,高于设定iou的就被剔除。

如此对于每一个类别进行重复操作,这样排除了很多置信度低的框。

下面贴一下自己写的nms代码,并简单分析一下。

#include <iostream>
#include <string>
#include <set>
#include <cmath>
#include <vector>
#include <tuple>
using namespace std;
float iou_cal(vector<float> box1, vector<float> box2){
float right_x = min(box1[2],box2[2]);
float right_y = min(box1[3],box2[3]);
float left_x = max(box1[2],box2[2]);
float left_y = max(box1[3],box2[3]);
float overlap = fmax(0.,left_x-right_x) * fmax(0.,left_y-right_y);
float area_sum = (box1[2]-box1[0])*(box1[3]-box1[1])+(box2[2]-box2[0])*(box2[3]-box2[1]);
return overlap/(area_sum-overlap);
}
tuple<vector<float>,int> find_base(vector<vector<float> > boxes){
vector<float> boxes_max{-1,-1,-1,-1};
float max_pb = 0.;
int index;
for(int i = 0; i<boxes.size();i++){
if(boxes[i][0]>max_pb){
max_pb = boxes[i][0];
boxes_max[0] = boxes[i][1];
boxes_max[1] = boxes[i][2];
boxes_max[2] = boxes[i][3];
boxes_max[3] = boxes[i][4];
index = i;
}
}
return make_tuple(boxes_max,index);
}
void nms(vector<vector<float> > &boxes,float iou_value){ // single class
tuple<vector<float>,int> box_value;
vector<float> boxes_base;
float iou = 0.0;
int index;
box_value = find_base(boxes);
boxes_base = get<0>(box_value);
index = get<1>(box_value);
for(int i=0;i<boxes.size();i++){
if(i!=index){
iou = iou_cal(boxes_base,boxes[i]);
if(iou>iou_value){
boxes.erase(boxes.begin()+i);
}
}
}
}
void print_boxes(vector<vector<float> > boxes){
for(int i=0;i<boxes.size();i++){
for(int j=0;j<boxes[0].size();j++){
cout << boxes[i][j] << " " ;
}
cout << endl;
}
}
int main(int argc, const char * argv[]) {
vector<float> box1{0.6,100,98,300,400};
vector<float> box2{0.7,85,60,250,500};
vector<float> box3{0.8,70,49,200,350};
vector<vector<float> > boxes;
boxes.push_back(box1);
boxes.push_back(box2);
boxes.push_back(box3);
print_boxes(boxes);
nms(boxes,0.5);
print_boxes(boxes);
return 0;
}

上面代码考虑单一类别的情况,多类别加一个for循环即可,首先是要找到置信度最大的候选框,通过find_base函数。之后进行for循环,对于其他候选框进行判断,计算iou占比,如果小于设定的阈值(这里设定的为0.5)那么就剔除这个框。

tip:c++语法要注意nms的输入应为引用。

最后

以上就是机智柚子为你收集整理的目标检测阅读总结(一)之RCNN以及NMS的全部内容,希望文章能够帮你解决目标检测阅读总结(一)之RCNN以及NMS所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部