YOLOs-CPP:一个免费开源的YOLO全系列C++推理库(以YOLO26为例)

YOLOs-CPP:一个免费开源的YOLO全系列C++推理库(以YOLO26为例)

YOLOs-CPP:一个免费开源的YOLO全系列C++推理库(以YOLO26为例)

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

前言

由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击进入Python日常小操作专栏、OpenCV-Python小应用专栏、YOLO系列专栏、自然语言处理专栏、人工智能混合编程实践专栏或我的个人主页查看Ultralytics:使用 YOLO11 进行速度估计Ultralytics:使用 YOLO11 进行物体追踪Ultralytics:使用 YOLO11 进行物体计数Ultralytics:使用 YOLO11 进行目标打码人工智能混合编程实践:C++调用Python ONNX进行YOLOv8推理人工智能混合编程实践:C++调用封装好的DLL进行YOLOv8实例分割人工智能混合编程实践:C++调用Python ONNX进行图像超分重建人工智能混合编程实践:C++调用Python AgentOCR进行文本识别通过计算实例简单地理解PatchCore异常检测Python将YOLO格式实例分割数据集转换为COCO格式实例分割数据集YOLOv8 Ultralytics:使用Ultralytics框架训练RT-DETR实时目标检测模型基于DETR的人脸伪装检测YOLOv7训练自己的数据集(口罩检测)YOLOv8训练自己的数据集(足球检测)YOLOv5:TensorRT加速YOLOv5模型推理YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU玩转Jetson Nano(五):TensorRT加速YOLOv5目标检测YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力机制YOLOv5:yolov5s.yaml配置文件解读、增加小目标检测层Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集YOLOv5:使用7.0版本训练自己的实例分割模型(车辆、行人、路标、车道线等实例分割)使用Kaggle GPU资源免费体验Stable Diffusion开源项目Stable Diffusion:在服务器上部署使用Stable Diffusion WebUI进行AI绘图(v2.0)Stable Diffusion:使用自己的数据集微调训练LoRA模型(v2.0)

环境要求

Windows 10VS2019C++17 compatible compilerCMake (version 3.10 or higher)OpenCV (version 4.5.5 or higher)ONNX Runtime (version 1.15.0 or higher, with optional GPU support)

相关介绍

C++简介

C++ 是一种广泛使用的编程语言,最初由丹麦计算机科学家Bjarne Stroustrup于1979年在贝尔实验室开发,作为C语言的扩展。C++的设计目标是提供一种能够高效利用硬件资源,同时支持面向对象编程(OOP)特性的语言。随着时间的发展,C++也引入了泛型编程和函数式编程的支持,使其成为一种多范式编程语言。

ONNX简介

ONNX(Open Neural Network Exchange) 是一个开放的生态系统,旨在促进不同框架之间深度学习模型的互操作性。通过ONNX,开发者可以更容易地在不同的深度学习框架(如PyTorch、TensorFlow等)间共享和部署模型。ONNX定义了一种通用的模型文件格式,使得训练好的模型可以在各种硬件平台上高效运行,无论是服务器端还是边缘设备。这有助于加速机器学习技术的研发和应用。

ONNX Runtime 简介

ONNX Runtime 是一个用于高效执行 ONNX(Open Neural Network Exchange)格式机器学习模型的引擎。它旨在简化模型部署,并支持多种硬件加速选项。

核心特点
  • 跨平台:支持 Windows、Linux 和 macOS。
  • 多硬件支持:包括 CPU、NVIDIA GPU(通过 CUDA)、AMD GPU 等。
  • 高性能:通过图优化和硬件特定优化提高推理速度。
  • 框架兼容性:支持从 TensorFlow、PyTorch 等转换的 ONNX 模型。
  • 易用API:提供 C++, Python, C#, Java 等语言接口。
  • 量化支持:减少模型大小并加快推理速度。

YOLOs-CPP简介

