C++实现nms和softmax

news2024/10/7 18:28:02

最近在面试过程中遇到了手写nms的问题,结束后重新实现并调通了nms和softmax的代码。
1、NMS
原理(通俗易懂):
先假设有6个候选框,根据分类器类别分类概率做排序,从小到大分别属于车辆的概率分别为A、B、C、D、E、F。
从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;
假设B、D与F的重叠度超过阈值,那么就扔掉B、D(因为超过阈值,说明D与F或者B与F,有很大部分是重叠的,保留概率最大的F即可);并标记第一个矩形框F,是我们保留下来的。
从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,删除重叠度大于一定阈值的框;并标记E是我们保留下来的第二个矩形框。
一直重复这个过程,找到所有曾经被保留下来的矩形框。

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

// // 左上坐标和框的宽高(x,y,w,h)
struct Box
{
	int x;
	int y;
	int w;
	int h;
	float score;
};

bool sort_score(Box box1, Box box2)
{
	return box1.score > box2.score ? true : false;
}


float iou(Box box1, Box box2)
{
	int x1 = max(box1.x, box2.x);
	int y1 = max(box1.y, box2.y);
	int x2 = min(box1.x + box1.w, box2.x + box2.w);
	int y2 = min(box1.y + box1.h, box2.y + box2.h);

	// 判断两框是否相交,若不相交,返回0
	if (x1 >= x2 || y1 >= y2)
	{
		return 0;
	}

	float over_area = (x2 - x1)*(y2 - y1);
	float both_area = box1.w*box1.h + box2.w*box2.h - over_area;
	float iou = over_area / both_area;

	int x3 = min(box1.x, box2.x);
	int y3 = min(box1.y, box2.y);
	int x4 = max(box1.x + box1.w, box2.x + box2.w);
	int y4 = max(box1.y + box1.h, box2.y + box2.h);

	float all_area = (x4 - x3)*(y4 - y3);

	float area1 = (all_area - both_area) / all_area;

	float giou = iou - area1;
	// 正常nms返回的是iou的值,此处实现giou,也可添加diou\ciou
	return giou;

}


vector<Box>nms(vector<Box>&vec_boxs, float threshold)
{
	vector<Box>results;
	//按分值从大到小排序
	std::sort(vec_boxs.begin(), vec_boxs.end(), sort_score);
	while (vec_boxs.size() > 0)
	{
		results.push_back(vec_boxs[0]);
		int index = 1;
		while (index < vec_boxs.size())
		{
			float iou_value = iou(vec_boxs[0], vec_boxs[index]);
			cout << "iou:" << iou_value << endl;
			// iou大于阈值,使用erase剔除
			if (iou_value > threshold)
			{
				vec_boxs.erase(vec_boxs.begin() + index);
			}
			else
				index++;
		}
		vec_boxs.erase(vec_boxs.begin());
	}

	return results;
}


int main()
{
	vector<Box>input;
	Box box1 = { 0, 0, 100, 101, 0.9 };
	Box box2 = { 5, 6, 90, 110, 0.7 };
	input.push_back(box1);
	input.push_back(box2);
	vector<Box>res;
	res = nms(input, 0.65);

	for (int i = 0; i < res.size(); i++)
	{
		printf("%d %d %d %d %f", res[i].x,res[i].y, res[i].w, res[i].h, res[i].score);
		cout << endl;
	}
	return 0;

}

结果为:
在这里插入图片描述
2、softmax
softmax是逻辑回归在多分类问题上的推广,大概的公式如下:
在这里插入图片描述
即判断该变量在总体变量中的占比。

2.1 简单实现
用vector来封装输入和输出,简单的按公式复现。

#include<iostream>
#include<vector>
#include<math.h>

using namespace std;

vector<double>softmax(vector<double>input)
{
	double total = 0;
	for (auto x : input)
	{
		total += exp(x);
	}
	vector<double>result;
	for (auto x : input)
	{
		result.push_back(exp(x) / total);
	}
	return result;
}

int main(int argc, char *argv[])
{
	int n; 
	cin >> n;
	vector<double>input;
	while (n--)
	{
		double x;
		cin >> x;
		input.push_back(x);
	}
	for (auto y : softmax(input))
	{
		cout << y << ' ';
	}
}

输入n:数字个数
回车键后依次输入四个数值。
在这里插入图片描述
经过测试正常。

2.2 改进
若输入数值中有一个数值特别大,如(1 3 4 1000),此时由于e^{1000}已经溢出了双精度浮点(double)所能表示的范围,所以变成了NaN。
改进原理:
注意观察softmax的公式:
在这里插入图片描述
如果我们给上下同时乘以一个很小的数,最后答案的值是不变的。
那我们可以给每一个输入都减去一个值a,防止数值超出精度范围。
大致表示如下:
在这里插入图片描述
a值得取值也比较简单,取输入数值中的最大值即可。

#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>

using namespace std;

vector<double>softmax(vector<double>input)
{
	double total = 0;
	double MAX = input[0];
	for (auto x : input)
	{
		MAX = max(x, MAX);
	}
	for (auto x : input)
	{
		total += exp(x - MAX);
	}
	vector<double>result;
	for (auto x : input)
	{
		result.push_back(exp(x - MAX) / total);
	}
	return result;
}


int main(int argc, char *argv[])
{
	int n;
	cin >> n;
	vector<double> input;
	while (n--)
	{
		double x;
		cin >> x;
		input.push_back(x);
	}
	for (auto y : softmax(input))
	{
		cout << y << ' ';
	}
}

输出为:
在这里插入图片描述
第三行为输出结果,数值正常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1039651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机视觉】2.图像特征提取

图像特征提取 一、颜色特征量化颜色直方图聚类颜色直方图 二、边缘特征边缘边缘定义边缘提取边缘精细 三、特征点的特征描述子Harris角点FAST角点斑点SIFTHaar-like特征SURFORBLBPGabor 一、颜色特征 量化颜色直方图 HSV空间 优势&#xff1a;计算高效 劣势&#xff1a;量化问…

LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

复制系统目录下面的&#xff1a;cvtres.exe到vs2010安装目录下面即可。

图神经网络详细内容

文章目录 1. 图神经网络1.1 GCN图卷积网络1.1.1 计算过程1.1.2 公式的物理原理1.1.3 GCN代码实现 1.2 GAT图注意力网络1.2.1 计算过程与原理1.2.2 GAT代码实现 1.3 消息传递1.4 图采样介绍1.5 图采样算法&#xff1a;GraphSAGE1.6 图采样算法&#xff1a;PinSAGE 2. 参考 1. 图…

数据结构 | 树

树 树是n&#xff08;n>0&#xff09;个结点的有限集。当n 0时&#xff0c;称为空树。在任意一棵非空树中应满足&#xff1a; 有且仅有一个特定的称为根的结点。当n>1时&#xff0c;其余节点可分为m&#xff08;m>0&#xff09;个互不相交的有限集T1,T2,…,Tm&#…

基于SpringBoot的可以做毕设或者课设的实时聊天系统(仿微信)

技术栈 前后端分离前端使用: Vue Element后端使用: SpringBoot Mysql8.0 Mybatis WebSocket 功能 登录和注册页 登录 和 注册 修改个人信息页 修改个人信息 消息列表页 展示最近半年的聊天信息&#xff0c;删除聊天记录 搜索好友和群页 搜索JJ号来找到 群/好友 好友信息详情页…

一文搞懂 this 指向

目录 一、前言二、箭头函数三、new指向四、bind五、call和apply六、bind call apply区别七、对象&#xff08;obj.&#xff09;八、全局this指向九、不在函数里 一、前言 JS 中 this 指向问题 - 掘金 在JavaScript中&#xff0c;this关键字表示当前执行代码的上下文对象。它的…

Linux 系统死机后挽救措施

一、背景 因我们日常使用Linux系统过程中&#xff0c;会不时遇到系统崩溃的事&#xff0c;但这时系统界面除了呈现一片告警字符外&#xff0c;无发执行任何其他操作&#xff0c;留给我们的要不重启&#xff0c;要不就是尴尬等待指令。那面对会这种情况&#xff0c;还到底有没有…

人工智能热潮推动光芯片与光器件需求飙升

随着人工智能技术的迅猛发展&#xff0c;光芯片和光器件作为关键的基础技术&#xff0c;在这一浪潮下迎来了前所未有的需求增长。光芯片和光器件的高速率、高带宽、低能耗等优势&#xff0c;使其在人工智能应用中发挥着重要作用&#xff0c;正日益成为推动人工智能进步的关键要…

上海长宁来福士P2.5直径4米无边圆形屏圆饼屏圆面屏圆盘屏平面圆屏异形创意LED显示屏案例

