diff --git a/build/bytetrack-counter b/build/bytetrack-counter index be0f335..28bc649 100755 Binary files a/build/bytetrack-counter and b/build/bytetrack-counter differ diff --git a/build/version.hpp b/build/version.hpp index 2268d43..781a6fa 100644 --- a/build/version.hpp +++ b/build/version.hpp @@ -4,11 +4,11 @@ namespace version { -const std::string GIT_COMMIT = "87277f75"; +const std::string GIT_COMMIT = "bed242d2"; const std::string GIT_BRANCH = "main"; const std::string GIT_TAG = ""; const std::string BUILD_DATE = "2026-07-06"; -const std::string BUILD_TIME = "18:03:38"; +const std::string BUILD_TIME = "22:54:19"; const int BUILD_YEAR = 2026; const bool BUILD_RKNN = 1; diff --git a/config.env.example b/config.env.example index dcba75e..5981a96 100644 --- a/config.env.example +++ b/config.env.example @@ -110,6 +110,13 @@ EXPORT_CSV=true CROSS_CSV=/opt/batch-counter/batch_crossings.csv # --- Rate / performance --- +# Enable motion detection pre-filter: skip inference on frames with no movement +# (true/false, default: false). When enabled, frames below MOTION_THRESHOLD are +# skipped, saving NPU/CPU load. +MOTION_DETECTION_ENABLED=false +# Mean absolute pixel difference threshold (0–255) to consider a frame as having +# motion. Lower = more sensitive. Default 5.0. +MOTION_THRESHOLD=5.0 # Sliding window in seconds for computing the crossing rate (objects/minute) RATE_WINDOW_SEC=60 # Number of frames to discard at startup to let the stream buffer stabilise diff --git a/src/config.cpp b/src/config.cpp index 882618e..4362cb8 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -119,6 +119,11 @@ void AppConfig::load_from_env(const char* env_path) { if (!ecsv.empty()) export_csv = (ecsv == "true"); cross_csv = get_env("CROSS_CSV", output_dir + "/batch_crossings.csv"); + auto mde_s = get_env("MOTION_DETECTION_ENABLED"); + motion_detection_enabled = (mde_s == "true"); + auto mt_s = get_env("MOTION_THRESHOLD"); + if (!mt_s.empty()) motion_threshold = std::stof(mt_s); + auto wf_s = get_env("WARMUP_FRAMES"); if (!wf_s.empty()) warmup_frames = std::stoi(wf_s); auto rd_s = get_env("RECONNECT_DELAY_SEC"); diff --git a/src/config.hpp b/src/config.hpp index cbc280d..e7824e8 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -51,6 +51,8 @@ struct AppConfig { bool export_csv = true; std::string cross_csv; + bool motion_detection_enabled = false; + float motion_threshold = 5.0f; int warmup_frames = 30; int reconnect_delay_sec = 3; int max_reconnect_attempts = 0; diff --git a/src/main.cpp b/src/main.cpp index 802c996..b2dadfd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -217,6 +217,7 @@ int main(int argc, char* argv[]) { std::unordered_map ayam_tracked; std::unordered_map talenan_tracked; + cv::Mat prev_gray; while (!shutdown_requested) { cv::Mat frame; @@ -257,10 +258,27 @@ int main(int argc, char* argv[]) { bool ayam_crossed_frame = false, batch_closed_frame = false, batch_started_frame = false; - auto inf_start = std::chrono::steady_clock::now(); - std::vector detections = model(frame); - float inf_ms = std::chrono::duration( - std::chrono::steady_clock::now() - inf_start).count(); + bool skip_inference = false; + if (g_config.motion_detection_enabled) { + cv::Mat gray; + cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); + if (!prev_gray.empty()) { + cv::Mat diff; + cv::absdiff(gray, prev_gray, diff); + double mean_diff = cv::mean(diff)[0]; + skip_inference = (mean_diff < g_config.motion_threshold); + } + prev_gray = gray; + } + + std::vector detections; + float inf_ms = 0.0f; + if (!skip_inference) { + auto inf_start = std::chrono::steady_clock::now(); + detections = model(frame); + inf_ms = std::chrono::duration( + std::chrono::steady_clock::now() - inf_start).count(); + } inf_ema = inf_ema * 0.9f + inf_ms * 0.1f; if (!detections.empty()) {