【纯c语言实现NMS算法并提供C++版实现(循环控制一致,方便阅读)】

前言:c++版本由于有std标准库的存在,所以nms的实现很简单,效率也很高。但是纯c是不提供的。

C版本实现


这里先附上我的结构体信息,以免对没有写过nms的同学们造成迷糊

typedef struct
{
    float x_min;
    float y_min;
    float x_max;
    float y_max;
}BBox;

typedef struct
{
    float confi;
    BBox bbox;
}ObjectResult;

以下是正式代码,会附带一些注释

// > 是降序, < 是升序
int compare(const ObjectResult a, const ObjectResult b)
{
    return a.confi < b.confi ? 1 : -1;
}

float iou(ObjectResult a, ObjectResult b)
{
    float x1 = a.bbox.x_min > b.bbox.x_min ? a.bbox.x_min : b.bbox.x_min;  // std::max
    float y1 = a.bbox.y_min > b.bbox.y_min ? a.bbox.y_min : b.bbox.y_min;  // std::max
    float x2 = a.bbox.x_max > b.bbox.x_max ? b.bbox.x_max : a.bbox.x_max;  // std::min
    float y2 = a.bbox.y_max > b.bbox.y_max ? b.bbox.y_max : a.bbox.y_max;  // std::min

    // 没有重叠面积
    if (x2 < x1 || y2 < y1) return 0;

    float a_width  = a.bbox.x_max - a.bbox.x_min;
    float a_height = a.bbox.y_max - a.bbox.y_min;
    float b_width =  b.bbox.x_max - b.bbox.x_min;
    float b_heihgt = b.bbox.y_max - b.bbox.y_min;

    float inter_area = (x2 - x1) * (y2 - y1);  // 交集
    float iou = inter_area / ((a_width * a_height) + b_width * b_heihgt - inter_area); // 并集

    return iou;
}

/*
    nms实现主体部分
 */
void nms(ObjectResult object[], ObjectResult result[], uint16_t* total, float nmsThreshold)
{
    // 按照分数进行降序排序
    qsort(object, *total, sizeof(ObjectResult), compare);

    for (uint16_t i = 0; i < *total; ++i)
    {
        uint16_t index = 1;
        result[i] = object[i];
        for (uint16_t j = i + 1; j < *total; ++j)
        {
            if (iou(result[i], object[j]) < nmsThreshold)
            {
            	// 将待确定的检测目标挪到已确定的检测目标后面
                object[index] = object[j];
                index += 1;
            }
        }

        *total = index;

		 // 剩余的框中不存在新的检测目标, 都是多余的框, 循环结束, 返回确定的检测框总数
        if (index == 1)
        {
            *total = i + 1;
        }
    }
}

接口调用示例,请结合自己的代码做调整

uint16_t total = 0;  			 // object中检测框的数量
ObjectResult object[100] = {};   // nms前
ObjectResult result[10] = {};    // nms后
float nmsThreshold = 0.25;
nms(object, result, &total, nmsThreshold);
for (uint8_t i = 0; i < total; i++)
{
	   printf("socre = %f, bbox = (%f, %f, %f, %f)\n", result[i].confi, result[i].bbox.x_min,
	   	 	   result[i].bbox.y_min, result[i].bbox.x_max, result[i].bbox.y_max);
}

C++版本实现


下班,后续补充

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值