代码
import numpy as np
def nms(bboxes, iou_threshold):
x1 = bboxes[:, 0]
y1 = bboxes[:, 1]
x2 = bboxes[:, 2]
y2 = bboxes[:, 3]
score = bboxes[:, 4]
area = (x2 - x1 + 1) * (y2 - y1 + 1)
index = area.argsort()[::-1]
res = []
while index.size > 0:
i = index[0]
res.append(i)
xx1 = np.maximum(x1[i], x1[index[1:] ])
yy1 = np.maximum(y1[i], y1[index[1:] ])
xx2 = np.minimum(x2[i], x2[index[1:] ])
yy2 = np.minimum(y2[i], y2[index[1:] ])
width = np.maximum(0, (xx2 - xx1 + 1))
height = np.maximum(0, (yy2 - yy1 + 1))
o_area = width * height
print("o_area ", o_area)
iou = o_area / (area[i] + area[index[1:]] - o_area)
print("iou ", iou)
ne_inde = np.where(iou <= iou_threshold)[0]
index = index[ne_inde +1]
return res
off = 10
print(off)
#
bboxes = np.array([[10, 10, 10 + off, 10 + off, 0.91], [12, 12, 12 + off, 12 + off, 0.9] , [14, 14, 14+off, 14+ off, 0.7], [15, 15, 15+off, 15+ off, 0.8]])
res = nms(bboxes, 0.3)
print(res)
/*
============================================================================
Name : NMS.c
Author : yiqun
Version :
Copyright : Your copyright notice
Description : NMS in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <iostream>
#define MAX(a,b)(a>b?a:b)
#define MIN(a,b)(a<=b?a:b)
#define BOX_SIZE 4
#define THRESH 0.3f
//候选框
typedef struct {
float lx, ly, rx, ry; //左上角x 左上角y 右下角x 右下角y
float cfd; //置信度 Confidence
int supression; //是否被抑制
} box;
//float overlap(float a_l, float a_r, float b_l, float b_r);
//
传入两个候选框变量某一维度坐标值,返回重叠部分的宽和高
//float overlap(float a_l, float a_r, float b_l, float b_r) { //返回值是否可以优化??//传入指针是否更快??
// //printf("a左边: %f,a右边: %f,b左边: %f,b右边: %f", a_l, a_r, b_r, b_r);
// float sum_sides = a_r - a_l + b_r - b_l; //同一方向两个边长之和 //是否要绝对值
// float new_sides = MAX(a_r, b_r) - MIN(a_l, b_l); //同一方向长度并集 //用max还是绝对值??优化。
// return sum_sides - new_sides;
//}
传入两个候选框变量a、b,返回相交面积值
//float box_intersection(box *a, box *b) //传入指针是否更快??
//{
// float w = overlap(a->lx, a->rx, b->lx, b->rx);
// float h = overlap(a->ly, a->ry, b->ly, b->ry);
// //printf("w: %f, h: %f", w, h);
// if (w <= 0 || h <= 0) return 0;
// float area = w * h; //直接返回 不创建变量??
// return w * h;
//}
传入两个候选框变量a、b,返回并集面积值
//float box_union(box *a, box *b) { //传入指针是否更快??
// float insersection = box_intersection(a, b); //减少函数调用还是开辟变量空间进行优化??
// float areaA = (a->rx - a->lx) * (a->ly - a->ry); //是否使用绝对值??
// float areaB = (b->rx - b->lx) * (b->ly - b->ry);
// float area = areaA + areaB - insersection; //直接返回 不创建变量??
// return area;
//}
float box_area(box *a){
float w = MAX((a->rx - a->lx + 1), 0);
float h = MAX((a->ry - a->ly + 1), 0);
return w * h;
}
float box_com(box *a, box *b){
float x1 = MAX(a->lx, b->lx);
float y1 = MAX(a->ly, b->ly);
float x2 = MIN(a->rx, b->rx);
float y2 = MIN(a->ry, b->ry);
float w = MAX(0, (x2 - x1 + 1));
float h = MAX(0, (y2 - y1 + 1));
float o_area = w * h;
return o_area;
}
float box_iou2(box *a, box *b){
float o_area = box_com(a, b);
float a_a = box_area(a);
float b_a = box_area(b);
float iou = o_area / (a_a + b_a - o_area);
return iou;
}
//传入两个候选框变量a、b,返回交并比值
//float box_iou(box *a, box *b) //传入指针是否更快??
//{
// std::cout << box_intersection(a, b) << std::endl;
iou = o_area / (area[i] + area[index[1:]] - o_area)
// return box_intersection(a, b)/box_union(a, b); //dsp可进行除法优化!!
//}
//归并排序
void merge(box* B, box* temp, int l, int mid, int r) {
int i = l, j = mid + 1, m = 1, k = 1;
while (i <= mid && j <= r) {
if ((B + i)->cfd < (B + j)->cfd)
*(temp + m++) = *(B + j++);
else
*(temp + m++) = *(B + i++);
}
while (i <= mid)
*(temp + m++) = *(B + i++);
while (j <= r)
*(temp + m++) = *(B + j++);
for (k = 1; k <= r - l + 1; k++)
*(B + l + k - 1) = *(temp + k);
}
//按照置信度从大到小排序
void sort_nms(box* B, box* temp, int l, int r) { //(数组查找和链表删除哪个费时)C++ ERASE()源码改写
if (l < r) {
int mid = (l + r) / 2;
sort_nms(B, temp, l, mid);
sort_nms(B, temp, mid + 1, r);
merge(B, temp, l, mid, r);
}
}
//NMS算法,传入出入候选框集合、输入候选框对应置信度集合、阈值,返回输出候选框个数
int do_nms(box* B, box*D, float Nt) {
int i;
for (i = 0; i < BOX_SIZE; i++)
printf("d: %.2f\n", (B + i)->cfd);
box* temp = (box*)malloc(sizeof(box) * (BOX_SIZE+1));
sort_nms(B, temp, 0, (BOX_SIZE - 1));
free(temp);
for (i = 0; i < BOX_SIZE; i++)
printf("d: %.2f\n", (B + i)->cfd);
int max_index = 0, current_index = 0;
int j;
float iou;
while (current_index< BOX_SIZE) { //探究一轮循环的方法,与所以输出框比较,递归??
printf("current_index: %d\n", current_index);
if (!((B+current_index)->supression)) {
*(D + max_index) = *(B + current_index);
(B + current_index)->supression = 1;
for (j = current_index+1; j < BOX_SIZE; j++) {
iou = box_iou2(D + max_index, B + j);
printf("iou: %f\n", iou);
if (iou >= Nt)
(B + j)->supression = 1;
}
max_index++;
}
current_index++;
}
return max_index;
}
//数据集分配处理
void data_clean(box* b) {
b[0].lx = 10.0;
b[0].ly = 10.0;
b[0].rx = 20.0;
b[0].ry = 20.0;
b[0].cfd = 0.91f;
b[0].supression = 0;
b[1].lx = 12.0;
b[1].ly = 12.0;
b[1].rx = 22.0;
b[1].ry = 22.0;
b[1].cfd = 0.90f;
b[1].supression = 0;
b[2].lx = 14.0;
b[2].ly = 14.0;
b[2].rx = 24.0;
b[2].ry = 24.0;
b[2].cfd = 0.70f;
b[2].supression = 0;
b[3].lx = 15.0;
b[3].ly = 15.0;
b[3].rx = 25.0;
b[3].ry = 25.0;
b[3].cfd = 0.80f;
b[3].supression = 0;
}
int main(void) {
box* b = (box*)malloc(sizeof(box) * BOX_SIZE);
// float* s = (float*)malloc(sizeof(float) * BOX_SIZE);
box* d = (box*)malloc(sizeof(box) * BOX_SIZE);
data_clean(b);
//计时器
long i = 10000000L;
clock_t start, finish;
double duration;
int count = 0;
start = clock();
/*******************/
//while (i--) {
count = do_nms(b, d, THRESH);
printf("count: %d\n", count);
//iou = box_iou(b+0,b+1);
//}
/*******************/
finish = clock();
duration = (finish - start) / CLOCKS_PER_SEC;
printf("%f seconds\n", duration);
//printf("IoU: %f\n", iou);
//printf("s1: %f, s2: %f",*(s+0), *(s+1));
if (d) {
for (i = 0; i < count; i++)
printf("d: %.2f\n", (d + i)->cfd);
}
free(b);
free(d);
system("pause");
return EXIT_SUCCESS;
}