YOLOs-CPP 是一款生产级推理引擎,将完整的 YOLO 生态系统引入 C++ 领域。不同于分散的实现方案,YOLOs-CPP 为所有 YOLO 版本和任务提供了统一、一致的 API。

核心能力
  • 高性能:零拷贝预处理、优化NMS算法、GPU加速
  • 精准匹配:与Ultralytics Python版本结果完全一致(经36项自动化测试验证)
  • 自包含:无需Python运行时环境,运行时无外部依赖
  • 易集成:基于头文件的库,采用现代C++17 API
  • 灵活:支持CPU/GPU并行,动态/静态输入形状,可配置阈值

Windows下使用YOLOs-CPP

下载YOLOs-CPP项目

官方源代码: https://github.com/Geekgineer/YOLOs-CPP.git

Windows

git clone https://github.com/Geekgineer/YOLOs-CPP.git 
在这里插入图片描述

YOLOs-CPP项目结构

YOLOs-CPP/ ├── include/yolos/ # Core library │ ├── core/ # Shared utilities │ │ ├── types.hpp # Detection, Segmentation result types │ │ ├── preprocessing.hpp # Letterbox, normalization │ │ ├── nms.hpp # Non-maximum suppression │ │ ├── drawing.hpp # Visualization utilities │ │ └── version.hpp # YOLO version detection │ ├── tasks/ # Task implementations │ │ ├── detection.hpp # Object detection │ │ ├── segmentation.hpp # Instance segmentation │ │ ├── pose.hpp # Pose estimation │ │ ├── obb.hpp # Oriented bounding boxes │ │ └── classification.hpp │ └── yolos.hpp # Main include (includes all) ├── src/ # Example applications ├── examples/ # Task-specific examples ├── tests/ # Automated test suite ├── benchmarks/ # Performance benchmarking └── models/ # Sample models & labels

导出ONNX

from ultralytics import YOLO # Load the yolo26s model model = YOLO("yolo26s.pt")# Export the model to ONNX format success = model.export(format="onnx")
在这里插入图片描述

使用VS2019编译运行C++推理

由于我的windows电脑使用CMake构建项目,报错了。因此,我直接使用VS2019创建了一个项目,里面的核心文件与YOLOs-CPP的一致。
在这里插入图片描述

infer_utils.hpp

