【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV3模型部署
【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV3模型部署
提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论
文章目录
- 【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV3模型部署
- 前言
- Windows平台搭建依赖环境
- 模型转换--pytorch转onnx
- ONNXRuntime推理代码
- YOLOV3前后处理代码
- 完整推理代码
- 总结
前言
本期将讲解深度学习目标检查网络YOLOV3模型的部署,对于该算法的基础知识,可以参考其他博主博文。
读者可以通过学习【OnnxRuntime部署】系列学习文章目录的C++篇* 的内容,系统的学习OnnxRuntime部署不同任务的onnx模型。
Windows平台搭建依赖环境
在【入门基础篇】中详细的介绍了onnxruntime环境的搭建以及ONNXRuntime推理核心流程代码,不再重复赘述。
模型转换–pytorch转onnx
本博文将通过Ultralytics–YOLOv3算法的人脸检测项目【参考博文:Windows11下YOLOV3人脸目标检测】,简要介绍YOLOV3模型部署。
在博文Windows11下YOLOV3人脸目标检测项目中已经通过以下命令导出了onnx模型:
python export.py --weights runs/train/exp/weights/best.pt --include onnx
【yolov3-face.onnx百度云链接,提取码:zd6a 】直接下载使用即可。
ONNXRuntime推理代码
YOLOV3前后处理代码
1.利用可视化工具查看onnx模型结构: 为了直观地看到整个神经网络的架构,包括各个层(如卷积层、全连接层等)及其连接方式,需要通过可视化工具展示,Netron是一个开源的可视化工具【在线工具】,支持包括ONNX在内的多种深度学习模型格式。它提供了一个交互式的用户界面,可以展示模型的层次结构、参数细节等。
将onnx模型上传到在线Netron可视化工具:
简单说明下四个输出分别代表的含义:
第一个输出:1代表batchsize;25200代表检测框的个数;6代表框的详细信息:即框中心点xy+框宽高hw+框置信度conf+框分类个数(这里是1)。
第二(三/四)个输出:1代表batchsize;3代表着当前网络层输出的特征图每个像素包含的框的个数;,80和80代表特征图的分辨率;6代表框的详细信息。
2.获取模型输出信息: YOLOV3模型是单输入多输出的模型,输入信息的获取方式和之前讲解的图像分类的保持一致,这里重点讲解下多输出信息的获取方式。 YOLOV3模型通常只需要获取第一个输出信息,这里博主分别保存了每个输出的信息,为未来处理其他多输入/输出时模型候提供参考。
// 获取模型输出信息
std::vector<int> nums;
std::vector<int> nbs;
std::vector<int> ncs;
std::vector<int> ncs1;
std::vector<int> ncs2;
for (int i = 0; i < output_nodes_num; i++) {// 获得输出节点的名称并存储auto output_name = session_.GetOutputNameAllocated(i, allocator);output_node_names.push_back(output_name.get());// 显示输出结果的形状auto outShapeInfo = session_.GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();nums.push_back(outShapeInfo[0]);nbs.push_back(outShapeInfo[1]);ncs.push_back(outShapeInfo[2]);if (outShapeInfo.size()>3) {ncs1.push_back(outShapeInfo[3]);ncs2.push_back(outShapeInfo[4]);std::cout << output_node_names[i].c_str() << " format: " << nums[i] << "x" << nbs[i] << "x" << ncs[i] << "x" << ncs1[i] << "x" << ncs2[i] << std::endl;}else {ncs1.push_back(0);ncs2.push_back(0);std::cout << output_node_names[i].c_str() << " format: " << nums[i] << "x" << nbs[i] << "x" << ncs[i] << std::endl;}
3.输入数据预处理: 输入预处理基本流程和此前的图像分类的类似,只是在YOLO系列中不需要考虑方差,因为rgb通道调整、归一化、图像缩放等可以直接通过 cv::dnn::blobFromImage函数完成。
// ******************* 5.输入数据预处理 *******************// 原始图像的宽高int w = frame.cols;int h = frame.rows;// 原始图像与输入图像之间的缩放系数float x_factor = 0.0;float y_factor = 0.0;// 获得原始图像中宽高中的长边,最为变换正方形的边长int _max = std::max(h, w); // 将原始的矩形图像放大变换成正方形图像,默认补零cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3);cv::Rect roi(0, 0, w, h);frame.copyTo(image(roi));// 计算宽高的缩放系数,模型的输入恒定为640×640,必须强制转换成浮点数x_factor = image.cols / static_cast<float>(640); y_factor = image.rows / static_cast<float>(640);// 完成归一化:1.0 / 255.0;缩放:cv::Size(input_w, input_h);格式转换(BGR转RGB):truecv::Mat blob = cv::dnn::blobFromImage(image, 1.0 / 255.0, cv::Size(input_w, input_h), cv::Scalar(0, 0, 0), true, false);std::cout << blob.size[0] << "x" << blob.size[1] << "x" << blob.size[2] << "x" << blob.size[3] << std::endl;// ********************************************************
这里需要注意一点,通常预测图像都不是规则的正方形尺寸,但是博主的yolov3版本是640×640的规则输入,因为宽高进行等比缩放(resize)操作或者宽高单独进行粗暴的缩放操作都可能会影响模型的预测,因此需要先将预测图像补零扩展变成规则的规则输入,再进行缩放操作。
4.后处理推理结果: YOLOV3输出得到的目标框个数为25200(通常是固定的),通过置信度得分和分类得分筛选出有目标的目标框,在通过NMS剔除针对同一目标重复多余的目标框。
// ******************* 8.后处理推理结果 *******************// 1x25200x6 获取(第一个)输出数据并包装成一个cv::Mat对象,为了方便后处理const float* pdata = ort_outputs[0].GetTensorMutableData<float>();cv::Mat det_output(nbs[0], ncs[0], CV_32F, (float*)pdata);std::vector<cv::Rect> boxes; // 目标框的坐标位置std::vector<float> confidences; // 目标框的置信度std::vector<int> classIds; // 目标框的类别得分// 剔除置信度较低的目标框,不作处理for (int i = 0; i < det_output.rows; i++) {float confidence = det_output.at<float>(i, 4);if (confidence < 0.45) {continue;}// 获得当前目标框的类别得分cv::Mat classes_scores = det_output.row(i).colRange(5, ncs[0]);// 这里与图像分类的方式一致cv::Point classIdPoint; // 用于存储分类中的得分最大值索引(坐标)double score; // 用于存储分类中的得分最大值minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);// 处理分类得分较高的目标框if (score > 0.25){ // 计算在原始图像上,目标框的左上角坐标和宽高// 在输入图像上目标框的中心点坐标和宽高float cx = det_output.at<float>(i, 0); float cy = det_output.at<float>(i, 1);float ow = det_output.at<float>(i, 2);float oh = det_output.at<float>(i, 3);//原始图像上目标框的左上角坐标int x = static_cast<int>((cx - 0.5 * ow) * x_factor); int y = static_cast<int>((cy - 0.5 * oh) * y_factor);//原始图像上目标框的宽高int width = static_cast<int>(ow * x_factor);int height = static_cast<int>(oh * y_factor);// 记录目标框信息cv::Rect box;box.x = x;box.y = y;box.width = width;box.height = height;boxes.push_back(box);classIds.push_back(classIdPoint.x);confidences.push_back(score);}}// NMS:非极大值抑制(Non-Maximum Suppression),剔除针对同一目标重复多余的目标框std::vector<int> indexes; // 剔除多余目标框后,保留的目标框的序号cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes);// 遍历筛选出的目标框for (size_t i = 0; i < indexes.size(); i++) {int idx = indexes[i]; // 获取当前目标框序号int cid = classIds[idx]; // 获取目标框分类得分// 输入/输出图像:frame;目标位置信息:boxes[idx];目标框颜色: cv::Scalar(0, 0, 255);// 边框线的厚度:4;线条类型:8;坐标点小数位数精度:0(通常为0)cv::rectangle(frame, boxes[idx], cv::Scalar(0, 0, 255), 4, 8, 0); // 在原始图片上框选目标区域// 输入/输出图像:frame;绘制文本内容:labels[cid].c_str();文本起始位置(左下角):boxes[idx].tl();// 字体类型:cv::FONT_HERSHEY_PLAIN;字体大小缩放比例:2.5;文本颜色:cv::Scalar(255, 0, 0);文本线条的厚度:3;线条类型:8putText(frame, labels[cid].c_str(), boxes[idx].tl(), cv::FONT_HERSHEY_PLAIN, 2.5, cv::Scalar(255, 0, 0), 3, 8); // 目标区域的类别}// ********************************************************
完整推理代码
需要配置face_classes.txt文件存储人脸的分类标签,并将其放置到工程目录下(推荐)。
face
这里需要将yolov3-face.onnx放置到工程目录下(推荐),并且将以下推理代码拷贝到新建的cpp文件中,并执行查看结果。
#include "onnxruntime_cxx_api.h"
#include "cpu_provider_factory.h"
#include <opencv2/opencv.hpp>
#include <fstream>// 加载标签文件获得分类标签
std::string labels_txt_file = "./face_classes.txt";
std::vector<std::string> readClassNames();
std::vector<std::string> readClassNames()
{std::vector<std::string> classNames;std::ifstream fp(labels_txt_file);if (!fp.is_open()){printf("could not open file...\n");exit(-1);}std::string name;while (!fp.eof()){std::getline(fp, name);if (name.length())classNames.push_back(name);}fp.close();return classNames;
}int main(int argc, char** argv) {// 预测的目标标签数std::vector<std::string> labels = readClassNames();// 测试图片cv::Mat frame = cv::imread("./zidane.jpg");cv::imshow("输入图", frame);// ******************* 1.初始化ONNXRuntime环境 *******************Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "YOLOV3-onnx");// ***************************************************************// ******************* 2.设置会话选项 *******************// 创建会话Ort::SessionOptions session_options;// 优化器级别:基本的图优化级别session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);// 线程数:4session_options.SetIntraOpNumThreads(4);// 设备使用优先使用GPU而是才是CPUstd::cout << "onnxruntime inference try to use GPU Device" << std::endl;OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);OrtSessionOptionsAppendExecutionProvider_CPU(session_options, 1);// ******************************************************// ******************* 3.加载模型并创建会话 *******************// onnx训练模型文件std::string onnxpath = "./yolov3-face.onnx";std::wstring modelPath = std::wstring(onnxpath.begin(), onnxpath.end());Ort::Session session_(env, modelPath.c_str(), session_options);// ************************************************************// ******************* 4.获取模型输入输出信息 *******************int input_nodes_num = session_.GetInputCount(); // 输入节点输int output_nodes_num = session_.GetOutputCount(); // 输出节点数std::vector<std::string> input_node_names; // 输入节点名称std::vector<std::string> output_node_names; // 输出节点名称Ort::AllocatorWithDefaultOptions allocator; // 创建默认配置的分配器实例,用来分配和释放内存 // 输入图像尺寸int input_h = 0;int input_w = 0;// 获取模型输入信息for (int i = 0; i < input_nodes_num; i++) {// 获得输入节点的名称并存储auto input_name = session_.GetInputNameAllocated(i, allocator);input_node_names.push_back(input_name.get());// 显示输入图像的形状auto inputShapeInfo = session_.GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();int ch = inputShapeInfo[1];input_h = inputShapeInfo[2];input_w = inputShapeInfo[3];std::cout << "input format: " << ch << "x" << input_h << "x" << input_w << std::endl;}// 获取模型输出信息std::vector<int> nums;std::vector<int> nbs; std::vector<int> ncs;std::vector<int> ncs1;std::vector<int> ncs2;for (int i = 0; i < output_nodes_num; i++) {// 获得输出节点的名称并存储auto output_name = session_.GetOutputNameAllocated(i, allocator);output_node_names.push_back(output_name.get());// 显示输出结果的形状auto outShapeInfo = session_.GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();nums.push_back(outShapeInfo[0]);nbs.push_back(outShapeInfo[1]);ncs.push_back(outShapeInfo[2]);if (outShapeInfo.size()>3) {ncs1.push_back(outShapeInfo[3]);ncs2.push_back(outShapeInfo[4]);std::cout << output_node_names[i].c_str() << " format: " << nums[i] << "x" << nbs[i] << "x" << ncs[i] << "x" << ncs1[i] << "x" << ncs2[i] << std::endl;}else {ncs1.push_back(0);ncs2.push_back(0);std::cout << output_node_names[i].c_str() << " format: " << nums[i] << "x" << nbs[i] << "x" << ncs[i] << std::endl;}}// **************************************************************// ******************* 5.输入数据预处理 *******************// 原始图像的宽高int w = frame.cols;int h = frame.rows;// 原始图像与输入图像之间的缩放系数float x_factor = 0.0;float y_factor = 0.0;// 获得原始图像中宽高中的长边,最为变换正方形的边长int _max = std::max(h, w); // 将原始的矩形图像放大变换成正方形图像,默认补零cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3);cv::Rect roi(0, 0, w, h);frame.copyTo(image(roi));// 计算宽高的缩放系数,模型的输入恒定为640×640,必须强制转换成浮点数x_factor = image.cols / static_cast<float>(640); y_factor = image.rows / static_cast<float>(640);// 完成归一化:1.0 / 255.0;缩放:cv::Size(input_w, input_h);格式转换(BGR转RGB):truecv::Mat blob = cv::dnn::blobFromImage(image, 1.0 / 255.0, cv::Size(input_w, input_h), cv::Scalar(0, 0, 0), true, false);std::cout << blob.size[0] << "x" << blob.size[1] << "x" << blob.size[2] << "x" << blob.size[3] << std::endl;// ********************************************************// ******************* 6.推理准备 *******************// 占用内存大小,后续计算是总像素*数据类型大小size_t tpixels = 3 * input_h * input_w;std::array<int64_t, 4> input_shape_info{ 1, 3, input_h, input_w };// 准备数据输入auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, blob.ptr<float>(), tpixels, input_shape_info.data(), input_shape_info.size());// 模型输入输出所需数据(名称及其数量),模型只认这种类型的数组const std::array<const char*, 1> inputNames = { input_node_names[0].c_str() };const std::array<const char*, 4> outNames = { output_node_names[0].c_str(), output_node_names[1].c_str(), output_node_names[2].c_str(), output_node_names[3].c_str()};// **************************************************// ******************* 7.执行推理 *******************std::vector<Ort::Value> ort_outputs;try {ort_outputs = session_.Run(Ort::RunOptions{ nullptr }, inputNames.data(), &input_tensor_, 1, outNames.data(), outNames.size());}catch (std::exception e) {std::cout << e.what() << std::endl;}// **************************************************// ******************* 8.后处理推理结果 *******************// 1x25200x6 获取(第一个)输出数据并包装成一个cv::Mat对象,为了方便后处理const float* pdata = ort_outputs[0].GetTensorMutableData<float>();cv::Mat det_output(nbs[0], ncs[0], CV_32F, (float*)pdata);std::vector<cv::Rect> boxes; // 目标框的坐标位置std::vector<float> confidences; // 目标框的置信度std::vector<int> classIds; // 目标框的类别得分// 剔除置信度较低的目标框,不作处理for (int i = 0; i < det_output.rows; i++) {float confidence = det_output.at<float>(i, 4);if (confidence < 0.45) {continue;}// 获得当前目标框的类别得分cv::Mat classes_scores = det_output.row(i).colRange(5, ncs[0]);// 这里与图像分类的方式一致cv::Point classIdPoint; // 用于存储分类中的得分最大值索引(坐标)double score; // 用于存储分类中的得分最大值minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);// 处理分类得分较高的目标框if (score > 0.25){ // 计算在原始图像上,目标框的左上角坐标和宽高// 在输入图像上目标框的中心点坐标和宽高float cx = det_output.at<float>(i, 0); float cy = det_output.at<float>(i, 1);float ow = det_output.at<float>(i, 2);float oh = det_output.at<float>(i, 3);//原始图像上目标框的左上角坐标int x = static_cast<int>((cx - 0.5 * ow) * x_factor); int y = static_cast<int>((cy - 0.5 * oh) * y_factor);//原始图像上目标框的宽高int width = static_cast<int>(ow * x_factor);int height = static_cast<int>(oh * y_factor);// 记录目标框信息cv::Rect box;box.x = x;box.y = y;box.width = width;box.height = height;boxes.push_back(box);classIds.push_back(classIdPoint.x);confidences.push_back(score);}}// NMS:非极大值抑制(Non-Maximum Suppression),去除同一个物体的重复多余的目标框std::vector<int> indexes; // 剔除多余目标框后,保留的目标框的序号cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes);// 遍历筛选出的目标框for (size_t i = 0; i < indexes.size(); i++) {int idx = indexes[i]; // 获取当前目标框序号int cid = classIds[idx]; // 获取目标框分类得分// 输入/输出图像:frame;目标位置信息:boxes[idx];目标框颜色: cv::Scalar(0, 0, 255);// 边框线的厚度:4;线条类型:8;坐标点小数位数精度:0(通常为0)cv::rectangle(frame, boxes[idx], cv::Scalar(0, 0, 255), 4, 8, 0); // 在原始图片上框选目标区域// 输入/输出图像:frame;绘制文本内容:labels[cid].c_str();文本起始位置(左下角):boxes[idx].tl();// 字体类型:cv::FONT_HERSHEY_PLAIN;字体大小缩放比例:2.5;文本颜色:cv::Scalar(255, 0, 0);文本线条的厚度:3;线条类型:8putText(frame, labels[cid].c_str(), boxes[idx].tl(), cv::FONT_HERSHEY_PLAIN, 2.5, cv::Scalar(255, 0, 0), 3, 8); // 目标区域的类别}// ********************************************************// 在测试图像上加上预测的目标位置和类别cv::imshow("输入图像", frame);cv::waitKey(0);// ******************* 9.释放资源*******************session_options.release();session_.release();// *************************************************return 0;
}
图片正确识别人脸:
总结
尽可能简单、详细的讲解了C++下OnnxRuntime环境部署YOLOV3模型的过程。
相关文章:
【深度学习】【目标检测】【OnnxRuntime】【C++】YOLOV3模型部署
【深度学习】【目标检测】【OnnxRuntime】【C】YOLOV3模型部署 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【目标检测】【OnnxRuntime】【C】YOLOV3模型部署前言Windows平台搭建依赖环境模型转换--pytorch转onnxONNXRuntime推…...
四种跨模态行人重识别可视化方法
1.Gradcam 2.检索可视化 3.tsne图 4.距离分布 需要的私聊,代码需要付费...
8个DeepSeek文章润色指令
今天道叔给各位文字工作者安利DeepSeek的8个神仙级润色指令(附真实案例拆解),建议搭配冰美式食用更佳↓↓↓ 一、【学术黑话翻译器】 适用场景:给投资人看的BP/行业白皮书/专家访谈实录 指令公式:"将以下内容转化为通俗易懂的行业洞察…...
解决PowerShell下Git中文乱码问题
解决PowerShell下Git中文乱码问题 在使用Git进行版本控制时,许多开发者可能会遇到中文乱码的问题,尤其是在Windows环境下使用PowerShell时。这不仅影响代码的阅读和提交,还可能导致一些不可预见的错误。本文将详细探讨如何在PowerShell下解决…...
oracle数据库(数据库启动关闭/sqlplus登录及基本操作/设置字符集/distinct去重)
目录 1. Oracle数据库启动 2. Oracle数据库关闭 3. sqlplus登录Oracle数据库 3.1 使用sqlplus登录Oracle数据库 3.2 使用sqlplus登录Oracle数据库 3.3 远程登录 3.4 解锁用户 3.5 修改用户密码 3.6 查看当前语言环境 4. sqlplus基本操作 4.1 显示当前用户 4.2 查看当前用户…...
mapreduce时,客户端做哪些事
在MapReduce过程中,客户端(Client)是用户提交作业的入口,负责作业的初始化、配置、资源提交和作业监控。以下是客户端在整个流程中的具体职责和操作步骤: 1. 作业配置与参数解析 设置作业属性: 定义MapRed…...
DeepBI:重构流量逻辑,助力亚马逊广告实现高效流量增长
在日益激烈的跨境电商竞争环境中,广告投放早已从“粗放撒网”走向“精细化运营”。尤其是在亚马逊这样一个成熟且竞争白热化的平台,如何在广告预算有限的前提下实现高效曝光、精准触达、稳定转化,成为众多卖家和运营团队面临的核心挑战。 De…...
Linux内核的页面错误:原因与解决方案
当程序访问虚拟内存中的一个页面时,如果该页面当前不在物理内存中,就会触发一个称为"page fault"(页异常)的异常。操作系统需要处理这个异常,并将所需页面从磁盘加载到内存中。实现虚存管理的一个关键是page…...
LORA 中的 梯度外积是什么意思; 方差和协方差的实际含义:衡量变量的离散程度和变量间的线性相关性
LORA 中的 梯度外积是什么意思 目录 LORA 中的 梯度外积是什么意思**一、梯度外积的定义****二、示例说明****步骤1:计算单样本梯度****步骤2:计算梯度外积****三、梯度外积的作用****四、总结**方差和协方差的实际含义:衡量变量的离散程度和变量间的线性相关性**一、方差(…...
XSS复现漏洞简单前八关靶场
靶场不需要安装任意环境 链接如下:XSS Game - Learning XSS Made Simple! | Created by PwnFunction 目录 XSS Game 第一关:Ma Spaghet! 第二关:Jefff 第三关:Ugandan Knuckles 第四关:Ricardo Milos 第五关&am…...
3.24-3 接口测试断言
一.postman 断言 1.断言再test中 #状态码是否等于200 tests["Status code is 200"] responseCode.code 200; #断言响应时间小于200ms tests["Response time is less than 200ms"] responseTime < 200; #断言响应体包含内容 tests["Body…...
《鸿蒙携手AI:解锁智慧出行底层逻辑》
在科技飞速发展的当下,智慧出行成为人们对未来交通的美好期许,而鸿蒙系统与人工智能的深度融合,正为这一愿景的实现提供强大助力。从技术原理角度深入剖析,鸿蒙系统究竟如何支撑人工智能在智慧出行场景中的应用呢?这背…...
【AVRCP】探寻AVRCP控制互操作性:连接、命令与设备交互
目录 一、AVCTP连接管理 1.1 AVCTP连接建立 1.2 AVCTP连接释放 二、AV/C命令的操作流程 2.1 AV/C命令交换流程 2.2 AV/C命令类型 三、AVRCP特定命令 四、AVRCP浏览命令 五、OBEX连接管理 5.1 OBEX连接建立 5.2 OBEX连接释放 六、总结 七、参考资料 AVRCP对于实现设…...
Mybatis-Plus知识点详解
Mybatis-plus(简称MP),基于Mybatis的增强工具,保留了Mybatis的所有功能,同时增加了通用的CRUD,条件构造器,分页插件等等实用工具 特性 即拿即用:通过通用Mapper和Service,无需编写XML既可以完成单表CURE操作 Lambda支持:使用Lambda表达式构建查询条件,避免硬编码字段名,提升代…...
紧凑交叉引用表
嗯,用户问的是“compact xref table”,也就是紧凑型交叉引用表。我之前在回答中提到过交叉引用流(XRef Stream),但可能需要更详细地解释两者的区别和联系。根据搜索结果中的网页1,传统的Xref表以文本形式存…...
CMake 详解:跨平台构建系统的入门与进阶
目录 一、相关知识点 1. 什么是cmake,为什么使用? 2. 构建过程 二、CMake使用流程 1. 创建 CMakeLists.txt 文件 2. 配置构建目录 3. 运行cmake 4. 运行make编译 一、相关知识点 1. 什么是cmake,为什么使用? CMake 是一个开…...
【架构设计】学习路径
掌握前置知识后,学习架构设计需要从理论认知到实践落地逐步推进。以下是系统化的学习路径,结合具体案例与实操建议,帮助你快速进阶: 一、构建架构思维基础 1. 理解架构设计的核心目标 关键问题驱动设计: 每个架构决策…...
14、Python 枚举与类型注解进阶
Python 枚举与类型注解进阶 文章概述 本文深入探讨Python中枚举(Enum)与类型注解的高级应用场景。通过剖析Enum类的核心特性、dataclass装饰器的工程实践、静态类型检查工具mypy的集成使用,结合状态机等实际案例,系统性地提升代…...
C语言 【实现电脑关机小游戏】非常好玩
引言 在时间限制内做出正确的回答,时间一到,电脑自动关机,听起来是不是很有意思,下面来看看怎么实现吧。 注意:该游戏只在windows系统下可以玩, 一、游戏原理: 在Windows系统下,通…...
【蓝桥杯速成】| 11.回溯 之 子集问题
题目一:子集 问题描述 78. 子集 - 力扣(LeetCode) 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例…...
统计矩的高阶推广:经验还是理论推导?
矩的发展既是经验总结的结果,也是数学理论推导的产物。研究者们在分析数据、描述物理现象的过程中,发现了低阶矩与日常物理概念(如质心、惯性)之间的紧密联系,而高阶矩的应用往往出现在更复杂的数学体系中,…...
SpringBoot2集成Elasticsearch8(使用spring-boot-starter-data-elasticsearch)
写在前面 使用spring-boot-starter-data-elasticsearch集成Elasticsearch8? What? 官方写的不支持啊?让我们来看下官方给出的版本建议。 官方地址: https://docs.spring.io/spring-data/elasticsearch/reference/elasticsearch/versions.…...
Postgresql源码(142)子查询提升pull_up_sublinks
1 案例 drop table t_fun01; create table t_fun01 (image_id numeric primary key, content_id varchar(50), file_code varchar(20)); create index idx3 on t_fun01(content_id); create index idx4 on t_fun01(file_code); insert into t_fun01 select t.i, t.i%10, t.i%1…...
sonar代码检测研究及平台搭建
为了实现提交代码自动检测代码缺陷,本文介绍了一种将jenkins与gitlab集成的自动检测机制,如需应用于生产级开发流程,可在此基础上进行功能丰富和扩展,本文仅进行了原理性搭建。 一、基础环境准备 与sonar配合使用的jenkins和gitlab基础软件…...
清华大学:DeepSeek从入门到精通系列教程1-9讲(持续更新中)|大礼包免费下载
导 读INTRODUCTION 今天分享由清华大学新闻与传播学院、人工智能学院双聘教授沈阳老师团队倾力打造的《DeepSeek从入门到精通系列教程1-9讲(持续更新中)》,包含:《DeepSeek:从入门到精通》《DeepSeek如何赋能职场应用》…...
使用Python可视化图结构:从GraphML文件生成节点关系图(lightrag 生成)
引言 在数据可视化领域,图结构(Graph)常用于展示实体间的复杂关系。例如,文学分析中的角色关系、社交网络中的用户互动等。本文将通过一个实际案例,演示如何使用 NetworkX 和 Matplotlib 从 GraphML 文件生成节点关系…...
排序复习_代码纯享
头文件 #pragma once #include<iostream> #include<vector> #include<utility> using std::vector; using std::cout; using std::cin; using std::endl; using std::swap;//插入排序 //1、直接插入排序(稳定) void InsertSort(vecto…...
Docker Hub Mirror 终极解决方案——0成本,超高速!
CNB Docker Mirror (cdm) CNB Docker Mirror 是一个基于 CNB 的 Docker 镜像加速工具,提供本地镜像加速功能。 功能特性 镜像加速:在本地启动连接到 CNB 环境的 Docker 镜像加速服务,然后通过配置 Docker 客户端实现镜像加速下载自动重连&…...
2000-2019年各省地方财政车船税数据
2000-2019年各省地方财政车船税数据 1、时间:2000-2019年 2、来源:国家统计局、统计年鉴 3、指标:行政区划代码、地区、年份、地方财政车船税 4、范围:31省 5、指标说明:车船税作为地方财政的重要组成部分&#x…...
c#处理算数溢出的情况
在C#中,算术运算的溢出处理可以通过 checked 和 unchecked 关键字控制,默认行为是 静默截断(unchecked模式),但可以通过配置或代码块显式调整。以下是详细说明: 1. 默认行为(unchecked模式&…...
Java「Deque」 方法详解:从入门到实战
Java Deque 各种方法解析:从入门到实战 在 Java 编程中,Deque(双端队列)是一个功能强大的数据结构,允许开发者从队列的两端高效地添加、删除和检查元素。作为 java.util 包中的一部分,Deque 接口继承自 Qu…...
简记_FPGA 硬件最小系统设计
一、FPGA板级设计的五要素 1.1、电源电路 核心电压:一般为固定值 IO电压:FPGA的IO分为多个bank,同一个bank的不同IO引脚电压相同,不同bank的电压可以不同 辅助电压:除了核心电压和IO电压,FPGA工作所需的…...
C++题目
1、内存管理 1.内存模型 栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。 堆:就是那些由new分配的内存块,其释放由程序员控制(一个new对应一个delete)…...
Vulhub-jangow-01-1.0.1通关攻略
第0步: 打开靶机,按下shift,出现下图界面 在此页面按下e键,进入如下界面, 将ro 替换为 rw signie init/bin/bash 替换完毕后,按下Ctrl键X键,进入如下页面 ip a查看网卡信息 编辑配置文件网卡信…...
入剖析 Android Compose 框架的关键帧动画(keyframes、Animatable)(二十三)
深入剖析 Android Compose 框架的关键帧动画(keyframes、Animatable) 引言 在当今的 Android 应用开发领域,用户体验已成为衡量一款应用成功与否的关键因素之一。而动画作为提升用户体验的重要手段,能够为应用增添生动性和交互性…...
java中的枚举类型和c,c++的有区别吗?c,c++的枚举,结构体,联合体,三种数据有什么区别和联系
Java 枚举类型与 C、C 枚举类型的区别 1. 类型安全 Java:Java 的枚举类型是类型安全的。枚举常量是枚举类型的实例,编译器会严格检查传递的参数是否为该枚举类型的有效常量。例如: java Apply enum Color { RED, GREEN, BLUE } // 编译器会检…...
详解Redis的持久化与数据可靠性
Redis持久化与数据可靠性详解(结合实例) Redis作为内存数据库,持久化是保证数据不丢失的核心机制。它通过将内存数据保存到磁盘,确保服务器重启后能恢复数据。Redis提供RDB、AOF和混合持久化三种方式,下面通过实例和操…...
1、mysql基础篇--概述
关系型数据库(RDBMS) 概念特点:数据模型: 概念 建立在关系模型基础上,有多张表相互连接的二维表组成的数据库 特点: 1、使用表存储,格式统一,便于维护 2、使用sql语言操作&#…...
【Tiny RDM】Redis客户端工具
Tiny RDM Tiny RDM是一款现代化、轻量级、跨平台的Redis客户端,支持Mac、Windows和Linux,目前在Github上已有10kStar。 Github 项目地址: https://github.com/tiny-craft/tiny-rdm 功能特性 极度轻量,基于Webview2,…...
常见框架漏洞攻略-Shiro篇
漏洞名称 Shiro rememberMe反序列化漏洞 漏洞简介 Apache Shiro是⼀个强⼤易⽤的Java安全框架,提供了认证、授权、加密和会话管理等功能。Shiro框架直观、易⽤,同时也能提供健壮的安全性。 漏洞原理 在Shiro框架下,⽤户登陆成功后会⽣成…...
常见框架漏洞之一:Thinkphp5x
ThinkPHP是为了简化企业级应⽤开发和敏捷WEB应⽤开发⽽诞⽣的,是⼀个快速、兼容⽽且简单的轻量级国产PHP开发框架,诞⽣于2006年初,原名FCS,2007年元旦正式更名为 ThinkPHP,遵循Apache2开源协议发布,从Stru…...
MORL4PDEs:基于多目标优化与强化学习的数据驱动偏微分方程发现
摘要:本文提出了一种结合多目标优化与强化学习的数据驱动方法MORL4PDEs,用于从复杂系统观测数据中发现简洁的偏微分方程(PDE)。该方法无需预定义候选函数库,通过神经网络代理生成符号表达式,结合遗传算法优…...
UniApp和微信小程序中v-switch夜间模式动画开关
UniApp兼容版 <template><view><view class"main-container" :style"{ backgroundColor: value ? #45e3f9 : #20114c,transform:scale(${size})}" tap"onClick"><view class"content" :style"{ left: val…...
六十天Linux从0到项目搭建第四天(通配符命令、其他命令、压缩解压工具、shell的感性理解、linux权限解析)
通配符(Wildcard) 是 Shell 提供的特殊字符,用于 匹配文件名或路径名,可以代替一个或多个字符,使得命令能批量操作文件,而无需手动输入每个文件名。 典型用法 * 匹配任意字符 *.txt → 匹配所有 .txt 文…...
RAG优化:python从零实现自适应检索增强Adaptive Retrieval
开篇:当RAG遇上“自适应大脑”,检索从此不再“一根筋”!🧠 想象一下,你的AI助手是个超级聪明的“学霸”,但有时候却像个“一根筋”的机器人——无论你问它什么,它都用同一种方式去回答。问它“什么是XAI?”它给你一堆定义;问它“AI发展太快了吗?”它还是给你一堆定…...
C语言实现的冰墩墩
在windows系统下,vs 2022编译。 其中#include <graphics.h>需要自己下载安装。 环境配置没什么难度,直接上demo。 代码如下: #include <graphics.h> #include <conio.h> #include <math.h> #define PI acos(-1.0…...
【构建CV图像识别系统】从传统方法到深度学习
目录 1. 图像的基本概念1.1 像素与色彩1.2 过滤与卷积 2. 图像分类与检测3. 图像特征的提取3.1 全局特征3.2 局部特征3.2.1 边缘(Edge)3.2.2 角点(Corner)3.2.3 SIFT 特征 4. 传统方法与深度学习在图像识别中的应用4.1 基于传统方…...
在Centos 7环境下安装MySQL
前言:在安装与卸载MySQL时,用户需切换为root,这样安装之后,普通用户也能够使用。 Tips:我们在刚开始学习时,尽量全部使用root进行,适应mysql语句,后面学了用户管理,就可以考虑新建普…...
【机器学习基础 4】 Pandas库
一、Pandas库简介 Pandas 是一个开源的 Python 数据分析库,主要用于数据清洗、处理、探索与分析。其核心数据结构是 Series(一维数据)和 DataFrame(二维表格数据),可以让我们高效地操作结构化数据。Pandas …...
干部监督预警系统的定义与功能
一、干部监督预警系统是什么? 干部监督预警系统是通过整合多源数据(如干部档案、履职表现、廉政记录、舆情反馈等),利用大数据分析、人工智能等技术,对干部行为进行实时监测、风险评估和分级预警的数字化管理工具。 二…...