非极大值抑制NMS算法c++版本
简介
非极大值抑制NMS算法 缩写NMS,全称 non maximum suppression 。常用于计算机视觉中的边缘检测、物体识别等。
给出一张图片和上面许多物体检测的候选框(即每个框可能都代表某种物体),但是这些框很可能有互相重叠的部分,我们要做的就是只保留最优的框。
NMS的作用:去掉detection任务重复的检测框。
算法流程
假设有N个框,每个框被分类器计算得到的分数为Si, 1<=i<=N。
0、建造一个存放待处理候选框的集合H,初始化为包含全部N个框;
建造一个存放最优框的集合M,初始化为空集。
1、将所有集合 H 中的框进行排序,选出分数最高的框 m,从集合 H 移到集合 M;
2、遍历集合 H 中的框,分别与框 m 计算交并比(Interection-over-union,IoU),如果高于某个阈值(一般为0~0.5),则认为此框与 m 重叠,将此框从集合 H 中去除。
3、回到第1步进行迭代,直到集合 H 为空。集合 M 中的框为我们所需。
需要优化的参数:
IoU 的阈值是一个可优化的参数,一般范围为0~0.5,可以使用交叉验证来选择最优的参数。
非极大值抑制NMS算法c++版本
typedef struct FaceInfo {
float score;//置信度
int x[2];
int y[2];//框左上和右下的坐标点
float area;//框的面积
float regreCoord[4];//4个坐标的修正信息,返回的是框的比例
int landmark[10];//人脸的5个特征点
} FaceInfo;
bool cmpScore(FaceInfo x, FaceInfo y)
{
if (x.score > y.score)
return true;
else
return false;
}
float calcIOU(FaceInfo box1, FaceInfo box2, string mode)
{
int maxX = max(box1.x[0], box2.x[0]);
int maxY = max(box1.y[0], box2.y[0]);
int minX = min(box1.x[1], box2.x[1]);
int minY = min(box1.y[1], box2.y[1]);//得到重叠部分的左上和右下的两个坐标点
int width = ((minX - maxX + 1) > 0) ? (minX - maxX + 1) : 0;
int height = ((minY - maxY + 1) > 0) ? (minY - maxY + 1) : 0;//+1防止为0,
int inter = width * height;//重叠部分面积
if (!mode.compare("union"))
return float(inter) / (box1.area + box2.area - float(inter));
else if (!mode.compare("min"))
return float(inter) / (box1.area < box2.area ? box1.area : box2.area);
else
return 0;
}
void doNms(vector<FaceInfo> &bboxs, float nms_thresh, string mode)
{
if (bboxs.empty())
return;
sort(bboxs.begin(), bboxs.end(), cmpScore);//将候选框按照置信度排序
for (int i = 0; i < bboxs.size(); i++)//总的
if (bboxs[i].score > 0)
for (int j = i + 1; j < bboxs.size(); j++)
if (bboxs[j].score > 0)//判断当前候选框是否被抑制
{
float iou = calcIOU(bboxs[i], bboxs[j], mode);//计算正交比
if (iou > nms_thresh)//nms_thresh为阈值
bboxs[j].score = 0;//将该候选框设置为抑制
}
for (auto it = bboxs.begin(); it != bboxs.end();)
if ((*it).score == 0)
bboxs.erase(it);//清除被抑制的候选框
else
it++;
}