/** * @file utils.hpp * @brief Utility functions for examples (timestamps, file saving, argument parsing) */#ifndefUTILS_HPP#defineUTILS_HPP#include<string>#include<chrono>#include<iomanip>#include<sstream>#include<filesystem>#include<algorithm>#include<opencv2/opencv.hpp>namespace utils {/** * @brief Get current timestamp string in format: YYYYMMDD_HHMMSS * @return Timestamp string */inline std::string getTimestamp(){auto now = std::chrono::system_clock::now();auto time_t_now = std::chrono::system_clock::to_time_t(now); std::tm tm_now;// Cross-platform localtime#ifdef_WIN32localtime_s(&tm_now,&time_t_now);// Windows#elselocaltime_r(&time_t_now,&tm_now);// POSIX (Linux/macOS)#endif std::ostringstream oss; oss << std::put_time(&tm_now,"%Y%m%d_%H%M%S");return oss.str();}/** * @brief Generate output filename with timestamp * @param inputPath Original input file path * @param outputDir Output directory (e.g., "outputs/det/") * @param suffix Additional suffix (e.g., "_result") * @return Full output path with timestamp */inline std::string getOutputPath(const std::string& inputPath,const std::string& outputDir,const std::string& suffix ="_result"){namespace fs = std::filesystem;// Ensure output directory exists fs::create_directories(outputDir);// Get input filename without extension fs::path inputFilePath(inputPath); std::string baseName = inputFilePath.stem().string(); std::string extension = inputFilePath.extension().string();// Create output filename: basename_timestamp_suffix.ext std::string timestamp =getTimestamp(); std::string outputFilename = baseName +"_"+ timestamp + suffix + extension;return(fs::path(outputDir)/ outputFilename).string();}/** * @brief Save image with timestamp * @param image Image to save * @param inputPath Original input path * @param outputDir Output directory * @return Path where image was saved */inline std::string saveImage(const cv::Mat& image,const std::string& inputPath,const std::string& outputDir){ std::string outputPath =getOutputPath(inputPath, outputDir); cv::imwrite(outputPath, image);return outputPath;}/** * @brief Save video writer output path with timestamp * @param inputPath Original input path * @param outputDir Output directory * @return Output path for video */inline std::string getVideoOutputPath(const std::string& inputPath,const std::string& outputDir){returngetOutputPath(inputPath, outputDir,"_result");}/** * @brief Print performance metrics * @param taskName Name of the task * @param durationMs Duration in milliseconds * @param fps Frames per second (optional) */inlinevoidprintMetrics(const std::string& taskName,int64_t durationMs,double fps =-1){ std::cout <<"\n═══════════════════════════════════════"<< std::endl; std::cout <<" "<< taskName <<" Metrics"<< std::endl; std::cout <<"═══════════════════════════════════════"<< std::endl; std::cout <<" Inference Time: "<< durationMs <<" ms"<< std::endl;if(fps >0){ std::cout <<" FPS: "<< std::fixed << std::setprecision(2)<< fps << std::endl;} std::cout <<"═══════════════════════════════════════\n"<< std::endl;}/** * @brief Check if file extension is supported image format */inlineboolisImageFile(const std::string& path){ std::string ext = std::filesystem::path(path).extension().string(); std::transform(ext.begin(), ext.end(), ext.begin(),::tolower);return(ext ==".jpg"|| ext ==".jpeg"|| ext ==".png"|| ext ==".bmp"|| ext ==".tiff"|| ext ==".tif");}/** * @brief Check if file extension is supported video format */inlineboolisVideoFile(const std::string& path){ std::string ext = std::filesystem::path(path).extension().string(); std::transform(ext.begin(), ext.end(), ext.begin(),::tolower);return(ext ==".mp4"|| ext ==".avi"|| ext ==".mov"|| ext ==".mkv"|| ext ==".flv"|| ext ==".wmv");}/** * @brief Print usage information */inlinevoidprintUsage(const std::string& programName,const std::string& taskType,const std::string& defaultModel,const std::string& defaultInput,const std::string& defaultLabels){ std::cout <<"\n╔════════════════════════════════════════════════════╗"<< std::endl; std::cout <<"║ YOLOs-CPP "<< taskType <<" Example"<< std::endl; std::cout <<"╚════════════════════════════════════════════════════╝"<< std::endl; std::cout <<"\nUsage: "<< programName <<" [model_path] [input_path] [labels_path]"<< std::endl; std::cout <<"\nArguments:"<< std::endl; std::cout <<" model_path : Path to ONNX model (default: "<< defaultModel <<")"<< std::endl; std::cout <<" input_path : Image/video file or directory (default: "<< defaultInput <<")"<< std::endl; std::cout <<" labels_path : Path to class labels file (default: "<< defaultLabels <<")"<< std::endl; std::cout <<"\nExamples:"<< std::endl; std::cout <<" "<< programName << std::endl; std::cout <<" "<< programName <<" ../models/yolo11n.onnx"<< std::endl; std::cout <<" "<< programName <<" ../models/yolo11n.onnx ../data/image.jpg"<< std::endl; std::cout <<" "<< programName <<" ../models/yolo11n.onnx ../data/ ../models/coco.names"<< std::endl; std::cout << std::endl;}}// namespace utils#endif// UTILS_HPP

main.cpp

