当前位置: 首页 > news >正文

昇腾 - AscendCL C++应用开发 目标检测中的非极大值抑制NMS和计算候选边界框之间的交并比IOU

昇腾 - AscendCL C++应用开发 目标检测中的非极大值抑制(NMS,Non-Maximum Suppression)涉及计算候选边界框之间的交并比(IOU,Intersection over Union)

flyfish

结构体 BBox: 定义了一个边界框的数据结构,包含中心坐标、宽高、置信度分数、类别索引和输出索引。
函数 IOU: 计算两个边界框之间的交并比。
函数 NMS: 实现非极大值抑制算法,通过逐步移除与当前最佳边界框的IOU超过给定阈值的边界框来筛选出最佳边界框集合。

#include <vector>
#include <algorithm>
#include <cmath>
#include <iostream>
struct BBox {float x;         // 边界框中心的x坐标float y;         // 边界框中心的y坐标float w;         // 边界框的宽度float h;         // 边界框的高度float score;     // 置信度分数int classIndex;  // 类别索引int index;       // 输出缓冲区的索引
};// 计算两个边界框的交并比(IOU)
float IOU(const BBox& box1, const BBox& box2) {// 计算每个边界框的左上角和右下角坐标float x1_min = box1.x - box1.w / 2.0f;float y1_min = box1.y - box1.h / 2.0f;float x1_max = box1.x + box1.w / 2.0f;float y1_max = box1.y + box1.h / 2.0f;float x2_min = box2.x - box2.w / 2.0f;float y2_min = box2.y - box2.h / 2.0f;float x2_max = box2.x + box2.w / 2.0f;float y2_max = box2.y + box2.h / 2.0f;// 计算相交区域的左上角和右下角坐标float inter_x_min = std::max(x1_min, x2_min);float inter_y_min = std::max(y1_min, y2_min);float inter_x_max = std::min(x1_max, x2_max);float inter_y_max = std::min(y1_max, y2_max);// 计算相交区域的宽度和高度float inter_w = std::max(0.0f, inter_x_max - inter_x_min);float inter_h = std::max(0.0f, inter_y_max - inter_y_min);// 计算相交面积float inter_area = inter_w * inter_h;// 计算每个边界框的面积float box1_area = box1.w * box1.h;float box2_area = box2.w * box2.h;// 计算交并比(IOU)float iou = inter_area / (box1_area + box2_area - inter_area);return iou;
}// 实现NMS算法
std::vector<BBox> NMS(const std::vector<BBox>& boxes, float iouThreshold) {// 按置信度分数从高到低排序std::vector<BBox> sortedBoxes = boxes;std::sort(sortedBoxes.begin(), sortedBoxes.end(), [](const BBox& a, const BBox& b) {return a.score > b.score;});std::vector<BBox> result;// 遍历每一个候选框while (!sortedBoxes.empty()) {// 选择置信度最高的框BBox bestBox = sortedBoxes.front();result.push_back(bestBox);// 移除与最佳框IOU大于阈值的所有框sortedBoxes.erase(std::remove_if(sortedBoxes.begin(), sortedBoxes.end(),[&](const BBox& box) {return IOU(bestBox, box) > iouThreshold;}),sortedBoxes.end());}return result;
}int main() {// 示例边界框std::vector<BBox> boxes = {{100.0, 100.0, 50.0, 50.0, 0.9, 0, 0},{102.0, 102.0, 50.0, 50.0, 0.85, 0, 1},{200.0, 200.0, 50.0, 50.0, 0.75, 1, 2},{220.0, 220.0, 50.0, 50.0, 0.7, 1, 3}};// 进行NMSfloat iouThreshold = 0.5;std::vector<BBox> filteredBoxes = NMS(boxes, iouThreshold);// 输出结果for (const auto& box : filteredBoxes) {std::cout << "Box: (" << box.x << ", " << box.y << "), w=" << box.w<< ", h=" << box.h << ", score=" << box.score<< ", classIndex=" << box.classIndex << std::endl;}return 0;
}

输出

Box: (100, 100), w=50, h=50, score=0.9, classIndex=0
Box: (200, 200), w=50, h=50, score=0.75, classIndex=1
Box: (220, 220), w=50, h=50, score=0.7, classIndex=1

移除与最佳框IOU大于阈值的所有框

  1. std::remove_if :首先调用 std::remove_if 将所有不符合条件的元素移到容器的前面,并将符合条件的元素移到后面。此时容器的大小并没有变化,且不符合条件的元素仍然存在于容器的内存中。
auto newEnd = std::remove_if(container.begin(), container.end(), condition);
  1. erase :接着,调用 erase 使用 std::remove_if 返回的迭代器范围来删除从“逻辑末尾”到实际末尾的元素。最终,这个操作会减少容器的大小,并真正删除那些符合条件的元素。
container.erase(newEnd, container.end());

这种组合方式可以避免多次调用 erase 来删除每个满足条件的元素,因为删除单个元素的代价较高,而 std::remove_if 只会遍历一次容器,并通过 erase 进行一次性删除。

例子

#include <vector>
#include <algorithm>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 移除所有偶数auto newEnd = std::remove_if(vec.begin(), vec.end(), [](int x) {return x % 2 == 0;  // 条件:为偶数时移除});// 真正从容器中删除它们vec.erase(newEnd, vec.end());// 输出结果for (int x : vec) {std::cout << x << " ";}return 0;
}

http://www.mrgr.cn/news/2572.html

相关文章:

  • 基于方面的情感分析研究综述——论文阅读笔记
  • 氟化工特氟龙精馏装置:PFA氟化氢反应装置的应用
  • 【docker】关于挂载
  • JNI编程四:java跟JNI字符串传递
  • 【C++】string讲解
  • 【GH】【EXCEL】P4: Chart
  • Flink 1.14.*版本kafkaSource源码
  • 文心快码 Baidu Comate 前端工程师观点分享:以文心快码 Baidu Comate为例,智能代码助手需要什么(一)
  • Nginx负载均衡调度状态
  • 多线程编程中的常见问题及解决方案
  • ES6笔记总结(Xmind格式):第一天
  • OpenCV几何图像变换(3)计算透视变换矩阵函数getPerspectiveTransform()的使用
  • 西安旅游系统--论文pf
  • ElasticSearch 相关面试题
  • linux:进程空间的回收,exec族
  • 【大模拟】逻辑回环类
  • VirtualBox上的Oracle Linux虚拟机安装Docker全流程
  • Prompt——与AI连接的桥梁
  • 【SpringBoot】10 日志持久化(log4j2)
  • WordPress Transposh WordPress Translation SQL注入漏洞