长宁来福士广场是一个大型广场&#xff0c;坐落于上海中山公园商圈的核心区域&#xff0c;占地逾6万平方米&#xff0c;其中地上总建筑面积近24万平方米&#xff0c;总投资额约为96亿人民币。 LED圆形屏是根据现场和客户要求定制的一款异形创意LED显示屏&#xff0c;进行文字、…

513找树左下角值

给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出: 7class Solution { public:int findBottomLeftValue(TreeNode…

RDLC动态设置整个表格是否显示

最近有个新的需求&#xff1a;使用RDLC打印&#xff0c;当数据库中能查出数据时&#xff0c;显示表格。没有数据时&#xff0c;不显示整个表格。 1.首先在RDLC中选中表格的任意一列&#xff0c;右键Tablix属性 2.Tablix属性中选中可见性》选中基于表达式显示或隐藏(E)并点开右…

Word | 简单可操作的快捷公式编号、右对齐和引用方法

1. 问题描述 在理工科论文的写作中&#xff0c;涉及到大量的公式输入&#xff0c;我们希望能够按照章节为公式进行编号&#xff0c;并且实现公式居中&#xff0c;编号右对齐的效果。网上有各种各样的方法来实现&#xff0c;操作繁琐和简单的混在一起&#xff0c;让没有接触过公…

深度强化学习(三)马尔科夫决策过程

文章目录 马尔可夫过程MP马尔科夫链MC状态转移概率矩阵n步转移概率 马尔科夫链 马尔科夫奖励过程MRP奖励机制计算价值概念定义计算价值推导贝尔曼方程贝尔曼方程实际应用 参考文章&#xff1a;https://blog.csdn.net/taka_is_beauty/article/details/88356375 序贯决策问题是针…

【Vue3 源码解析】nextTick

nextTick 是 Vue 3 中用于异步执行回调函数的函数&#xff0c;它会将回调函数延迟到下一个微任务队列中执行。其中&#xff0c;Vue 更新 DOM 是异步的。下面是对 nextTick 函数的详细解释&#xff1a; export function nextTick<T void, R void>(this: T,fn?: (this:…

2023-09-25 LeetCode每日一题(LFU 缓存)

2023-09-25每日一题 一、题目编号 460. LFU 缓存二、题目链接 点击跳转到题目位置 三、题目描述 请你为 最不经常使用&#xff08;LFU&#xff09;缓存算法设计并实现数据结构。 实现 LFUCache 类&#xff1a; LFUCache(int capacity) - 用数据结构的容量 capacity 初始…

全流量安全分析之服务器非法外连

服务器非法外连监控的重要性在于保护服务器的安全性和防止被黑客利用&#xff0c;以下是几个重要的理由&#xff1a; 1、发现恶意活动&#xff1a;通过监控服务器的外连流量&#xff0c;可以及时发现是否有未经授权或可疑的连接尝试。这可能包括入侵攻击、数据泄露、恶意软件传…

基于微信小程序的家校通系统设计与实现(亮点:选题新颖、上传作业、批改作业、成绩统计)

文章目录 前言运行环境说明家长微信小程序端的主要功能有&#xff1a;教师微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文…

MySQL 索引底层 B+Tree 原理解析

目录 一、前言二、B-Tree 和 BTree 的区别三、InnoDB 和 MyISAM 存储引擎索引存储区别MyISAMInnoDB 四、InnoDB 联合索引底层数据结构五、MySQL 中三次磁盘IO最大能检索多少数据 一、前言 索引是帮助高效获取数据排好序的数据结构&#xff0c;任何数据库都会使用到索引&#x…

漂流伞顾曼宁(顾曼)的创业之路:相信的力量

顾曼宁&#xff08;顾曼&#xff09;的心情在蚂蚁生态全球CEO大会上充满了感动和鼓舞。这是一个期待已久的盛会&#xff0c;时隔三年&#xff0c;蚂蚁生态全球的首席执行官们再次汇聚一堂。智慧与商业的碰撞下&#xff0c;更藏着感情与坚持的交汇。 蚂蚁集团举办了【相信展】的…

求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux

求生之路2服务器搭建插件安装及详细的游戏参数配置教程linux 大家好我是艾西&#xff0c;在上一篇文章中我用windows系统给搭建演示了一遍怎么搭建自己的L4D2游戏。 那么也有不少小伙伴想知道linux系统的搭建方式以及在这个过程中有什么区别。 那么艾西今天就跟大家分享下用lin…