/** * @file example_image_det.cpp * @brief Standard object detection on images using YOLO models * @details Loads a YOLO detection model and performs inference on images */#include<opencv2/opencv.hpp>#include<iostream>#include<iomanip>#include<chrono>#include<filesystem>#include<vector>#include"classification.hpp"#include"detection.hpp"#include"segmentation.hpp"#include"obb.hpp"#include"pose.hpp"#include"infer_utils.hpp"usingnamespace yolos::cls;usingnamespace yolos::det;usingnamespace yolos::seg;usingnamespace yolos::obb;usingnamespace yolos::pose;intmain(int argc,char* argv[]){namespace fs = std::filesystem;// Default configuration std::string inputPath ="src"; std::string outputDir ="dst/"; std::string modelPath ="./models/yolo26s.onnx"; std::string labelsPath ="./models/coco.names";// Default configuration std::string cls_modelPath ="./models/yolo26s-cls.onnx"; std::string cls_labelsPath ="./models/ImageNet.names";// Default configuration std::string seg_modelPath ="./models/yolo26s-seg.onnx";// Default configuration std::string obb_modelPath ="./models/yolo26s-obb.onnx"; std::string obb_labelsPath ="./models/Dota.names";// Default configuration std::string pose_modelPath ="./models/yolo26s-pose.onnx";// Collect image files std::vector<std::string> imageFiles;try{if(fs::is_directory(inputPath)){for(constauto& entry : fs::directory_iterator(inputPath)){if(entry.is_regular_file()&& utils::isImageFile(entry.path().string())){ imageFiles.push_back(fs::absolute(entry.path()).string());}}if(imageFiles.empty()){ std::cerr <<"❌ No image files found in: "<< inputPath << std::endl;return-1;}}elseif(fs::is_regular_file(inputPath)){ imageFiles.push_back(inputPath);}else{ std::cerr <<"❌ Invalid path: "<< inputPath << std::endl;return-1;}}catch(const fs::filesystem_error& e){ std::cerr <<"❌ Filesystem error: "<< e.what()<< std::endl;return-1;}// Initialize YOLO detector//bool useGPU = false; // CPU by defaultbool useGPU =true;// CPU by default std::cout <<"🔄 Loading detection model: "<< modelPath << std::endl;try{ YOLODetector detector(modelPath, labelsPath, useGPU); std::cout <<"✅ Model loaded successfully!"<< std::endl;// Process each imagefor(constauto& imgPath : imageFiles){ std::cout <<"\n📷 Processing: "<< imgPath << std::endl;// Load image cv::Mat image = cv::imread(imgPath);if(image.empty()){ std::cerr <<"❌ Could not load image: "<< imgPath << std::endl;continue;}// Run detection with timingauto start = std::chrono::high_resolution_clock::now(); std::vector<Detection> detections = detector.detect(image);auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now()- start);// Print results std::cout <<"✅ Detection completed!"<< std::endl; std::cout <<"📊 Found "<< detections.size()<<" objects"<< std::endl;for(size_t i =0; i < detections.size();++i){ std::cout <<" ["<< i <<"]token operator"><< detections[i].classId <<", Confidence="<< std::fixed << std::setprecision(2)<< detections[i].conf <<", Box=("<< detections[i].box.x <<","<< detections[i].box.y <<","<< detections[i].box.width <<"x"<< detections[i].box.height <<")"<< std::endl;}// Draw detections cv::Mat resultImage = image.clone(); detector.drawDetections(resultImage, detections);// Save output with timestamp std::string outputPath = utils::saveImage(resultImage, imgPath, outputDir); std::cout <<"💾 Saved result to: "<< outputPath << std::endl;// Display metrics utils::printMetrics("Detection", duration.count());//// Display result//cv::imshow("YOLO Detection", resultImage);//std::cout << "Press any key to continue..." << std::endl;//cv::waitKey(0);} cv::destroyAllWindows(); std::cout <<"\n✅ All images processed successfully!"<< std::endl;}catch(const std::exception& e){ std::cerr <<"❌ Error: "<< e.what()<< std::endl;return-1;}// Initialize YOLO classifier//bool useGPU = false; // CPU by default std::cout <<"🔄 Loading classification model: "<< cls_modelPath << std::endl;try{// Use YOLO11 version by default YOLOClassifier classifier(cls_modelPath, cls_labelsPath, useGPU); std::cout <<"✅ Model loaded successfully!"<< std::endl; std::cout <<"📐 Input shape: "<< classifier.getInputShape()<< std::endl;// Process each imagefor(constauto& imgPath : imageFiles){ std::cout <<"\n📷 Processing: "<< imgPath << std::endl;// Load image cv::Mat image = cv::imread(imgPath);if(image.empty()){ std::cerr <<"❌ Could not load image: "<< imgPath << std::endl;continue;}// Run classification with timingauto start = std::chrono::high_resolution_clock::now(); ClassificationResult result = classifier.classify(image);auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now()- start);// Print results std::cout <<"✅ Classification completed!"<< std::endl; std::cout <<"📊 Result: "<< result.className <<" (ID: "<< result.classId <<")"<<" with confidence: "<< std::fixed << std::setprecision(4)<<(result.confidence *100.0f)<<"%"<< std::endl;// Draw result on image cv::Mat resultImage = image.clone(); classifier.drawResult(resultImage, result, cv::Point(10,30));// Save output with timestamp std::string outputPath = utils::saveImage(resultImage, imgPath, outputDir); std::cout <<"💾 Saved result to: "<< outputPath << std::endl;// Display metrics utils::printMetrics("Classification", duration.count());//// Display result//cv::imshow("YOLO Classification", resultImage);//std::cout << "Press any key to continue..." << std::endl;//cv::waitKey(0);} cv::destroyAllWindows(); std::cout <<"\n✅ All images processed successfully!"<< std::endl;}catch(const std::exception& e){ std::cerr <<"❌ Error: "<< e.what()<< std::endl;return-1;}// Initialize YOLO segmentation detector//bool useGPU = false; // CPU by default std::cout <<"🔄 Loading segmentation model: "<< seg_modelPath << std::endl;try{ YOLOSegDetector detector(seg_modelPath, labelsPath, useGPU); std::cout <<"✅ Model loaded successfully!"<< std::endl;// Process each imagefor(constauto& imgPath : imageFiles){ std::cout <<"\n📷 Processing: "<< imgPath << std::endl;// Load image cv::Mat image = cv::imread(imgPath);if(image.empty()){ std::cerr <<"❌ Could not load image: "<< imgPath << std::endl;continue;}// Run segmentation with timingauto start = std::chrono::high_resolution_clock::now(); std::vector<Segmentation> results = detector.segment(image);auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now()- start);// Print results std::cout <<"✅ Segmentation completed!"<< std::endl; std::cout <<"📊 Found "<< results.size()<<" segments"<< std::endl;for(size_t i =0; i < results.size();++i){ std::cout <<" ["<< i <<"]token operator"><< results[i].classId <<", Confidence="<< std::fixed << std::setprecision(2)<< results[i].conf <<", Box=("<< results[i].box.x <<","<< results[i].box.y <<","<< results[i].box.width <<"x"<< results[i].box.height <<")"<<", Mask size="<< results[i].mask.size()<< std::endl;}// Draw segmentations with boxes and masks cv::Mat resultImage = image.clone(); detector.drawSegmentations(resultImage, results);// Save output with timestamp std::string outputPath = utils::saveImage(resultImage, imgPath, outputDir); std::cout <<"💾 Saved result to: "<< outputPath << std::endl;// Display metrics utils::printMetrics("Segmentation", duration.count());//// Display result//cv::imshow("YOLO Segmentation", resultImage);//std::cout << "Press any key to continue..." << std::endl;//cv::waitKey(0);} cv::destroyAllWindows(); std::cout <<"\n✅ All images processed successfully!"<< std::endl;}catch(const std::exception& e){ std::cerr <<"❌ Error: "<< e.what()<< std::endl;return-1;} std::cout <<"🔄 Loading OBB model: "<< obb_modelPath << std::endl;try{ YOLOOBBDetector detector(obb_modelPath, obb_labelsPath, useGPU); std::cout <<"✅ Model loaded successfully!"<< std::endl;// Process each imagefor(constauto& imgPath : imageFiles){ std::cout <<"\n📷 Processing: "<< imgPath << std::endl;// Load image cv::Mat image = cv::imread(imgPath);if(image.empty()){ std::cerr <<"❌ Could not load image: "<< imgPath << std::endl;continue;}// Run OBB detection with timingauto start = std::chrono::high_resolution_clock::now(); std::vector<OBBResult> detections = detector.detect(image);auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now()- start);// Print results std::cout <<"✅ OBB detection completed!"<< std::endl; std::cout <<"📊 Found "<< detections.size()<<" oriented boxes"<< std::endl;for(size_t i =0; i < detections.size();++i){ std::cout <<" ["<< i <<"]token operator"><< detections[i].classId <<", Confidence="<< std::fixed << std::setprecision(2)<< detections[i].conf <<", Center=("<< detections[i].box.x <<","<< detections[i].box.y <<")"<<", Size=("<< detections[i].box.width <<"x"<< detections[i].box.height <<")"<<", Angle="<<(detections[i].box.angle *180.0/ CV_PI)<<"°"<< std::endl;}// Draw oriented bounding boxes cv::Mat resultImage = image.clone(); detector.drawDetections(resultImage, detections);// Save output with timestamp std::string outputPath = utils::saveImage(resultImage, imgPath, outputDir); std::cout <<"💾 Saved result to: "<< outputPath << std::endl;// Display metrics utils::printMetrics("OBB Detection", duration.count());//// Display result//cv::imshow("YOLO OBB Detection", resultImage);//std::cout << "Press any key to continue..." << std::endl;//cv::waitKey(0);} cv::destroyAllWindows(); std::cout <<"\n✅ All images processed successfully!"<< std::endl;}catch(const std::exception& e){ std::cerr <<"❌ Error: "<< e.what()<< std::endl;return-1;} std::cout <<"🔄 Loading pose estimation model: "<< pose_modelPath << std::endl;try{ YOLOPoseDetector detector(pose_modelPath, labelsPath, useGPU); std::cout <<"✅ Model loaded successfully!"<< std::endl;// Process each imagefor(constauto& imgPath : imageFiles){ std::cout <<"\n📷 Processing: "<< imgPath << std::endl;// Load image cv::Mat image = cv::imread(imgPath);if(image.empty()){ std::cerr <<"❌ Could not load image: "<< imgPath << std::endl;continue;}// Run pose detection with timingauto start = std::chrono::high_resolution_clock::now(); std::vector<PoseResult> detections = detector.detect(image,0.4f,0.5f);auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::high_resolution_clock::now()- start);// Print results std::cout <<"✅ Pose detection completed!"<< std::endl; std::cout <<"📊 Found "<< detections.size()<<" person(s)"<< std::endl;for(size_t i =0; i < detections.size();++i){ std::cout <<" ["<< i <<"] Confidence="<< std::fixed << std::setprecision(2)<< detections[i].conf <<", Box=("<< detections[i].box.x <<","<< detections[i].box.y <<","<< detections[i].box.width <<"x"<< detections[i].box.height <<")"<<", Keypoints="<< detections[i].keypoints.size()<< std::endl;}// Draw pose keypoints and skeleton cv::Mat resultImage = image.clone(); detector.drawPoses(resultImage, detections);// Save output with timestamp std::string outputPath = utils::saveImage(resultImage, imgPath, outputDir); std::cout <<"💾 Saved result to: "<< outputPath << std::endl;// Display metrics utils::printMetrics("Pose Estimation", duration.count());//// Display result//cv::imshow("YOLO Pose Estimation", resultImage);//std::cout << "Press any key to continue..." << std::endl;//cv::waitKey(0);} cv::destroyAllWindows(); std::cout <<"\n✅ All images processed successfully!"<< std::endl;}catch(const std::exception& e){ std::cerr <<"❌ Error: "<< e.what()<< std::endl;return-1;}return0;}

