Configurable side-view shoe ratio

This commit is contained in:
tian 2026-04-14 14:38:08 +08:00
parent ddc99dc2a8
commit d33cd152fa
4 changed files with 95 additions and 39 deletions

View File

@ -238,6 +238,7 @@
"max_shoe_roi_area_ratio": 0.25, "max_shoe_roi_area_ratio": 0.25,
"min_front_shoe_width_ratio": 0.18, "min_front_shoe_width_ratio": 0.18,
"max_front_shoe_aspect_ratio": 1.5, "max_front_shoe_aspect_ratio": 1.5,
"max_side_height_width_ratio": 1.1,
"max_shoe_aspect_ratio": 2.0 "max_shoe_aspect_ratio": 2.0
} }
}, },

View File

@ -35,6 +35,7 @@ struct PersonShoeCheckConfig {
float max_shoe_roi_area_ratio = 0.25f; float max_shoe_roi_area_ratio = 0.25f;
float min_front_shoe_width_ratio = 0.18f; float min_front_shoe_width_ratio = 0.18f;
float max_front_shoe_aspect_ratio = 1.5f; float max_front_shoe_aspect_ratio = 1.5f;
float max_side_height_width_ratio = 1.1f;
float max_shoe_aspect_ratio = 2.0f; float max_shoe_aspect_ratio = 2.0f;
float match_iou = 0.02f; float match_iou = 0.02f;
float x_offset = -0.20f; float x_offset = -0.20f;
@ -156,6 +157,7 @@ private:
float max_shoe_roi_area_ratio, float max_shoe_roi_area_ratio,
float min_front_shoe_width_ratio, float min_front_shoe_width_ratio,
float max_front_shoe_aspect_ratio, float max_front_shoe_aspect_ratio,
float max_side_height_width_ratio,
float max_shoe_aspect_ratio) { float max_shoe_aspect_ratio) {
ShoeGeomMetrics m; ShoeGeomMetrics m;
const float person_w = std::max(1.0f, person_bbox.w); const float person_w = std::max(1.0f, person_bbox.w);
@ -181,6 +183,7 @@ private:
PersonShoeShapeConfig{ PersonShoeShapeConfig{
min_front_shoe_width_ratio, min_front_shoe_width_ratio,
max_front_shoe_aspect_ratio, max_front_shoe_aspect_ratio,
max_side_height_width_ratio,
}); });
m.aspect_ratio = shape_metrics.aspect_ratio; m.aspect_ratio = shape_metrics.aspect_ratio;
m.is_front_view = shape_metrics.is_front_view; m.is_front_view = shape_metrics.is_front_view;
@ -263,6 +266,8 @@ private:
"min_front_shoe_width_ratio", config.person_shoe.min_front_shoe_width_ratio); "min_front_shoe_width_ratio", config.person_shoe.min_front_shoe_width_ratio);
config.person_shoe.max_front_shoe_aspect_ratio = ps->ValueOr<float>( config.person_shoe.max_front_shoe_aspect_ratio = ps->ValueOr<float>(
"max_front_shoe_aspect_ratio", config.person_shoe.max_front_shoe_aspect_ratio); "max_front_shoe_aspect_ratio", config.person_shoe.max_front_shoe_aspect_ratio);
config.person_shoe.max_side_height_width_ratio = ps->ValueOr<float>(
"max_side_height_width_ratio", config.person_shoe.max_side_height_width_ratio);
config.person_shoe.max_shoe_aspect_ratio = ps->ValueOr<float>( config.person_shoe.max_shoe_aspect_ratio = ps->ValueOr<float>(
"max_shoe_aspect_ratio", config.person_shoe.max_shoe_aspect_ratio); "max_shoe_aspect_ratio", config.person_shoe.max_shoe_aspect_ratio);
if (const SimpleJson* fr = ps->Find("foot_region"); fr && fr->IsObject()) { if (const SimpleJson* fr = ps->Find("foot_region"); fr && fr->IsObject()) {
@ -379,6 +384,7 @@ private:
config_.person_shoe.max_shoe_roi_area_ratio, config_.person_shoe.max_shoe_roi_area_ratio,
config_.person_shoe.min_front_shoe_width_ratio, config_.person_shoe.min_front_shoe_width_ratio,
config_.person_shoe.max_front_shoe_aspect_ratio, config_.person_shoe.max_front_shoe_aspect_ratio,
config_.person_shoe.max_side_height_width_ratio,
config_.person_shoe.max_shoe_aspect_ratio); config_.person_shoe.max_shoe_aspect_ratio);
const bool size_preferred = !config_.person_shoe.enable_size_preferred || const bool size_preferred = !config_.person_shoe.enable_size_preferred ||
(metrics.person_gate && metrics.roi_gate && metrics.shape_gate); (metrics.person_gate && metrics.roi_gate && metrics.shape_gate);

