共计 2059 个字符,预计需要花费 6 分钟才能阅读完成。
技术背景
YOLO(You Only Look Once)算法因其实时性和高精度在工业检测领域广受欢迎。相比 Python 生态,C++ 部署有以下优势:

- 运行效率更高,适合嵌入式设备和边缘计算
- 内存管理更精细,适合长期运行的工业级应用
- 更容易与现有 C ++ 工业系统集成
环境配置
Ubuntu 系统
-
安装基础依赖
sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config -
安装 CUDA 和 cuDNN(以 CUDA 11.3 为例)
sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub sudo add-apt-repository "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/ /" sudo apt-get install cuda-11-3 libcudnn8 -
编译 OpenCV(建议 4.5.5 版本)
git clone --branch 4.5.5 https://github.com/opencv/opencv.git cd opencv && mkdir build && cd build cmake -D WITH_CUDA=ON -D CUDA_ARCH_BIN="7.5" .. make -j8 sudo make install
Windows 系统
- 安装 Visual Studio 2019+ 和 CMake
- 下载预编译的 CUDA 和 cuDNN
- 使用 CMake-GUI 配置 OpenCV 时勾选 WITH_CUDA 选项
核心实现
模型加载
cv::dnn::Net net = cv::dnn::readNetFromONNX("yolov5s.onnx");
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
图像预处理
cv::Mat blob = cv::dnn::blobFromImage(
image, // 输入图像
1/255.0, // 归一化系数
cv::Size(640, 640), // 模型输入尺寸
cv::Scalar(0,0,0), // 均值减除
true, // 交换 RB 通道
false, // 不裁剪
CV_32F // 输出类型
);
后处理实现
struct Detection {
int class_id;
float confidence;
cv::Rect box;
};
std::vector<Detection> postprocess(
const cv::Mat& output,
float conf_threshold=0.5,
float iou_threshold=0.4
) {
std::vector<Detection> detections;
// 解析输出层数据
// [Nx25200x85] for YOLOv5
// 置信度过滤
// ...
// NMS 处理
// ...
return detections;
}
代码规范
CMake 配置示例
cmake_minimum_required(VERSION 3.10)
project(YOLOInference)
find_package(OpenCV REQUIRED)
add_executable(yolo_inference main.cpp)
target_link_libraries(yolo_inference ${OpenCV_LIBS})
RAII 资源管理
class NetWrapper {
public:
NetWrapper(const std::string& model_path) {net_ = cv::dnn::readNet(model_path);
}
~NetWrapper() {// 自动释放资源}
private:
cv::dnn::Net net_;
};
性能优化
| 精度模式 | 推理时间 (ms) | 显存占用 (MB) |
|---|---|---|
| FP32 | 15.2 | 1200 |
| FP16 | 9.8 | 800 |
多线程预处理方案:
void preprocessThread(
const cv::Mat& frame,
std::promise<cv::Mat>&& promise
) {cv::Mat blob = cv::dnn::blobFromImage(frame, ...);
promise.set_value(blob);
}
避坑指南
- OpenCV 版本与 CUDA 的兼容性
- OpenCV 4.5+ 对 CUDA 11.x 支持最好
-
编译时注意 CUDA_ARCH 设置
-
模型输出层解析
- 不同 YOLO 版本的输出维度不同
-
建议使用 netron 工具查看模型结构
-
跨平台部署
- Windows 下注意 DLL 依赖
- ARM 平台需要交叉编译
思考题
如何实现动态 batch 处理?考虑以下方向:
– 使用 std::vector 收集多帧
– 设计批处理队列
– 异步推理流水线
正文完
