fix: handle YOLO11 output format [1,5,8400] with transpose for OpenCV DNN
Build and Deploy / build (push) Successful in 2m36s
Build and Deploy / deploy (push) Successful in 9s

This commit is contained in:
2026-07-17 08:54:23 +00:00
parent d9cc4b0be0
commit 8dcbfb5535
+43 -12
View File
@@ -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<float>(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));
}
}