You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yolov9 C++ CUDA推理时检测框坐标全为0的问题

Yolov9 C++ OpenCV CUDA推理检测框坐标全为0的解决方案

问题诊断

CPU推理正常但GPU下检测框坐标全为0,核心原因通常是:

  • ONNX模型算子与OpenCV CUDA后端不兼容
  • 直接访问GPU张量内存导致读取错误
  • 输入预处理或输出解析的维度/布局不匹配

具体解决步骤

1. 重新导出兼容的ONNX模型

导出时添加简化和指定兼容算子集,避免CUDA后端无法识别的算子:

python3 export.py --weights yolov9-s-converted.pt --imgsz 640 --include onnx --simplify --opset 12

未简化的模型可能包含冗余算子,CUDA后端处理时容易出现分支计算失效。

2. 修正GPU张量的内存访问

CUDA后端返回的张量数据存储在GPU上,直接读取指针会导致错误,需先拷贝到CPU再解析:

// 替换原有的输出解析代码
std::vector<cv::Mat> outputs;
net.forward(outputs, net.getUnconnectedOutLayersNames()); 
cv::Mat preds = outputs.at(0); 
cv::Mat det_output;

if (is_cuda) {
    cv::Mat preds_host;
    preds.copyTo(preds_host); // 将GPU张量拷贝到CPU内存
    det_output = cv::Mat(preds_host.size[1], preds_host.size[2], CV_32F, preds_host.ptr<float>()).t();
} else {
    det_output = cv::Mat(preds.size[1], preds.size[2], CV_32F, preds.ptr<float>()).t();
}

3. 对齐输入预处理参数

确保blobFromImage的参数与模型导出逻辑完全一致,明确指定均值并保持类型匹配:

cv::Mat blob;
cv::dnn::blobFromImage(input_image, blob, 1./255., cv::Size(640, 640), cv::Scalar(0,0,0), true, false, CV_32F);

4. 尝试FP16推理模式

部分版本的OpenCV CUDA后端对FP16模式的算子兼容性更好,修改目标设备设置:

if (is_cuda)
{
    std::cout << "Attempt to use CUDA\n";
    net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
    net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16); // 改用FP16
}

5. 简化输入预处理流程

避免手动创建padding图像,直接用blobFromImage自动处理,减少内存对齐问题:

// 删除手动padding的代码,直接使用原始图像
cv::Mat image = cv::imread(filename);
cv::Mat blob;
cv::dnn::blobFromImage(image, blob, 1./255., cv::Size(640, 640), cv::Scalar(0,0,0), true, false, CV_32F);

验证方法

修改后重新运行GPU推理,若坐标仍异常,用Netron工具查看ONNX模型输出维度,确认输出shape为[1, 84, 8400](Yolov9-s标准输出),确保解析时的行列对应正确。

内容的提问来源于stack exchange,提问作者Roebli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:43:20