yolo数据流传输可能有问题,导致帧率极低

:rocket: C++ 迁移方案

用 C++ 重写可以进一步减少 10-20ms 的 Python 开销,尤其是后处理部分。


:bar_chart: 性能对比

实现方式 后处理耗时 总 FPS 难度
Python V2 (320×320) 15-25ms 40-60 :star:
C++ 原生 5-10ms 60-80 :star::star::star:
C++ + 解析器 3-5ms 70-90 :star::star:

:hammer_and_wrench: 两条 C++ 路径

方案 A:使用 hobot_dnn C++ API(推荐,简单)

// 核心代码框架
#include "hobot_dnn/hobot_dnn.h"
#include <opencv2/opencv.hpp>

int main() {
    // 1. 加载模型(自动使用 ultralytics_yolo 解析器)
    hobot::dnn::Model model;
    model.Load("/home/sunrise/yolov5_best_quant(320).bin", 
               {{"parser", "ultralytics_yolo"}});
    
    // 2. 摄像头
    cv::VideoCapture cap(0);
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
    
    // 3. 推理循环
    while (true) {
        cv::Mat frame;
        cap.read(frame);
        
        // BGR → NV12
        cv::Mat nv12;
        cv::cvtColor(frame, nv12, cv::COLOR_BGR2NV12);
        
        // 推理(解析器自动处理 DFL+NMS)
        auto outputs = model.Forward({nv12});
        
        // 直接获取解析后的检测结果
        auto dets = outputs.GetDetections();
        
        // 绘制 + 显示
        for (auto& det : dets) {
            cv::rectangle(frame, det.bbox, cv::Scalar(0, 255, 0), 2);
        }
        cv::imshow("YOLO", frame);
        if (cv::waitKey(1) == 'q') break;
    }
}

方案 B:参考社区 C++ 示例(完整实现)

官方 Model Zoo C++ 示例

# 1. 克隆示例代码
git clone https://github.com/D-Robotics/rdk_model_zoo.git
cd rdk_model_zoo/samples/vision/ultralytics_yolo/cpp

# 2. 修改配置文件
# 编辑 config/yolo_seg_320.json
{
    "model_file": "/home/sunrise/yolov5_best_quant(320).bin",
    "dnn_parser": "ultralytics_yolo",
    "reg_max": 16,
    "class_num": 6,
    "score_threshold": 0.25,
    "nms_threshold": 0.30
}

# 3. 编译
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
make -j4

# 4. 运行
./yolo_seg_example --config ../config/yolo_seg_320.json --camera 0

:clipboard: 完整 C++ 示例(自包含版)

// yolo_seg_cpp.cpp
#include <iostream>
#include <vector>
#include <chrono>
#include <opencv2/opencv.hpp>
#include <hobot_dnn/hobot_dnn.h>

struct Detection {
    int cls;
    float conf;
    cv::Rect bbox;
    cv::Mat mask;  // 可选
};

class YoloSeg {
public:
    YoloSeg(const std::string& model_path) {
        model_.Load(model_path, {{"parser", "ultralytics_yolo"}});
    }
    
    std::vector<Detection> Detect(const cv::Mat& frame) {
        // BGR → NV12
        cv::Mat nv12;
        cv::cvtColor(frame, nv12, cv::COLOR_BGR2NV12);
        
        // 推理
        auto start = std::chrono::high_resolution_clock::now();
        auto outputs = model_.Forward({nv12});
        auto end = std::chrono::high_resolution_clock::now();
        
        std::cout << "BPU: " 
                  << std::chrono::duration<double, std::milli>(end - start).count()
                  << "ms" << std::endl;
        
        // 解析结果(根据实际输出格式调整)
        std::vector<Detection> dets;
        // TODO: 解析 outputs 中的 boxes/scores/classes
        return dets;
    }
    
private:
    hobot::dnn::Model model_;
};

int main() {
    YoloSeg detector("/home/sunrise/yolov5_best_quant(320).bin");
    
    cv::VideoCapture cap(0);
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
    cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
    cap.set(cv::CAP_PROP_BUFFERSIZE, 1);
    
    int fps_count = 0;
    auto fps_t0 = std::chrono::high_resolution_clock::now();
    
    while (true) {
        cv::Mat frame;
        cap.read(frame);
        if (frame.empty()) continue;
        
        auto dets = detector.Detect(frame);
        
        // 绘制
        for (auto& det : dets) {
            cv::rectangle(frame, det.bbox, cv::Scalar(0, 255, 0), 2);
            cv::putText(frame, std::to_string(det.conf), 
                       {det.bbox.x, det.bbox.y - 5},
                       cv::FONT_HERSHEY_SIMPLEX, 0.5, {0, 255, 0}, 1);
        }
        
        // FPS 统计
        fps_count++;
        if (fps_count >= 30) {
            auto now = std::chrono::high_resolution_clock::now();
            double fps = 30.0 / std::chrono::duration<double>(now - fps_t0).count();
            std::cout << "FPS: " << fps << std::endl;
            fps_count = 0;
            fps_t0 = now;
        }
        
        cv::imshow("YOLO", frame);
        if (cv::waitKey(1) == 'q') break;
    }
    
    return 0;
}

:wrench: 编译步骤

# 1. 创建项目目录
mkdir yolo_cpp && cd yolo_cpp

# 2. 创建 CMakeLists.txt
cat > CMakeLists.txt << 'EOF'
cmake_minimum_required(VERSION 3.10)
project(yolo_seg_cpp)

set(CMAKE_CXX_STANDARD 14)

find_package(OpenCV REQUIRED)
find_package(hobot_dnn REQUIRED)

add_executable(yolo_seg_cpp yolo_seg_cpp.cpp)
target_link_libraries(yolo_seg_cpp 
    ${OpenCV_LIBS} 
    hobot_dnn
)
EOF

# 3. 编译
mkdir build && cd build
cmake ..
make -j4

# 4. 运行
./yolo_seg_cpp

:books: 参考资源


:white_check_mark: 建议

你的情况 推荐方案
Python FPS ≥ 45 先用着,没必要换 C++
Python FPS 30-45 试试 C++ + 解析器
Python FPS < 30 先排查量化配置,再考虑 C++

先跑完 Python V2 的分层计时,把输出发出来,我帮你判断是否值得换 C++!:rocket: