fix: handle YOLO11 output format [1,5,8400] with transpose for OpenCV DNN
This commit is contained in:
+43
-12
@@ -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;
|
float scaleY = (float)frame.rows / inpHeight;
|
||||||
|
|
||||||
for (size_t i = 0; i < outs.size(); ++i) {
|
for (size_t i = 0; i < outs.size(); ++i) {
|
||||||
float* data = (float*)outs[i].data;
|
// YOLO11 输出格式: [1, 5+num_classes, 8400] (通道在前)
|
||||||
for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) {
|
// 需要转置为 [8400, 5+num_classes]
|
||||||
Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
|
Mat out = outs[i];
|
||||||
Point classIdPoint;
|
int num_detections = out.size[2]; // 8400
|
||||||
double confidence;
|
int num_features = out.size[1]; // 5 + num_classes
|
||||||
minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
|
|
||||||
|
// 转置输出
|
||||||
|
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) {
|
if (confidence > detector->confThreshold) {
|
||||||
int centerX = (int)(data[0] * scaleX);
|
float cx = data[0];
|
||||||
int centerY = (int)(data[1] * scaleY);
|
float cy = data[1];
|
||||||
int width = (int)(data[2] * scaleX);
|
float w = data[2];
|
||||||
int height = (int)(data[3] * scaleY);
|
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 left = centerX - width / 2;
|
||||||
int top = centerY - height / 2;
|
int top = centerY - height / 2;
|
||||||
|
|
||||||
classIds.push_back(classIdPoint.x);
|
classIds.push_back(classId);
|
||||||
confidences.push_back((float)confidence);
|
confidences.push_back(confidence);
|
||||||
boxes.push_back(Rect(left, top, width, height));
|
boxes.push_back(Rect(left, top, width, height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user