修复人脸画框3
This commit is contained in:
parent
dd1f419406
commit
63f448c108
@ -36,11 +36,12 @@
|
||||
"role": "filter",
|
||||
"enable": true,
|
||||
"model_path": "./models/RetinaFace_mobile320.rknn",
|
||||
"conf": 0.6,
|
||||
"conf": 0.2,
|
||||
"nms": 0.4,
|
||||
"max_faces": 10,
|
||||
"output_landmarks": true,
|
||||
"input_format": "rgb"
|
||||
"input_format": "bgr",
|
||||
"face_class_index": -1
|
||||
},
|
||||
{
|
||||
"id": "osd_cam1",
|
||||
|
||||
@ -382,6 +382,10 @@ public:
|
||||
nms_thresh_ = config.ValueOr<float>("nms", 0.4f);
|
||||
max_faces_ = std::max(1, config.ValueOr<int>("max_faces", 10));
|
||||
output_landmarks_ = config.ValueOr<bool>("output_landmarks", true);
|
||||
face_class_index_ = config.ValueOr<int>("face_class_index", face_class_index_);
|
||||
if (face_class_index_ != 0 && face_class_index_ != 1) {
|
||||
face_class_index_ = -1; // auto
|
||||
}
|
||||
|
||||
const std::string fmt = config.ValueOr<std::string>("input_format", "rgb");
|
||||
input_format_ = fmt;
|
||||
@ -672,6 +676,35 @@ private:
|
||||
if (loc.n <= 0 || conf.n != loc.n) return;
|
||||
const int n = loc.n;
|
||||
|
||||
// Determine which class index represents "face".
|
||||
// Most RetinaFace uses [bg, face], i.e., face_idx=1, but some exports swap it.
|
||||
int face_idx = face_class_index_;
|
||||
float max_p0 = 0.0f;
|
||||
float max_p1 = 0.0f;
|
||||
if (face_idx < 0) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const float s0 = conf.data[static_cast<size_t>(i) * 2 + 0];
|
||||
const float s1 = conf.data[static_cast<size_t>(i) * 2 + 1];
|
||||
float p1;
|
||||
if (s0 >= 0.0f && s0 <= 1.0f && s1 >= 0.0f && s1 <= 1.0f && std::fabs((s0 + s1) - 1.0f) < 0.1f) {
|
||||
p1 = s1;
|
||||
} else {
|
||||
p1 = Softmax2(s0, s1);
|
||||
}
|
||||
const float p0 = 1.0f - p1;
|
||||
if (p0 > max_p0) max_p0 = p0;
|
||||
if (p1 > max_p1) max_p1 = p1;
|
||||
}
|
||||
face_idx = (max_p1 >= max_p0) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!logged_conf_probe_.exchange(true)) {
|
||||
LogInfo("[ai_face_det] conf probe: max_p0=" + std::to_string(max_p0) +
|
||||
" max_p1=" + std::to_string(max_p1) +
|
||||
" face_idx=" + std::to_string(face_idx) +
|
||||
(face_class_index_ < 0 ? " (auto)" : " (cfg)"));
|
||||
}
|
||||
|
||||
const std::vector<Prior> priors = GenerateRetinaFacePriors(in_w, in_h, steps_, min_sizes_);
|
||||
if (!priors.empty() && static_cast<int>(priors.size()) != n) {
|
||||
// Mismatch: can't reliably decode.
|
||||
@ -692,15 +725,18 @@ private:
|
||||
constexpr float var0 = 0.1f;
|
||||
constexpr float var1 = 0.2f;
|
||||
|
||||
float max_face_prob = 0.0f;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const float s0 = conf.data[static_cast<size_t>(i) * 2 + 0];
|
||||
const float s1 = conf.data[static_cast<size_t>(i) * 2 + 1];
|
||||
float score;
|
||||
float p1;
|
||||
if (s0 >= 0.0f && s0 <= 1.0f && s1 >= 0.0f && s1 <= 1.0f && std::fabs((s0 + s1) - 1.0f) < 0.1f) {
|
||||
score = s1;
|
||||
p1 = s1;
|
||||
} else {
|
||||
score = Softmax2(s0, s1);
|
||||
p1 = Softmax2(s0, s1);
|
||||
}
|
||||
const float score = (face_idx == 1) ? p1 : (1.0f - p1);
|
||||
if (score > max_face_prob) max_face_prob = score;
|
||||
if (score < conf_thresh_) continue;
|
||||
|
||||
const Prior p = priors.empty() ? Prior{0, 0, 0, 0} : priors[static_cast<size_t>(i)];
|
||||
@ -751,7 +787,13 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (boxes.empty()) return;
|
||||
if (boxes.empty()) {
|
||||
if (!logged_no_face_detail_.exchange(true)) {
|
||||
LogInfo("[ai_face_det] no face passed conf=" + std::to_string(conf_thresh_) +
|
||||
", max_face_prob=" + std::to_string(max_face_prob));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> keep;
|
||||
NmsSorted(boxes, scores, nms_thresh_, keep);
|
||||
@ -782,6 +824,7 @@ private:
|
||||
float nms_thresh_ = 0.4f;
|
||||
int max_faces_ = 10;
|
||||
bool output_landmarks_ = true;
|
||||
int face_class_index_ = -1; // -1=auto, 0/1=explicit
|
||||
|
||||
std::string input_format_ = "rgb";
|
||||
|
||||
@ -801,6 +844,8 @@ private:
|
||||
std::atomic<bool> logged_io_{false};
|
||||
std::atomic<bool> logged_decode_{false};
|
||||
std::atomic<bool> logged_decode_detail_{false};
|
||||
std::atomic<bool> logged_conf_probe_{false};
|
||||
std::atomic<bool> logged_no_face_detail_{false};
|
||||
};
|
||||
|
||||
REGISTER_NODE(AiFaceDetNode, "ai_face_det");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user