C++实战YOLO算法:从环境搭建到模型推理的完整指南

1次阅读
没有评论

共计 2743 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

技术背景

YOLO(You Only Look Once)算法因其实时性和高精度,在工业检测领域广受欢迎。与 Python 生态相比,C++ 部署具有以下优势:

C++ 实战 YOLO 算法:从环境搭建到模型推理的完整指南

  • 性能优势:C++ 直接编译为机器码,无解释器开销
  • 资源控制:精确管理内存和计算资源
  • 部署便捷:生成单个可执行文件,无需依赖 Python 环境
  • 系统集成:更容易嵌入现有 C ++ 工业系统

环境配置

Ubuntu 系统

  1. 安装基础依赖

    sudo apt-get install build-essential cmake git libgtk2.0-dev

  2. 安装 CUDA 和 cuDNN(以 CUDA 11.1 为例)

    sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub
    sudo apt-get install cuda-toolkit-11-1 libcudnn8

  3. 编译 OpenCV(4.5.0+)

    git clone --branch 4.5.5 https://github.com/opencv/opencv.git
    mkdir build && cd build
    cmake -D WITH_CUDA=ON -D OPENCV_DNN_CUDA=ON ..
    make -j8
    sudo make install

Windows 系统

  1. 安装 Visual Studio 2019+ 和 CMake
  2. 下载预编译的 CUDA 和 cuDNN
  3. 使用 CMake-GUI 配置 OpenCV 时勾选 WITH_CUDAOPENCV_DNN_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_thresh=0.5, 
    float iou_thresh=0.4
) {
    std::vector<Detection> detections;

    // 解析模型输出(YOLOv5 格式示例)const float* data = (float*)output.data;
    for (int i = 0; i < output.rows; ++i) {float confidence = data[4];
        if (confidence > conf_thresh) {
            // 解析类别和边界框...
            detections.emplace_back(class_id, confidence, box);
        }
        data += output.cols;
    }

    // NMS 处理
    std::vector<int> indices;
    cv::dnn::NMSBoxes(boxes, confidences, conf_thresh, iou_thresh, indices);

    // 返回过滤后的结果
    std::vector<Detection> final_detections;
    for (int idx : indices) {final_detections.push_back(detections[idx]);
    }
    return final_detections;
}

代码规范

CMake 配置示例

cmake_minimum_required(VERSION 3.12)
project(YOLO_CPP)

find_package(OpenCV REQUIRED)

add_executable(yolo_demo
    src/main.cpp
    src/utils.cpp
)

target_link_libraries(yolo_demo PRIVATE
    ${OpenCV_LIBS}
)

# CUDA 支持
if(CUDA_FOUND)
    target_compile_options(yolo_demo PRIVATE
        $<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
    )
endif()

RAII 资源管理示例

class NetWrapper {
public:
    NetWrapper(const std::string& model_path) {net = cv::dnn::readNet(model_path);
        if (net.empty()) {throw std::runtime_error("Failed to load model");
        }
    }

    ~NetWrapper() {// OpenCV Net 对象会自动释放}

private:
    cv::dnn::Net net;
};

性能优化

精度 / 速度对比

模型类型 推理精度 FPS (RTX 3060) 显存占用
FP32 45 2.1GB
FP16 68 1.4GB
INT8 92 0.9GB

多线程预处理

void parallel_preprocess(
    const std::vector<cv::Mat>& images,
    std::vector<cv::Mat>& blobs,
    int num_threads=4
) {blobs.resize(images.size());

    #pragma omp parallel for num_threads(num_threads)
    for (size_t i = 0; i < images.size(); ++i) {blobs[i] = cv::dnn::blobFromImage(images[i], ...);
    }
}

避坑指南

  1. 版本兼容性:OpenCV 4.5+ 才支持 CUDA 加速的 DNN 模块
  2. 模型输出解析:不同 YOLO 版本输出格式不同,需查看官方文档
  3. 跨平台问题 :Windows 下路径使用\\/,建议使用 C ++17 的filesystem

总结与思考

通过本文,我们实现了:

  • 完整的 C ++ YOLO 部署流程
  • 工业级性能优化技巧
  • 健壮的异常处理机制

思考题:如何实现动态 batch 处理?可以考虑:

  1. 使用 std::vector<cv::Mat> 存储多个帧
  2. 实现自动 batch 大小调整算法
  3. 设计流水线处理架构
正文完
 0
评论(没有评论)