From 866ab2c27c6d20e88ea22b71aaf7916b378ea970 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Tue, 14 Apr 2026 17:37:03 +0800 Subject: [PATCH] Use bottom-third shoe color sampling --- plugins/logic_gate/color_analyzer.cpp | 32 +++++++-------- plugins/logic_gate/color_analyzer.h | 2 - plugins/logic_gate/logic_gate_node.cpp | 2 - tests/CMakeLists.txt | 2 + tests/test_color_analyzer.cpp | 56 ++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 tests/test_color_analyzer.cpp diff --git a/plugins/logic_gate/color_analyzer.cpp b/plugins/logic_gate/color_analyzer.cpp index affbacd..2532b3a 100644 --- a/plugins/logic_gate/color_analyzer.cpp +++ b/plugins/logic_gate/color_analyzer.cpp @@ -33,25 +33,23 @@ ColorResult ColorAnalyzer::Analyze(const Frame& frame, const Rect& bbox) { return result; } - const float center_w_scale = std::clamp(config_.center_w_scale, 0.1f, 1.0f); - const float center_h_scale = std::clamp(config_.center_h_scale, 0.1f, 1.0f); - const int inner_w = std::max(1, static_cast(crop_w * center_w_scale)); - const int inner_h = std::max(1, static_cast(crop_h * center_h_scale)); - const int inner_x = std::max(0, (crop_w - inner_w) / 2); - const int inner_y = std::max(0, (crop_h - inner_h) / 2); + const int sample_w = crop_w; + const int sample_h = std::max(1, crop_h / 3); + const int sample_x = 0; + const int sample_y = std::max(0, crop_h - sample_h); - std::vector center(inner_w * inner_h * 3); - for (int row = 0; row < inner_h; ++row) { - const uint8_t* src_row = cropped.data() + ((inner_y + row) * crop_w + inner_x) * 3; - uint8_t* dst_row = center.data() + row * inner_w * 3; - std::memcpy(dst_row, src_row, inner_w * 3); + std::vector sample(sample_w * sample_h * 3); + for (int row = 0; row < sample_h; ++row) { + const uint8_t* src_row = cropped.data() + ((sample_y + row) * crop_w + sample_x) * 3; + uint8_t* dst_row = sample.data() + row * sample_w * 3; + std::memcpy(dst_row, src_row, sample_w * 3); } // 保存调试图像(用于检查裁剪区域) if (config_.debug_output) { static int save_count = 0; if (save_count++ % 30 == 0) { // 每30帧保存一次 - SaveDebugImage(center.data(), inner_w, inner_h, "/tmp/boot_debug_" + std::to_string(save_count) + ".ppm"); + SaveDebugImage(sample.data(), sample_w, sample_h, "/tmp/boot_debug_" + std::to_string(save_count) + ".ppm"); LogInfo("[ColorAnalyzer] Saved debug image: /tmp/boot_debug_" + std::to_string(save_count) + ".ppm"); } } @@ -59,13 +57,13 @@ ColorResult ColorAnalyzer::Analyze(const Frame& frame, const Rect& bbox) { // 根据方法进行分析 switch (config_.method) { case ColorMethod::HSV: - result = AnalyzeHSV(center.data(), inner_w, inner_h, 3); + result = AnalyzeHSV(sample.data(), sample_w, sample_h, 3); break; case ColorMethod::RGB: - result = AnalyzeRGB(center.data(), inner_w, inner_h, 3); + result = AnalyzeRGB(sample.data(), sample_w, sample_h, 3); break; case ColorMethod::BRIGHTNESS: - result = AnalyzeBrightness(center.data(), inner_w, inner_h, 3); + result = AnalyzeBrightness(sample.data(), sample_w, sample_h, 3); break; default: LogWarn("[ColorAnalyzer] Unsupported color method: " + @@ -88,8 +86,8 @@ ColorResult ColorAnalyzer::Analyze(const Frame& frame, const Rect& bbox) { std::to_string(static_cast(expanded.y)) + "," + std::to_string(static_cast(expanded.w)) + "x" + std::to_string(static_cast(expanded.h)) + - " center=" + std::to_string(inner_x) + "," + std::to_string(inner_y) + "," + - std::to_string(inner_w) + "x" + std::to_string(inner_h)); + " sample=" + std::to_string(sample_x) + "," + std::to_string(sample_y) + "," + + std::to_string(sample_w) + "x" + std::to_string(sample_h)); } return result; diff --git a/plugins/logic_gate/color_analyzer.h b/plugins/logic_gate/color_analyzer.h index 4eb7d71..b963d26 100644 --- a/plugins/logic_gate/color_analyzer.h +++ b/plugins/logic_gate/color_analyzer.h @@ -17,8 +17,6 @@ struct ColorConfig { ColorMethod method = ColorMethod::HSV; int dark_threshold = 80; // 深色阈值(亮度0-255) float roi_expand = 1.0f; // ROI扩大系数 - float center_w_scale = 0.6f; // 中心区域宽度比例 - float center_h_scale = 0.6f; // 中心区域高度比例 bool debug_output = false; // 是否输出调试信息 }; diff --git a/plugins/logic_gate/logic_gate_node.cpp b/plugins/logic_gate/logic_gate_node.cpp index 383bcdc..af4b528 100644 --- a/plugins/logic_gate/logic_gate_node.cpp +++ b/plugins/logic_gate/logic_gate_node.cpp @@ -226,8 +226,6 @@ private: } config.color.dark_threshold = color->ValueOr("dark_threshold", 80); config.color.roi_expand = color->ValueOr("roi_expand", 1.0f); - config.color.center_w_scale = color->ValueOr("center_w_scale", 0.6f); - config.color.center_h_scale = color->ValueOr("center_h_scale", 0.6f); config.color.debug_output = config.debug; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index feb007d..f2c1cd6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,7 @@ endif() # New Google Test based tests add_executable(rk3588_gtests + test_color_analyzer.cpp test_result.cpp test_spsc_queue.cpp test_simple_json.cpp @@ -57,6 +58,7 @@ add_executable(rk3588_gtests ${CMAKE_SOURCE_DIR}/plugins/region_event/region_event_node.cpp ${CMAKE_SOURCE_DIR}/plugins/action_recog/action_recog_node.cpp ${CMAKE_SOURCE_DIR}/plugins/event_fusion/event_fusion_node.cpp + ${CMAKE_SOURCE_DIR}/plugins/logic_gate/color_analyzer.cpp ${CMAKE_SOURCE_DIR}/plugins/alarm/rule_engine.cpp ) diff --git a/tests/test_color_analyzer.cpp b/tests/test_color_analyzer.cpp new file mode 100644 index 0000000..541e7f3 --- /dev/null +++ b/tests/test_color_analyzer.cpp @@ -0,0 +1,56 @@ +#include + +#include +#include +#include + +#include "frame/frame.h" +#include "../plugins/logic_gate/color_analyzer.h" + +namespace rk3588 { +namespace { + +Frame MakeRgbFrame(int width, int height, uint8_t top_value, uint8_t bottom_value) { + auto pixels = std::make_shared>(static_cast(width * height * 3), 0); + for (int y = 0; y < height; ++y) { + const uint8_t value = (y < (height * 2 / 3)) ? top_value : bottom_value; + for (int x = 0; x < width; ++x) { + const size_t idx = static_cast((y * width + x) * 3); + (*pixels)[idx] = value; + (*pixels)[idx + 1] = value; + (*pixels)[idx + 2] = value; + } + } + + Frame frame; + frame.width = width; + frame.height = height; + frame.format = PixelFormat::RGB; + frame.stride = width * 3; + frame.data = pixels->data(); + frame.data_size = pixels->size(); + frame.data_owner = pixels; + return frame; +} + +TEST(ColorAnalyzerTest, UsesBottomThirdInsteadOfCenterRegionForBrightness) { + ColorConfig config; + config.method = ColorMethod::RGB; + config.dark_threshold = 80; + config.roi_expand = 1.0f; + config.debug_output = false; + + ColorAnalyzer analyzer(config); + Frame frame = MakeRgbFrame(9, 9, 180, 20); + Rect bbox{0.0f, 0.0f, 9.0f, 9.0f}; + + const ColorResult result = analyzer.Analyze(frame, bbox); + + ASSERT_TRUE(result.valid); + EXPECT_TRUE(result.is_dark); + EXPECT_LT(result.brightness, static_cast(config.dark_threshold)); + EXPECT_GT(result.dark_ratio, 0.6f); +} + +} // namespace +} // namespace rk3588