推理结果(以YOLO26为例))

图像分类

在这里插入图片描述
在这里插入图片描述

目标检测

在这里插入图片描述
在这里插入图片描述

实例分割

在这里插入图片描述
在这里插入图片描述

旋转框检测

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述

姿势估计

在这里插入图片描述
在这里插入图片描述

更多功能

更多功能可查阅官方项目代码中的相关文档,自行探索。

参考

[1] https://github.com/Geekgineer/YOLOs-CPP.git

由于本人水平有限,难免出现错漏,敬请批评改正。更多精彩内容,可点击进入Python日常小操作专栏、OpenCV-Python小应用专栏、YOLO系列专栏、自然语言处理专栏、人工智能混合编程实践专栏或我的个人主页查看Ultralytics:使用 YOLO11 进行速度估计Ultralytics:使用 YOLO11 进行物体追踪Ultralytics:使用 YOLO11 进行物体计数Ultralytics:使用 YOLO11 进行目标打码人工智能混合编程实践:C++调用Python ONNX进行YOLOv8推理人工智能混合编程实践:C++调用封装好的DLL进行YOLOv8实例分割人工智能混合编程实践:C++调用Python ONNX进行图像超分重建人工智能混合编程实践:C++调用Python AgentOCR进行文本识别通过计算实例简单地理解PatchCore异常检测Python将YOLO格式实例分割数据集转换为COCO格式实例分割数据集YOLOv8 Ultralytics:使用Ultralytics框架训练RT-DETR实时目标检测模型基于DETR的人脸伪装检测YOLOv7训练自己的数据集(口罩检测)YOLOv8训练自己的数据集(足球检测)YOLOv5:TensorRT加速YOLOv5模型推理YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU玩转Jetson Nano(五):TensorRT加速YOLOv5目标检测YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力机制YOLOv5:yolov5s.yaml配置文件解读、增加小目标检测层Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集YOLOv5:使用7.0版本训练自己的实例分割模型(车辆、行人、路标、车道线等实例分割)使用Kaggle GPU资源免费体验Stable Diffusion开源项目Stable Diffusion:在服务器上部署使用Stable Diffusion WebUI进行AI绘图(v2.0)Stable Diffusion:使用自己的数据集微调训练LoRA模型(v2.0)