View File

@ -7,7 +7,7 @@ namespace rk3588 {
struct PersonShoeShapeConfig { struct PersonShoeShapeConfig {
float min_front_shoe_width_ratio = 0.18f; float min_front_shoe_width_ratio = 0.18f;
float max_front_aspect_ratio = 1.5f; float max_front_aspect_ratio = 1.5f;
float max_side_height_width_ratio = 0.8f; float max_side_height_width_ratio = 1.1f;
}; };
struct PersonShoeShapeMetrics { struct PersonShoeShapeMetrics {

View File

@ -1,75 +1,124 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include "../plugins/logic_gate/person_shoe_shape.h" #include "../plugins/logic_gate/person_shoe_shape.h"
#include "utils/simple_json.h"
namespace rk3588 { namespace rk3588 {
namespace { namespace {
TEST(PersonShoeShapeTest, RejectsTallSideViewBoxes) { PersonShoeShapeConfig LoadShapeConfig() {
PersonShoeShapeConfig config; std::ifstream file("configs/full_pipeline_1080p_test_alarm.json");
config.min_front_shoe_width_ratio = 0.18f; if (!file.is_open()) {
config.max_front_aspect_ratio = 1.5f; throw std::runtime_error("failed to open configs/full_pipeline_1080p_test_alarm.json");
config.max_side_height_width_ratio = 0.8f; }
const auto metrics = EvaluatePersonShoeShape(20.0f, 33.0f, 100.0f, config); std::ostringstream buffer;
buffer << file.rdbuf();
SimpleJson root;
std::string err;
if (!ParseSimpleJson(buffer.str(), root, err)) {
throw std::runtime_error("failed to parse configs/full_pipeline_1080p_test_alarm.json: " + err);
}
const auto& graphs = root.Find("graphs")->AsArray();
const auto& nodes = graphs.at(0).Find("nodes")->AsArray();
for (const auto& node : nodes) {
if (node.ValueOr<std::string>("id", "") != "shoe_assoc") continue;
const SimpleJson* ps = node.Find("person_shoe_check");
if (!ps || !ps->IsObject()) break;
PersonShoeShapeConfig config;
config.min_front_shoe_width_ratio =
ps->ValueOr<float>("min_front_shoe_width_ratio", config.min_front_shoe_width_ratio);
config.max_front_aspect_ratio =
ps->ValueOr<float>("max_front_shoe_aspect_ratio", config.max_front_aspect_ratio);
config.max_side_height_width_ratio =
ps->ValueOr<float>("max_side_height_width_ratio", config.max_side_height_width_ratio);
return config;
}
throw std::runtime_error("failed to find shoe_assoc.person_shoe_check config");
}
TEST(PersonShoeShapeTest, RejectsSideViewBoxesBeyondConfiguredRatio) {
const auto config = LoadShapeConfig();
const float shoe_w = 20.0f;
const float shoe_h = shoe_w * (config.max_side_height_width_ratio + 0.25f);
const float person_w = shoe_w / (config.min_front_shoe_width_ratio + 0.02f);
const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_FALSE(metrics.is_front_view); EXPECT_FALSE(metrics.is_front_view);
EXPECT_FALSE(metrics.shape_gate); EXPECT_FALSE(metrics.shape_gate);
EXPECT_FLOAT_EQ(metrics.person_width_ratio, 0.2f); EXPECT_GT(metrics.person_width_ratio, config.min_front_shoe_width_ratio);
EXPECT_FLOAT_EQ(metrics.aspect_ratio, 1.65f); EXPECT_GT(metrics.aspect_ratio, config.max_side_height_width_ratio);
} }
TEST(PersonShoeShapeTest, AllowsSlightlyTallFrontViewBoxes) { TEST(PersonShoeShapeTest, AllowsFrontViewBoxesAtConfiguredAspectLimit) {
PersonShoeShapeConfig config; const auto config = LoadShapeConfig();
config.min_front_shoe_width_ratio = 0.18f; const float shoe_w = 16.0f;
config.max_front_aspect_ratio = 1.5f; const float shoe_h = shoe_w * config.max_front_aspect_ratio;
config.max_side_height_width_ratio = 0.8f; const float person_w = shoe_w / (config.min_front_shoe_width_ratio - 0.02f);
const auto metrics = EvaluatePersonShoeShape(16.0f, 24.0f, 100.0f, config); const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_TRUE(metrics.is_front_view); EXPECT_TRUE(metrics.is_front_view);
EXPECT_TRUE(metrics.shape_gate); EXPECT_TRUE(metrics.shape_gate);
EXPECT_FLOAT_EQ(metrics.person_width_ratio, 0.16f); EXPECT_LT(metrics.person_width_ratio, config.min_front_shoe_width_ratio);
EXPECT_FLOAT_EQ(metrics.aspect_ratio, 1.5f); EXPECT_FLOAT_EQ(metrics.aspect_ratio, config.max_front_aspect_ratio);
} }
TEST(PersonShoeShapeTest, RejectsFrontViewBoxesBeyondAllowedAspect) { TEST(PersonShoeShapeTest, RejectsFrontViewBoxesBeyondConfiguredAspect) {
PersonShoeShapeConfig config; const auto config = LoadShapeConfig();
config.min_front_shoe_width_ratio = 0.18f; const float shoe_w = 16.0f;
config.max_front_aspect_ratio = 1.5f; const float shoe_h = shoe_w * (config.max_front_aspect_ratio + 0.1f);
config.max_side_height_width_ratio = 0.8f; const float person_w = shoe_w / (config.min_front_shoe_width_ratio - 0.02f);
const auto metrics = EvaluatePersonShoeShape(16.0f, 25.0f, 100.0f, config); const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_TRUE(metrics.is_front_view); EXPECT_TRUE(metrics.is_front_view);
EXPECT_FALSE(metrics.shape_gate); EXPECT_FALSE(metrics.shape_gate);
EXPECT_FLOAT_EQ(metrics.aspect_ratio, 1.5625f); EXPECT_GT(metrics.aspect_ratio, config.max_front_aspect_ratio);
} }
TEST(PersonShoeShapeTest, AllowsWideSideViewBoxes) { TEST(PersonShoeShapeTest, AllowsSideViewBoxesWithinConfiguredRatio) {
PersonShoeShapeConfig config; const auto config = LoadShapeConfig();
config.min_front_shoe_width_ratio = 0.18f; const float shoe_w = 40.0f;
config.max_front_aspect_ratio = 1.5f; const float shoe_h = shoe_w * (config.max_side_height_width_ratio - 0.1f);
config.max_side_height_width_ratio = 0.8f; const float person_w = shoe_w / (config.min_front_shoe_width_ratio + 0.05f);
const auto metrics = EvaluatePersonShoeShape(40.0f, 24.0f, 100.0f, config); const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_FALSE(metrics.is_front_view); EXPECT_FALSE(metrics.is_front_view);
EXPECT_TRUE(metrics.shape_gate); EXPECT_TRUE(metrics.shape_gate);
EXPECT_FLOAT_EQ(metrics.aspect_ratio, 0.6f); EXPECT_GT(metrics.person_width_ratio, config.min_front_shoe_width_ratio);
EXPECT_LT(metrics.aspect_ratio, config.max_side_height_width_ratio);
} }
TEST(PersonShoeShapeTest, RejectsNearSquareSideViewBoxes) { TEST(PersonShoeShapeTest, AllowsNearSquareSideViewBoxesWhenConfigPermits) {
PersonShoeShapeConfig config; const auto config = LoadShapeConfig();
config.min_front_shoe_width_ratio = 0.18f; const float shoe_w = 40.0f;
config.max_front_aspect_ratio = 1.5f; const float shoe_h = shoe_w * (config.max_side_height_width_ratio - 0.05f);
config.max_side_height_width_ratio = 0.8f; const float person_w = shoe_w / (config.min_front_shoe_width_ratio + 0.04f);
const auto metrics = EvaluatePersonShoeShape(40.0f, 33.0f, 100.0f, config); const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_FALSE(metrics.is_front_view); EXPECT_FALSE(metrics.is_front_view);
EXPECT_FALSE(metrics.shape_gate); EXPECT_TRUE(metrics.shape_gate);
EXPECT_FLOAT_EQ(metrics.aspect_ratio, 0.825f); EXPECT_LT(metrics.aspect_ratio, config.max_side_height_width_ratio);
}
TEST(PersonShoeShapeTest, ReadsCurrentThresholdsFromRuntimeConfig) {
PersonShoeShapeConfig config;
ASSERT_NO_THROW(config = LoadShapeConfig());
EXPECT_GT(config.min_front_shoe_width_ratio, 0.0f);
EXPECT_GT(config.max_front_aspect_ratio, 1.0f);
EXPECT_GT(config.max_side_height_width_ratio, 0.0f);
} }
} // namespace } // namespace