ONNXRuntime C++如何获取动态输出Tensor的真实形状?
问题描述
我正在使用ONNXRuntime C++运行YOLOX模型,代码如下:
std::vector<Ort::Value> ort_inputs; for (int i = 0; i < inputNames.size(); ++i) { ort_inputs.emplace_back(Ort::Value::CreateTensor<float>( memoryInfo, static_cast<float *>(inputs[i].data), inputs[i].get_size(), inputShapes[i].data(), inputShapes[i].size())); } std::vector<Ort::Value> outputTensors = session.Run(Ort::RunOptions{nullptr}, inputNames.data(), ort_inputs.data(), 1, outputNames.data(), outputNames.size());
模型为yolox_tiny_cpunms.onnx,输入输出详情如下:
| Name | Shape | Input/Output | Dtype |
|---|---|---|---|
| input | [1, 3, 416, 416] | Input | float32 |
| boxes | [1, -1, -1] | Output | float32 |
| scores | [1, -1] | Output | float32 |
| labels | [1, -1] | Output | int64 |
模型输出为动态形状,但当前代码得到的输出Tensor形状为[1, 0, 4]、[1, 0]、[1,0],请问如何在C++中获取正确的输出形状?
解决方法
出现[1,0,...]的形状通常说明模型推理后未检测到目标,或是输入预处理存在问题。若确认输入图像包含目标,可按以下步骤处理:
检查输入预处理是否符合YOLOX要求
- 输入图像需转为RGB格式,再按模型训练时的逻辑做归一化(如除以255,或
(img - mean)/std) - 输入尺寸必须为
416x416,需保持图像原始宽高比,建议用letterbox填充方式避免拉伸变形 - 确保输入数据内存布局为
NCHW(批量、通道、高度、宽度),这是ONNX模型的标准输入格式
- 输入图像需转为RGB格式,再按模型训练时的逻辑做归一化(如除以255,或
正确获取动态输出的实际形状
推理完成后,通过ONNXRuntime的API直接读取输出Tensor的实际形状:
// 遍历所有输出Tensor for (size_t i = 0; i < outputTensors.size(); ++i) { // 获取Tensor的类型与形状信息 auto tensor_info = outputTensors[i].GetTensorTypeAndShapeInfo(); // 提取实际形状 std::vector<int64_t> actual_output_shape = tensor_info.GetShape(); // 打印验证形状 std::cout << "Output " << outputNames[i] << " shape: "; for (auto dim : actual_output_shape) { std::cout << dim << " "; } std::cout << std::endl; // 按需获取输出数据指针 if (outputNames[i] == "boxes") { float* boxes_data = outputTensors[i].GetTensorMutableData<float>(); // 根据actual_output_shape处理检测框数据 } else if (outputNames[i] == "scores") { float* scores_data = outputTensors[i].GetTensorMutableData<float>(); } else if (outputNames[i] == "labels") { int64_t* labels_data = outputTensors[i].GetTensorMutableData<int64_t>(); } }
- 验证ONNXRuntime会话配置
- 创建Session时不要手动固定输出形状,默认配置已支持动态形状:
Ort::SessionOptions session_options; // 无需额外设置固定形状,保持默认即可 Ort::Session session(env, model_path.c_str(), session_options); - 若模型是带NMS的YOLOX导出版本,需确认导出时的置信度、NMS阈值参数是否合理,避免过滤掉所有目标
- 创建Session时不要手动固定输出形状,默认配置已支持动态形状:
内容的提问来源于stack exchange,提问作者Nicholas Jela
相关产品推荐
相关产品推荐