Read more

C++红黑树的深入解析:从理论到实践

C++红黑树的深入解析:从理论到实践

红黑树作为一种自平衡的二叉搜索树,是计算机科学中的经典数据结构之一,广泛应用于各种需要高效查找、插入和删除操作的场景中,比如STL中的 map 和 set。虽然它的基本原理并不复杂,但在实现过程中,需要处理许多细节,比如颜色的调整、旋转操作等。本文将对红黑树的结构、插入、删除等操作进行详细的剖析,以帮助大家更好地理解和实现这一高效的数据结构。 一、红黑树的基本概念与规则 红黑树是一种满足特定性质的二叉搜索树。与普通的二叉搜索树不同,红黑树的每个结点都附加了一个颜色属性,且通过一些规则保证了树的平衡性。红黑树的四条基本规则如下: 每个节点的颜色要么是红色,要么是黑色。根节点是黑色的。如果一个节点是红色的,那么它的两个子节点必须是黑色的。 这就意味着红色节点不能有连续的红色节点。从任意一个节点到其所有叶子节点的路径上,必须包含相同数量的黑色节点。 这条规则保证了树的平衡性,防止树的某些路径过长。 红黑树的这些规则通过“颜色约束”来间接实现自平衡,因此每次进行插入、删除操作时,都需要确保这些规则被满足。 以上均为红黑树示例。 二、红黑树的高度与效率 红黑树的高度是它的关键特性之

