#include #include #include #include "chicken_counter/capture.hpp" #include "chicken_counter/video_writer.hpp" #include "chicken_counter/counting.hpp" #include "chicken_counter/motion.hpp" #include "chicken_counter/overlay.hpp" #include "chicken_counter/batch_discovery.hpp" #include "chicken_counter/report.hpp" #include "chicken_counter/compress.hpp" int main() { std::cout << "=== test_modules ===" << std::endl; // test CountingZone { cc::RoiConfig roi; roi.points = {{100, 200}, {1600, 200}, {1600, 800}, {100, 800}}; roi.min_overlap_ratio = 0.3f; cc::GateConfig gate; gate.mode = "two_line"; gate.lines_y = {320, 600}; cc::CountingZone zone(roi, gate, 20, 75, 500, false, false); cc::TrackObservation t; t.track_id = 1; t.bbox_x1 = 200; t.bbox_y1 = 300; t.bbox_x2 = 350; t.bbox_y2 = 500; t.centroid_x = 275; t.centroid_y = 400; t.confidence = 0.9f; auto events = zone.update({t}, 100, false); assert(zone.total_entered_count == 1); assert(events.size() == 1); assert(events[0].track_id == 1); assert(zone.is_inside(1)); assert(zone.is_validated(1)); auto trail = zone.trail_for(1); assert(trail.size() == 1); std::cout << " CountingZone OK" << std::endl; } // test BackwardMotionDetector (disabled) { cc::MotionConfig mc; mc.enabled = false; cc::RoiConfig roi; roi.points = {{0, 0}, {100, 0}, {100, 100}, {0, 100}}; cc::BackwardMotionDetector detector(mc, roi, false); cv::Mat frame(100, 100, CV_8UC3, cv::Scalar(0, 0, 0)); std::vector tracks; auto state = detector.update(frame, tracks, 0); assert(!state.backward_active); std::cout << " BackwardMotionDetector OK" << std::endl; } // test overlay { cc::RoiConfig roi; roi.points = {{50, 50}, {200, 50}, {200, 200}, {50, 200}}; cc::GateConfig gate; cc::CountingZone zone(roi, gate, 20, 75); cc::CameraConfig cfg; cfg.camera_id = "test"; cfg.roi = roi; cfg.overlay.trail_length = 20; cv::Mat frame(300, 400, CV_8UC3, cv::Scalar(60, 60, 60)); cc::MotionState ms; cc::TrackObservation t; t.track_id = 99; t.bbox_x1 = 100; t.bbox_y1 = 80; t.bbox_x2 = 150; t.bbox_y2 = 130; t.centroid_x = 125; t.centroid_y = 105; t.confidence = 0.9f; zone.update({t}, 1, false); auto annotated = cc::draw_overlay(frame, cfg, zone, {t}, ms, 1); assert(annotated.rows == 300 && annotated.cols == 400); std::cout << " Overlay OK" << std::endl; } // test report { cc::PipelineResult pr; pr.camera_id = "CC1"; pr.total_entered_count = 42; pr.frames_processed = 1000; pr.stopped_reason = "eof"; pr.source_video = "/tmp/CC1.mp4"; pr.elapsed_seconds = 10.5; cc::CameraBatchResult cr; cr.camera_id = "CC1"; cr.pipeline = pr; auto entry = cc::build_camera_report_entry(cr, "/tmp/output"); assert(entry["total_entered"] == 42); std::cout << " Report OK" << std::endl; } // test batch_discovery { cc::CameraPreset preset; preset.camera_id = "CC1"; preset.camera_num = 1; preset.roi.points = {{0, 0}, {100, 100}}; cc::BatchSettings settings; settings.batch.root_dir = "/tmp/batch"; settings.batch.camera_glob = "kandang_*_camera_{num}_*.mp4"; settings.cameras["CC1"] = preset; // test pattern replacement (not actual filesystem) auto pattern = cc::replace_glob_placeholder(settings.batch.camera_glob, 1); assert(pattern == "kandang_*_camera_1_*.mp4"); std::cout << " BatchDiscovery OK" << std::endl; } std::cout << "=== all tests passed ===" << std::endl; return 0; }