mirror of
https://github.com/sipeed/MaixCDK.git
synced 2026-11-09 17:04:38 -06:00
* fix detect 4 class issue of yolo26
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
#include "maix_nn_F.hpp"
|
#include "maix_nn_F.hpp"
|
||||||
#include "maix_nn_object.hpp"
|
#include "maix_nn_object.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
// Platform-specific optimization
|
// Platform-specific optimization
|
||||||
#if PLATFORM_MAIXCAM2
|
#if PLATFORM_MAIXCAM2
|
||||||
@@ -261,16 +262,30 @@ namespace maix::nn
|
|||||||
std::vector<nn::LayerInfo> outputs = _model->outputs_info();
|
std::vector<nn::LayerInfo> outputs = _model->outputs_info();
|
||||||
err::check_bool_raise(outputs.size() >= 6, "need at least 6 outputs");
|
err::check_bool_raise(outputs.size() >= 6, "need at least 6 outputs");
|
||||||
|
|
||||||
struct OutputInfo { std::string name; int h, w, c; };
|
struct OutputInfo { std::string name; int h, w, c; int idx; };
|
||||||
std::vector<OutputInfo> bbox_outputs, cls_outputs;
|
std::vector<OutputInfo> parsed_outputs, bbox_outputs, cls_outputs;
|
||||||
|
|
||||||
|
auto has_token = [](const std::string &name, std::initializer_list<const char *> tokens) {
|
||||||
|
std::string lower = name;
|
||||||
|
std::transform(lower.begin(), lower.end(), lower.begin(),
|
||||||
|
[](unsigned char ch) { return std::tolower(ch); });
|
||||||
|
for (const char *token : tokens)
|
||||||
|
{
|
||||||
|
if (lower.find(token) != std::string::npos)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
// Classify outputs by channel count
|
// Classify outputs by channel count
|
||||||
for (const auto &output : outputs)
|
for (size_t output_idx = 0; output_idx < outputs.size(); ++output_idx)
|
||||||
{
|
{
|
||||||
|
const auto &output = outputs[output_idx];
|
||||||
if (output.shape.size() != 4) continue;
|
if (output.shape.size() != 4) continue;
|
||||||
|
|
||||||
OutputInfo info;
|
OutputInfo info;
|
||||||
info.name = output.name;
|
info.name = output.name;
|
||||||
|
info.idx = output_idx;
|
||||||
|
|
||||||
#if PLATFORM_MAIXCAM2
|
#if PLATFORM_MAIXCAM2
|
||||||
// MaixCAM2: Always NHWC format
|
// MaixCAM2: Always NHWC format
|
||||||
@@ -315,10 +330,64 @@ namespace maix::nn
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (info.c == 4)
|
if (info.c == 4 || info.c == (int)labels.size() || info.c == 80)
|
||||||
bbox_outputs.push_back(info);
|
parsed_outputs.push_back(info);
|
||||||
else if (info.c == (int)labels.size() || info.c == 80)
|
}
|
||||||
cls_outputs.push_back(info);
|
|
||||||
|
std::sort(parsed_outputs.begin(), parsed_outputs.end(), [](const OutputInfo &a, const OutputInfo &b) {
|
||||||
|
if (a.h != b.h) return a.h > b.h;
|
||||||
|
if (a.w != b.w) return a.w > b.w;
|
||||||
|
return a.idx < b.idx;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (size_t i = 0; i < parsed_outputs.size();)
|
||||||
|
{
|
||||||
|
std::vector<OutputInfo> group;
|
||||||
|
const int h = parsed_outputs[i].h;
|
||||||
|
const int w = parsed_outputs[i].w;
|
||||||
|
while (i < parsed_outputs.size() && parsed_outputs[i].h == h && parsed_outputs[i].w == w)
|
||||||
|
{
|
||||||
|
group.push_back(parsed_outputs[i]);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.size() != 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int bbox_idx = -1;
|
||||||
|
int cls_idx = -1;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < group.size(); ++j)
|
||||||
|
{
|
||||||
|
if (has_token(group[j].name, {"bbox", "box", "reg", "loc"}))
|
||||||
|
bbox_idx = j;
|
||||||
|
if (has_token(group[j].name, {"cls", "class", "score"}))
|
||||||
|
cls_idx = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bbox_idx < 0 || cls_idx < 0 || bbox_idx == cls_idx)
|
||||||
|
{
|
||||||
|
if (group[0].c == 4 && group[1].c != 4)
|
||||||
|
{
|
||||||
|
bbox_idx = 0;
|
||||||
|
cls_idx = 1;
|
||||||
|
}
|
||||||
|
else if (group[1].c == 4 && group[0].c != 4)
|
||||||
|
{
|
||||||
|
bbox_idx = 1;
|
||||||
|
cls_idx = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// When num_classes == 4, bbox/cls both have 4 channels.
|
||||||
|
// Fall back to stable output order within the same grid.
|
||||||
|
bbox_idx = 0;
|
||||||
|
cls_idx = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bbox_outputs.push_back(group[bbox_idx]);
|
||||||
|
cls_outputs.push_back(group[cls_idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
err::check_bool_raise(bbox_outputs.size() == 3 && cls_outputs.size() == 3,
|
err::check_bool_raise(bbox_outputs.size() == 3 && cls_outputs.size() == 3,
|
||||||
@@ -550,7 +619,7 @@ namespace maix::nn
|
|||||||
int ay = i / fw;
|
int ay = i / fw;
|
||||||
|
|
||||||
// Get class scores (handle NCHW vs NHWC)
|
// Get class scores (handle NCHW vs NHWC)
|
||||||
float class_scores[80];
|
std::vector<float> class_scores(num_class);
|
||||||
const float *c;
|
const float *c;
|
||||||
|
|
||||||
if (_is_nchw)
|
if (_is_nchw)
|
||||||
@@ -559,7 +628,7 @@ namespace maix::nn
|
|||||||
{
|
{
|
||||||
class_scores[j] = cls[j * fh * fw + ay * fw + ax];
|
class_scores[j] = cls[j * fh * fw + ay * fw + ax];
|
||||||
}
|
}
|
||||||
c = class_scores;
|
c = class_scores.data();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -861,4 +930,4 @@ namespace maix::nn
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace maix::nn
|
} // namespace maix::nn
|
||||||
|
|||||||
Reference in New Issue
Block a user