By Ne0inhk
python之路并不一马平川:带你踩坑Pandas

python之路并不一马平川:带你踩坑Pandas

这是我的亲身经历。作为一名全能型的混子,Pandas是我吃饭的家伙之一,但光是把它请到我的电脑上,就差点让我“饭碗不保”。这是一段长达数周,充满挫折、困惑和最终解脱的曲折历程。我将带你完整回顾我踩过的每一个坑,以及那最后的“救命稻草”。我将以第一视角,带你完整回顾我踩过的那些坑,以及我是如何一步步爬出来的。 记得刚入行那年,我接手的第一个项目是个电商小程序开发。当时为了赶进度,我直接跳过了需求分析阶段,结果上线后发现支付接口和后台数据对不上,不得不紧急下架整改。那三天三夜不眠不休的debug经历,现在想起来还心有余悸。 去年在开发智能家居App时,我又犯了个典型错误:没有做好版本兼容性测试。当用户反馈老型号设备无法连接时,我们才发现蓝牙协议栈对新老设备的处理方式完全不同。这个教训让我养成了建立完整测试矩阵的习惯。 最惨痛的经历是去年年底的云服务迁移。当时为了节省成本,我选择了直接全量迁移数据库,结果因为网络波动导致数据不一致,差点酿成重大事故。现在我做数据迁移时都会严格遵循"全量备份-增量同步-数据校验"的标准流程。 这些血泪教训让我明白,在技术这条路上,捷径往往是最远的路。每

