From ddc99dc2a8464a13c413722a28977499420bed52 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Tue, 14 Apr 2026 13:09:01 +0800 Subject: [PATCH] Tighten person-shoe shape filtering --- AGENTS.md | 6 ++ configs/full_pipeline_1080p_test_alarm.json | 2 + plugins/logic_gate/logic_gate_node.cpp | 26 ++++++- plugins/logic_gate/person_shoe_shape.h | 40 +++++++++++ tests/CMakeLists.txt | 1 + tests/test_person_shoe_shape.cpp | 76 +++++++++++++++++++++ 6 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 plugins/logic_gate/person_shoe_shape.h create mode 100644 tests/test_person_shoe_shape.cpp diff --git a/AGENTS.md b/AGENTS.md index d27edba..39e05c6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,12 @@ This repository is a plugin-based C++ video analytics system for RK3588. Develop - Do not distort production code to satisfy the local machine environment. - Do not remove or weaken RK3588-specific paths just because they are not runnable on the current workstation. +## Shell Environment Rules + +- For agent-run shell commands on this workstation, use PowerShell 7.6 instead of Windows PowerShell 5.1. +- Prefer explicit invocation via `C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.0.0_x64__8wekyb3d8bbwe\pwsh.exe` when running commands. +- Do not rely on the system-default `powershell.exe` resolving to the desired version. + ## Plugin and Architecture Rules - New analytics capabilities should be implemented as plugins when they represent pipeline nodes. diff --git a/configs/full_pipeline_1080p_test_alarm.json b/configs/full_pipeline_1080p_test_alarm.json index 2c42e5e..edcc991 100644 --- a/configs/full_pipeline_1080p_test_alarm.json +++ b/configs/full_pipeline_1080p_test_alarm.json @@ -236,6 +236,8 @@ "max_shoe_roi_width_ratio": 0.65, "max_shoe_roi_height_ratio": 0.6, "max_shoe_roi_area_ratio": 0.25, + "min_front_shoe_width_ratio": 0.18, + "max_front_shoe_aspect_ratio": 1.5, "max_shoe_aspect_ratio": 2.0 } }, diff --git a/plugins/logic_gate/logic_gate_node.cpp b/plugins/logic_gate/logic_gate_node.cpp index eae2b7a..afec5d9 100644 --- a/plugins/logic_gate/logic_gate_node.cpp +++ b/plugins/logic_gate/logic_gate_node.cpp @@ -6,6 +6,7 @@ #include #include "color_analyzer.h" +#include "person_shoe_shape.h" #include "frame/frame.h" #include "node.h" #include "utils/logger.h" @@ -32,6 +33,8 @@ struct PersonShoeCheckConfig { float max_shoe_roi_width_ratio = 0.65f; float max_shoe_roi_height_ratio = 0.60f; float max_shoe_roi_area_ratio = 0.25f; + float min_front_shoe_width_ratio = 0.18f; + float max_front_shoe_aspect_ratio = 1.5f; float max_shoe_aspect_ratio = 2.0f; float match_iou = 0.02f; float x_offset = -0.20f; @@ -61,6 +64,7 @@ struct ShoeGeomMetrics { float roi_height_ratio = 0.0f; float roi_area_ratio = 0.0f; float aspect_ratio = 0.0f; + bool is_front_view = false; bool person_gate = false; bool roi_gate = false; bool shape_gate = false; @@ -150,6 +154,8 @@ private: float max_shoe_roi_width_ratio, float max_shoe_roi_height_ratio, float max_shoe_roi_area_ratio, + float min_front_shoe_width_ratio, + float max_front_shoe_aspect_ratio, float max_shoe_aspect_ratio) { ShoeGeomMetrics m; const float person_w = std::max(1.0f, person_bbox.w); @@ -168,7 +174,16 @@ private: m.roi_width_ratio = shoe_w / roi_w; m.roi_height_ratio = shoe_h / roi_h; m.roi_area_ratio = shoe_area / roi_area; - m.aspect_ratio = shoe_h / shoe_w; + const PersonShoeShapeMetrics shape_metrics = EvaluatePersonShoeShape( + shoe_w, + shoe_h, + person_w, + PersonShoeShapeConfig{ + min_front_shoe_width_ratio, + max_front_shoe_aspect_ratio, + }); + m.aspect_ratio = shape_metrics.aspect_ratio; + m.is_front_view = shape_metrics.is_front_view; m.person_gate = m.person_height_ratio >= min_shoe_height_ratio && @@ -180,7 +195,7 @@ private: m.roi_width_ratio <= max_shoe_roi_width_ratio && m.roi_height_ratio <= max_shoe_roi_height_ratio && m.roi_area_ratio <= max_shoe_roi_area_ratio; - m.shape_gate = m.aspect_ratio <= max_shoe_aspect_ratio; + m.shape_gate = shape_metrics.shape_gate && m.aspect_ratio <= max_shoe_aspect_ratio; return m; } @@ -244,6 +259,10 @@ private: "max_shoe_roi_height_ratio", config.person_shoe.max_shoe_roi_height_ratio); config.person_shoe.max_shoe_roi_area_ratio = ps->ValueOr( "max_shoe_roi_area_ratio", config.person_shoe.max_shoe_roi_area_ratio); + config.person_shoe.min_front_shoe_width_ratio = ps->ValueOr( + "min_front_shoe_width_ratio", config.person_shoe.min_front_shoe_width_ratio); + config.person_shoe.max_front_shoe_aspect_ratio = ps->ValueOr( + "max_front_shoe_aspect_ratio", config.person_shoe.max_front_shoe_aspect_ratio); config.person_shoe.max_shoe_aspect_ratio = ps->ValueOr( "max_shoe_aspect_ratio", config.person_shoe.max_shoe_aspect_ratio); if (const SimpleJson* fr = ps->Find("foot_region"); fr && fr->IsObject()) { @@ -358,6 +377,8 @@ private: config_.person_shoe.max_shoe_roi_width_ratio, config_.person_shoe.max_shoe_roi_height_ratio, config_.person_shoe.max_shoe_roi_area_ratio, + config_.person_shoe.min_front_shoe_width_ratio, + config_.person_shoe.max_front_shoe_aspect_ratio, config_.person_shoe.max_shoe_aspect_ratio); const bool size_preferred = !config_.person_shoe.enable_size_preferred || (metrics.person_gate && metrics.roi_gate && metrics.shape_gate); @@ -383,6 +404,7 @@ private: ",h:" + std::to_string(metrics.roi_height_ratio) + ",a:" + std::to_string(metrics.roi_area_ratio) + ")" + " aspect=" + std::to_string(metrics.aspect_ratio) + + " front_view=" + std::string(metrics.is_front_view ? "true" : "false") + " gates=(person:" + std::string(metrics.person_gate ? "true" : "false") + ",roi:" + std::string(metrics.roi_gate ? "true" : "false") + ",shape:" + std::string(metrics.shape_gate ? "true" : "false") + ")" + diff --git a/plugins/logic_gate/person_shoe_shape.h b/plugins/logic_gate/person_shoe_shape.h new file mode 100644 index 0000000..de0107c --- /dev/null +++ b/plugins/logic_gate/person_shoe_shape.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +namespace rk3588 { + +struct PersonShoeShapeConfig { + float min_front_shoe_width_ratio = 0.18f; + float max_front_aspect_ratio = 1.5f; + float max_side_height_width_ratio = 0.8f; +}; + +struct PersonShoeShapeMetrics { + float person_width_ratio = 0.0f; + float aspect_ratio = 0.0f; + bool is_front_view = false; + bool shape_gate = false; +}; + +inline PersonShoeShapeMetrics EvaluatePersonShoeShape(float shoe_w, + float shoe_h, + float person_w, + const PersonShoeShapeConfig& config) { + PersonShoeShapeMetrics m; + const float safe_person_w = std::max(1.0f, person_w); + const float safe_shoe_w = std::max(1.0f, shoe_w); + const float safe_shoe_h = std::max(1.0f, shoe_h); + + m.person_width_ratio = safe_shoe_w / safe_person_w; + m.aspect_ratio = safe_shoe_h / safe_shoe_w; + m.is_front_view = m.person_width_ratio < config.min_front_shoe_width_ratio; + if (m.is_front_view) { + m.shape_gate = m.aspect_ratio <= config.max_front_aspect_ratio; + } else { + m.shape_gate = safe_shoe_h <= (safe_shoe_w * config.max_side_height_width_ratio); + } + return m; +} + +} // namespace rk3588 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d510c3b..94dc850 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -38,6 +38,7 @@ add_executable(rk3588_gtests test_hw_factory.cpp test_frame_buffer.cpp test_behavior_event_model.cpp + test_person_shoe_shape.cpp test_region_event.cpp test_action_recog.cpp test_event_fusion.cpp diff --git a/tests/test_person_shoe_shape.cpp b/tests/test_person_shoe_shape.cpp new file mode 100644 index 0000000..6cc3d0c --- /dev/null +++ b/tests/test_person_shoe_shape.cpp @@ -0,0 +1,76 @@ +#include + +#include "../plugins/logic_gate/person_shoe_shape.h" + +namespace rk3588 { +namespace { + +TEST(PersonShoeShapeTest, RejectsTallSideViewBoxes) { + PersonShoeShapeConfig config; + config.min_front_shoe_width_ratio = 0.18f; + config.max_front_aspect_ratio = 1.5f; + config.max_side_height_width_ratio = 0.8f; + + const auto metrics = EvaluatePersonShoeShape(20.0f, 33.0f, 100.0f, config); + + EXPECT_FALSE(metrics.is_front_view); + EXPECT_FALSE(metrics.shape_gate); + EXPECT_FLOAT_EQ(metrics.person_width_ratio, 0.2f); + EXPECT_FLOAT_EQ(metrics.aspect_ratio, 1.65f); +} + +TEST(PersonShoeShapeTest, AllowsSlightlyTallFrontViewBoxes) { + PersonShoeShapeConfig config; + config.min_front_shoe_width_ratio = 0.18f; + config.max_front_aspect_ratio = 1.5f; + config.max_side_height_width_ratio = 0.8f; + + const auto metrics = EvaluatePersonShoeShape(16.0f, 24.0f, 100.0f, config); + + EXPECT_TRUE(metrics.is_front_view); + EXPECT_TRUE(metrics.shape_gate); + EXPECT_FLOAT_EQ(metrics.person_width_ratio, 0.16f); + EXPECT_FLOAT_EQ(metrics.aspect_ratio, 1.5f); +} + +TEST(PersonShoeShapeTest, RejectsFrontViewBoxesBeyondAllowedAspect) { + PersonShoeShapeConfig config; + config.min_front_shoe_width_ratio = 0.18f; + config.max_front_aspect_ratio = 1.5f; + config.max_side_height_width_ratio = 0.8f; + + const auto metrics = EvaluatePersonShoeShape(16.0f, 25.0f, 100.0f, config); + + EXPECT_TRUE(metrics.is_front_view); + EXPECT_FALSE(metrics.shape_gate); + EXPECT_FLOAT_EQ(metrics.aspect_ratio, 1.5625f); +} + +TEST(PersonShoeShapeTest, AllowsWideSideViewBoxes) { + PersonShoeShapeConfig config; + config.min_front_shoe_width_ratio = 0.18f; + config.max_front_aspect_ratio = 1.5f; + config.max_side_height_width_ratio = 0.8f; + + const auto metrics = EvaluatePersonShoeShape(40.0f, 24.0f, 100.0f, config); + + EXPECT_FALSE(metrics.is_front_view); + EXPECT_TRUE(metrics.shape_gate); + EXPECT_FLOAT_EQ(metrics.aspect_ratio, 0.6f); +} + +TEST(PersonShoeShapeTest, RejectsNearSquareSideViewBoxes) { + PersonShoeShapeConfig config; + config.min_front_shoe_width_ratio = 0.18f; + config.max_front_aspect_ratio = 1.5f; + config.max_side_height_width_ratio = 0.8f; + + const auto metrics = EvaluatePersonShoeShape(40.0f, 33.0f, 100.0f, config); + + EXPECT_FALSE(metrics.is_front_view); + EXPECT_FALSE(metrics.shape_gate); + EXPECT_FLOAT_EQ(metrics.aspect_ratio, 0.825f); +} + +} // namespace +} // namespace rk3588