safesight/edge/tests/test_person_shoe_shape.cpp
tian 29d9ef5d0d refactor: 项目结构梳理 - 设备端/管理端对称布局
仓库结构:
  edge/     设备端(原根目录设备端代码整体移入)
  control/  管理端(清理后)
  docs/     文档(PRD 移入 design/)
  README.md 根导航(新增)

清理:
- control/.brainstorm 临时草稿删除
- control 根级重复文档(API表/PRD_04)并入 docs/design/
- control/plan.md -> docs/implementation/control-plan.md
- control/safesightd-linux-arm64 二进制取消版本控制(.gitignore)
- edge/transform 模型转换产物归入 models/,onnx/pt 大源文件取消跟踪(.gitignore)
- Readme.md(PRD) -> docs/design/PRD_Product_v1.2.md(避开 README 大小写冲突)

更新:
- 根 README.md 导航、docs/README.md 文档索引
- deployment.md/检查表路径加 edge/ 前缀
- .gitignore 重写(edge/control 分区规则)
2026-08-02 11:39:54 +08:00

126 lines
4.8 KiB
C++

#include <gtest/gtest.h>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include "../plugins/logic_gate/person_shoe_shape.h"
#include "utils/simple_json.h"
namespace rk3588 {
namespace {
PersonShoeShapeConfig LoadShapeConfig() {
std::ifstream file("configs/full_pipeline_1080p_test_alarm.json");
if (!file.is_open()) {
throw std::runtime_error("failed to open configs/full_pipeline_1080p_test_alarm.json");
}
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.shape_gate);
EXPECT_GT(metrics.person_width_ratio, config.min_front_shoe_width_ratio);
EXPECT_GT(metrics.aspect_ratio, config.max_side_height_width_ratio);
}
TEST(PersonShoeShapeTest, AllowsFrontViewBoxesAtConfiguredAspectLimit) {
const auto config = LoadShapeConfig();
const float shoe_w = 16.0f;
const float shoe_h = shoe_w * config.max_front_aspect_ratio;
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_TRUE(metrics.is_front_view);
EXPECT_TRUE(metrics.shape_gate);
EXPECT_LT(metrics.person_width_ratio, config.min_front_shoe_width_ratio);
EXPECT_FLOAT_EQ(metrics.aspect_ratio, config.max_front_aspect_ratio);
}
TEST(PersonShoeShapeTest, RejectsFrontViewBoxesBeyondConfiguredAspect) {
const auto config = LoadShapeConfig();
const float shoe_w = 16.0f;
const float shoe_h = shoe_w * (config.max_front_aspect_ratio + 0.1f);
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_TRUE(metrics.is_front_view);
EXPECT_FALSE(metrics.shape_gate);
EXPECT_GT(metrics.aspect_ratio, config.max_front_aspect_ratio);
}
TEST(PersonShoeShapeTest, AllowsSideViewBoxesWithinConfiguredRatio) {
const auto config = LoadShapeConfig();
const float shoe_w = 40.0f;
const float shoe_h = shoe_w * (config.max_side_height_width_ratio - 0.1f);
const float person_w = shoe_w / (config.min_front_shoe_width_ratio + 0.05f);
const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_FALSE(metrics.is_front_view);
EXPECT_TRUE(metrics.shape_gate);
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, AllowsNearSquareSideViewBoxesWhenConfigPermits) {
const auto config = LoadShapeConfig();
const float shoe_w = 40.0f;
const float shoe_h = shoe_w * (config.max_side_height_width_ratio - 0.05f);
const float person_w = shoe_w / (config.min_front_shoe_width_ratio + 0.04f);
const auto metrics = EvaluatePersonShoeShape(shoe_w, shoe_h, person_w, config);
EXPECT_FALSE(metrics.is_front_view);
EXPECT_TRUE(metrics.shape_gate);
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 rk3588