By Ne0inhk
【STL】stack/queue 底层模拟实现与典型算法场景实践

【STL】stack/queue 底层模拟实现与典型算法场景实践

前言 STL 中 stack 与 queue 本质是容器适配器,基于基础容器封装实现特定操作逻辑。本文先介绍容器适配器及二者核心概念,再手动模拟实现,最后通过几道算法题展示其应用,助力夯实 STL 设计思想与数据结构基础。 目录  ------------容器适配器------------ 1、什么是容器适配器? 2、为啥容器配置器不支持迭代器  ---------------stack--------------- 1、stack介绍 2、stack模拟实现 问题:为啥 stack 不用提供默认成员函数? ---------------queue-------------- 1、queue介绍 2、queue模拟实现 --------------算法题-------------- 1、最小栈 2、栈的压入、弹出序列 3、逆波兰表达式求值 4、用栈实现队列 5、用队列实现栈  ------------容器适配器------------ 1、什么是容器适配器? 适配器可以理解为“

By Ne0inhk
C++ 运算符重载:自定义类型的运算扩展

C++ 运算符重载:自定义类型的运算扩展

C++ 运算符重载:自定义类型的运算扩展 💡 学习目标:掌握运算符重载的核心语法与规则,能够为自定义类型重载常用运算符,实现类对象的灵活运算。 💡 学习重点:运算符重载的基本形式、成员函数与全局函数重载的区别、常见运算符的重载实现、禁止重载的运算符。 一、运算符重载的概念与核心价值 ✅ 结论:运算符重载是 C++ 静态多态的重要体现,允许为自定义类型(如类、结构体)重新定义运算符的行为,让自定义对象可以像内置类型一样使用运算符。 运算符重载的核心价值: 1. 简化代码书写:用直观的运算符替代繁琐的成员函数调用,提升代码可读性 2. 统一操作风格:让自定义类型的运算逻辑与内置类型保持一致,降低学习和使用成本 3. 扩展类型功能:根据业务需求定制运算符的行为,满足自定义类型的运算需求 ⚠️ 注意事项:运算符重载不会改变运算符的优先级和结合性,也不会改变运算符的操作数个数。 二、运算符重载的基本语法 运算符重载的本质是函数重载,分为成员函数重载和全局函数重载两种形式。 2.1 成员函数重载语法 将运算符重载函数定义为类的成员函数,语法格式如下: class

By Ne0inhk