OrangePi3588Media/tests/test_action_recog.cpp

129 lines
4.4 KiB
C++

#include <gtest/gtest.h>
#include <memory>
#include <string>
#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<SpscQueue<FramePtr>>(4, QueueDropStrategy::DropOldest);
ctx.output_queues.push_back(out);
ASSERT_TRUE(node.Init(config, ctx));
ASSERT_TRUE(node.Start());
auto frame1 = std::make_shared<Frame>();
frame1->width = 1920;
frame1->height = 1080;
frame1->pts = 1000;
frame1->det = std::make_shared<DetectionResult>();
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<Frame>();
frame2->width = 1920;
frame2->height = 1080;
frame2->pts = 1600;
frame2->det = std::make_shared<DetectionResult>();
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<int>(node.Process(frame1)), static_cast<int>(NodeStatus::OK));
EXPECT_EQ(static_cast<int>(node.Process(frame2)), static_cast<int>(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<SpscQueue<FramePtr>>(4, QueueDropStrategy::DropOldest);
ctx.output_queues.push_back(out);
ASSERT_TRUE(node.Init(config, ctx));
ASSERT_TRUE(node.Start());
auto frame1 = std::make_shared<Frame>();
frame1->width = 1920;
frame1->height = 1080;
frame1->pts = 1000;
frame1->det = std::make_shared<DetectionResult>();
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<Frame>();
frame2->width = 1920;
frame2->height = 1080;
frame2->pts = 1300;
frame2->det = std::make_shared<DetectionResult>();
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<int>(node.Process(frame1)), static_cast<int>(NodeStatus::OK));
EXPECT_EQ(static_cast<int>(node.Process(frame2)), static_cast<int>(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