From 8dcbfb5535826a264403dffc524b812ca2924f40 Mon Sep 17 00:00:00 2001 From: Admin Date: Fri, 17 Jul 2026 08:54:23 +0000 Subject: [PATCH] fix: handle YOLO11 output format [1,5,8400] with transpose for OpenCV DNN --- pkg/opencv/opencv.cpp | 55 +++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/pkg/opencv/opencv.cpp b/pkg/opencv/opencv.cpp index 873f065..2ed5800 100644 --- a/pkg/opencv/opencv.cpp +++ b/pkg/opencv/opencv.cpp @@ -165,24 +165,55 @@ int cv_yolo_detect(const char* name, const unsigned char* img_data, int width, i float scaleY = (float)frame.rows / inpHeight; for (size_t i = 0; i < outs.size(); ++i) { - float* data = (float*)outs[i].data; - for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) { - Mat scores = outs[i].row(j).colRange(5, outs[i].cols); - Point classIdPoint; - double confidence; - minMaxLoc(scores, 0, &confidence, 0, &classIdPoint); + // YOLO11 输出格式: [1, 5+num_classes, 8400] (通道在前) + // 需要转置为 [8400, 5+num_classes] + Mat out = outs[i]; + int num_detections = out.size[2]; // 8400 + int num_features = out.size[1]; // 5 + num_classes + + // 转置输出 + Mat out_transposed; + if (out.size[1] < out.size[2]) { + // [1, features, detections] -> [detections, features] + Mat out_2d(out.size[1], out.size[2], CV_32F, out.data); + transpose(out_2d, out_transposed); + } else { + out_transposed = out; + } + + for (int j = 0; j < num_detections; ++j) { + float* data = out_transposed.ptr(j); + + float obj_conf = data[4]; + if (obj_conf < detector->confThreshold) continue; + + // 找最大类别分数 + int classId = 0; + float maxScore = 0; + for (int k = 5; k < num_features; ++k) { + if (data[k] > maxScore) { + maxScore = data[k]; + classId = k - 5; + } + } + float confidence = obj_conf * maxScore; if (confidence > detector->confThreshold) { - int centerX = (int)(data[0] * scaleX); - int centerY = (int)(data[1] * scaleY); - int width = (int)(data[2] * scaleX); - int height = (int)(data[3] * scaleY); + float cx = data[0]; + float cy = data[1]; + float w = data[2]; + float h = data[3]; + + int centerX = (int)(cx * scaleX); + int centerY = (int)(cy * scaleY); + int width = (int)(w * scaleX); + int height = (int)(h * scaleY); int left = centerX - width / 2; int top = centerY - height / 2; - classIds.push_back(classIdPoint.x); - confidences.push_back((float)confidence); + classIds.push_back(classId); + confidences.push_back(confidence); boxes.push_back(Rect(left, top, width, height)); } }