先说原因:维度错乱
-
正确解析输出维度:确认输出张量的形状是[1, 84, 8400],其中84是每个锚点的参数,8400是锚点数量。因此,signalResultNum应为84,strideNum为8400。
-
数据转置:由于OpenCV的cv::Mat是按行优先存储的,而模型输出可能按通道优先排列,因此需要转置数据,使得每行对应一个锚点的所有参数。
// 原始输出维度应为[1,84,8400] nvinfer1::Dims output_dims = output_bindings[0].dims; const int num_classes = output_dims.d[1] - 4; // 80 const int num_anchors = output_dims.d[2]; // 8400 // 正确创建数据矩阵(行列转置) cv::Mat output_mat(num_classes + 4, num_anchors, CV_32F, output_data); cv::Mat transposed_mat; cv::transpose(output_mat, transposed_mat); // 转换为[8400,84]
如果你用的是YOLO的官方代码:位置原代码inference.cpp第224行,后处理部分
int strideNum = outputNodeDims[1];//8400
int signalResultNum = outputNodeDims[2];//84
std::vector<int> class_ids;
std::vector<float> confidences;
std::vector<cv::Rect> boxes;
cv::Mat rawData;
if (modelType == YOLO_DETECT_V8)
{
// FP32
rawData = cv::Mat(strideNum, signalResultNum, CV_32F, output);
}
else
{
// FP16
rawData = cv::Mat(strideNum, signalResultNum, CV_16F, output);
rawData.convertTo(rawData, CV_32F);
}
float* data = (float*)rawData.data;
修改为
int strideNum = outputNodeDims[2];//8400 int signalResultNum = outputNodeDims[1];//84 std::vector<int> class_ids; std::vector<float> confidences; std::vector<cv::Rect> boxes; cv::Mat rawData; cv::Mat transposed_output; if (modelType == YOLO_DETECT_V8) { // FP32 //rawData = cv::Mat(strideNum, signalResultNum, CV_32F, output); rawData = cv::Mat(signalResultNum, strideNum, CV_32F, output); cv::transpose(rawData, transposed_output); } else { // FP16 rawData = cv::Mat(signalResultNum, strideNum, CV_16F, output); rawData.convertTo(rawData, CV_32F); cv::transpose(rawData, transposed_output); } //float* data = (float*)rawData.data; float* data = (float*)transposed_output.data;
网上抄录的野路子代码,可以把原因告诉deepseek,让他修改代码。