#include #include #include #include "frame/frame.h" #include "node.h" #include "utils/simple_json.h" #include "../plugins/action_recog/action_recog_node.h" namespace rk3588 { namespace { SimpleJson ParseActionConfig(const std::string& text) { SimpleJson config; std::string err; const bool ok = ParseSimpleJson(text, config, err); EXPECT_TRUE(ok); return config; } TEST(ActionRecogTest, EmitsFallAfterRapidDropAndLowPosePersistence) { ActionRecogNode node; const std::string config_text = R"({ "id": "action_evt", "events": [ { "type": "fall", "window_ms": 1500, "min_drop_pixels": 120, "min_aspect_ratio_delta": 0.35, "activate_duration_ms": 0 } ] })"; SimpleJson config = ParseActionConfig(config_text); NodeContext ctx; auto out = std::make_shared>(4, QueueDropStrategy::DropOldest); ctx.output_queues.push_back(out); ASSERT_TRUE(node.Init(config, ctx)); ASSERT_TRUE(node.Start()); auto frame1 = std::make_shared(); frame1->width = 1920; frame1->height = 1080; frame1->pts = 1000; frame1->det = std::make_shared(); frame1->det->img_w = 1920; frame1->det->img_h = 1080; frame1->det->items.push_back(Detection{0, 0.92f, Rect{800.0f, 240.0f, 120.0f, 320.0f}, 17}); auto frame2 = std::make_shared(); frame2->width = 1920; frame2->height = 1080; frame2->pts = 1600; frame2->det = std::make_shared(); frame2->det->img_w = 1920; frame2->det->img_h = 1080; frame2->det->items.push_back(Detection{0, 0.94f, Rect{760.0f, 460.0f, 260.0f, 140.0f}, 17}); EXPECT_EQ(static_cast(node.Process(frame1)), static_cast(NodeStatus::OK)); EXPECT_EQ(static_cast(node.Process(frame2)), static_cast(NodeStatus::OK)); ASSERT_NE(frame2->behavior_events, nullptr); ASSERT_EQ(frame2->behavior_events->items.size(), 1u); EXPECT_EQ(frame2->behavior_events->items[0].type, BehaviorEventType::Fall); ASSERT_EQ(frame2->behavior_events->items[0].track_ids.size(), 1u); EXPECT_EQ(frame2->behavior_events->items[0].track_ids[0], 17); } TEST(ActionRecogTest, EmitsFightWhenTwoTracksStayCloseWithRepeatedMotion) { ActionRecogNode node; const std::string config_text = R"({ "id": "action_evt", "events": [ { "type": "fight", "window_ms": 1200, "proximity_pixels": 220, "min_motion_pixels": 70, "activate_duration_ms": 0 } ] })"; SimpleJson config = ParseActionConfig(config_text); NodeContext ctx; auto out = std::make_shared>(4, QueueDropStrategy::DropOldest); ctx.output_queues.push_back(out); ASSERT_TRUE(node.Init(config, ctx)); ASSERT_TRUE(node.Start()); auto frame1 = std::make_shared(); frame1->width = 1920; frame1->height = 1080; frame1->pts = 1000; frame1->det = std::make_shared(); frame1->det->img_w = 1920; frame1->det->img_h = 1080; frame1->det->items.push_back(Detection{0, 0.90f, Rect{700.0f, 320.0f, 120.0f, 300.0f}, 31}); frame1->det->items.push_back(Detection{0, 0.89f, Rect{860.0f, 320.0f, 120.0f, 300.0f}, 32}); auto frame2 = std::make_shared(); frame2->width = 1920; frame2->height = 1080; frame2->pts = 1300; frame2->det = std::make_shared(); frame2->det->img_w = 1920; frame2->det->img_h = 1080; frame2->det->items.push_back(Detection{0, 0.91f, Rect{780.0f, 340.0f, 120.0f, 300.0f}, 31}); frame2->det->items.push_back(Detection{0, 0.92f, Rect{820.0f, 300.0f, 120.0f, 300.0f}, 32}); EXPECT_EQ(static_cast(node.Process(frame1)), static_cast(NodeStatus::OK)); EXPECT_EQ(static_cast(node.Process(frame2)), static_cast(NodeStatus::OK)); ASSERT_NE(frame2->behavior_events, nullptr); ASSERT_EQ(frame2->behavior_events->items.size(), 1u); EXPECT_EQ(frame2->behavior_events->items[0].type, BehaviorEventType::Fight); ASSERT_EQ(frame2->behavior_events->items[0].track_ids.size(), 2u); EXPECT_EQ(frame2->behavior_events->items[0].track_ids[0], 31); EXPECT_EQ(frame2->behavior_events->items[0].track_ids[1], 32); } } // namespace } // namespace rk3588