forked from dsutanto/bytetrack-counter-cpp
Latest Leveling with python Fix!
This commit is contained in:
1 parent
5483837769
commit
9ca1f2914e
11 files changed
+561
-172
No files matched your search
+28
-10
@@ -73,17 +73,35 @@ void AppConfig::load_from_env(const char* env_path) {
|
||||
if (!nc_s.empty()) num_classes = std::stoi(nc_s);
|
||||
auto ss_s = get_env("SCORE_SIGMOID");
|
||||
score_sigmoid = (ss_s == "true");
|
||||
auto ac_s = get_env("AYAM_CLASS_ID");
|
||||
if (!ac_s.empty()) ayam_class_id = std::stoi(ac_s);
|
||||
auto tc_s = get_env("TALENAN_CLASS_ID");
|
||||
if (!tc_s.empty()) talenan_class_id = std::stoi(tc_s);
|
||||
|
||||
auto th_s = get_env("TRACK_HIGH_THRESH");
|
||||
if (!th_s.empty()) track_high_thresh = std::stof(th_s);
|
||||
auto tl_s = get_env("TRACK_LOW_THRESH");
|
||||
if (!tl_s.empty()) track_low_thresh = std::stof(tl_s);
|
||||
auto tm_s = get_env("TRACK_MATCH_THRESH");
|
||||
if (!tm_s.empty()) track_match_thresh = std::stof(tm_s);
|
||||
auto tb_s = get_env("TRACK_BUFFER");
|
||||
if (!tb_s.empty()) track_buffer = std::stoi(tb_s);
|
||||
auto tmh_s = get_env("TRACK_MIN_HITS");
|
||||
if (!tmh_s.empty()) track_min_hits = std::stoi(tmh_s);
|
||||
auto th0_s = get_env("TRACK_HIGH_THRESH_0");
|
||||
if (!th0_s.empty()) track_high_thresh_0 = std::stof(th0_s);
|
||||
auto tl0_s = get_env("TRACK_LOW_THRESH_0");
|
||||
if (!tl0_s.empty()) track_low_thresh_0 = std::stof(tl0_s);
|
||||
auto tm0_s = get_env("TRACK_MATCH_THRESH_0");
|
||||
if (!tm0_s.empty()) track_match_thresh_0 = std::stof(tm0_s);
|
||||
auto tb0_s = get_env("TRACK_BUFFER_0");
|
||||
if (!tb0_s.empty()) track_buffer_0 = std::stoi(tb0_s);
|
||||
auto tmh0_s = get_env("TRACK_MIN_HITS_0");
|
||||
if (!tmh0_s.empty()) track_min_hits_0 = std::stoi(tmh0_s);
|
||||
|
||||
auto th1_s = get_env("TRACK_HIGH_THRESH_1");
|
||||
if (!th1_s.empty()) track_high_thresh_1 = std::stof(th1_s);
|
||||
auto tl1_s = get_env("TRACK_LOW_THRESH_1");
|
||||
if (!tl1_s.empty()) track_low_thresh_1 = std::stof(tl1_s);
|
||||
auto tm1_s = get_env("TRACK_MATCH_THRESH_1");
|
||||
if (!tm1_s.empty()) track_match_thresh_1 = std::stof(tm1_s);
|
||||
auto tb1_s = get_env("TRACK_BUFFER_1");
|
||||
if (!tb1_s.empty()) track_buffer_1 = std::stoi(tb1_s);
|
||||
auto tmh1_s = get_env("TRACK_MIN_HITS_1");
|
||||
if (!tmh1_s.empty()) track_min_hits_1 = std::stoi(tmh1_s);
|
||||
|
||||
auto rw_s = get_env("RATE_WINDOW_SEC");
|
||||
if (!rw_s.empty()) rate_window_sec = std::stoi(rw_s);
|
||||
|
||||
daily_cutoff_time = get_env("DAILY_CUTOFF_TIME", daily_cutoff_time);
|
||||
auto bto_s = get_env("BATCH_TIMEOUT_SECONDS");
|
||||
|
||||
+15
-5
@@ -24,12 +24,22 @@ struct AppConfig {
|
||||
int core_mask = 1;
|
||||
int num_classes = 2;
|
||||
bool score_sigmoid = false;
|
||||
int ayam_class_id = 0;
|
||||
int talenan_class_id = 1;
|
||||
|
||||
float track_high_thresh = 0.5f;
|
||||
float track_low_thresh = 0.1f;
|
||||
float track_match_thresh = 0.8f;
|
||||
int track_buffer = 30;
|
||||
int track_min_hits = 3;
|
||||
float track_high_thresh_0 = 0.5f;
|
||||
float track_low_thresh_0 = 0.1f;
|
||||
float track_match_thresh_0 = 0.8f;
|
||||
int track_buffer_0 = 30;
|
||||
int track_min_hits_0 = 3;
|
||||
|
||||
float track_high_thresh_1 = 0.5f;
|
||||
float track_low_thresh_1 = 0.1f;
|
||||
float track_match_thresh_1 = 0.6f;
|
||||
int track_buffer_1 = 30;
|
||||
int track_min_hits_1 = 3;
|
||||
|
||||
int rate_window_sec = 60;
|
||||
|
||||
std::string daily_cutoff_time = "20:00";
|
||||
float batch_timeout_seconds = 300.0f;
|
||||
|
||||
+24
-25
@@ -9,8 +9,8 @@ const std::vector<std::pair<int, int>> SKELETON = {
|
||||
};
|
||||
|
||||
const std::vector<cv::Scalar> SK_COLORS = {
|
||||
{255, 255, 0}, {255, 255, 0}, {255, 0, 255}, {255, 0, 255},
|
||||
{0, 255, 0}, {255, 255, 0}, {255, 0, 0}, {0, 200, 200}
|
||||
{0, 255, 255}, {0, 255, 255}, {255, 0, 255}, {255, 0, 255},
|
||||
{0, 255, 0}, {255, 255, 0}, {0, 0, 255}, {200, 200, 0}
|
||||
};
|
||||
|
||||
int resolve_line_x(int frame_width, int line_x_opt, float line_x_frac) {
|
||||
@@ -68,54 +68,53 @@ void draw_elegant_counting_line(cv::Mat& img, int line_x, int h, int pulse_remai
|
||||
void draw_hero_count(cv::Mat& img, int line_x, int h, int count, int pulse_remaining) {
|
||||
std::string text = std::to_string(count);
|
||||
float boost = 0.35f * (pulse_remaining / std::max(15.0f, 1.0f));
|
||||
double font_scale = 1.6 + boost;
|
||||
double font_scale = 1.4 + boost;
|
||||
int thickness = static_cast<int>(3 + boost);
|
||||
int baseline = 0;
|
||||
cv::Size ts = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, font_scale, thickness, &baseline);
|
||||
int pad = 14;
|
||||
int tx = line_x - ts.width / 2;
|
||||
int ty = h / 2 + ts.height / 2;
|
||||
overlay_rect(img, tx - pad, ty - ts.height - pad, tx + ts.width + pad, ty + pad / 2, C_PANEL, 0.78f);
|
||||
int ty = h / 3 + ts.height / 2;
|
||||
overlay_rect(img, tx - pad, ty - ts.height - pad, tx + ts.width + pad, ty + pad, C_PANEL, 0.78f);
|
||||
cv::rectangle(img, cv::Rect(tx - pad, ty - ts.height - pad,
|
||||
ts.width + pad * 2, ts.height + pad + pad / 2),
|
||||
ts.width + pad * 2, ts.height + pad * 2),
|
||||
C_LINE_CORE, 2);
|
||||
cv::putText(img, text, cv::Point(tx, ty), cv::FONT_HERSHEY_SIMPLEX, font_scale, C_GREEN, thickness, cv::LINE_AA);
|
||||
}
|
||||
|
||||
void draw_hud(cv::Mat& img, int w, int batch_num, int batch_count, int total_ayam,
|
||||
double elapsed_sec, double rate, const std::string& camera_id, const std::string& clock) {
|
||||
int bar_h = 52;
|
||||
double elapsed_sec, double rate) {
|
||||
int bar_h = 40;
|
||||
overlay_rect(img, 0, 0, w, bar_h, C_PANEL, 0.72f);
|
||||
cv::line(img, cv::Point(0, bar_h), cv::Point(w, bar_h), C_BORDER, 1);
|
||||
|
||||
cv::putText(img, "BATCH", cv::Point(16, 20), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
std::string batch_label = batch_num ? std::to_string(batch_num) : "\xe2\x80\x94";
|
||||
cv::putText(img, batch_label, cv::Point(16, 44), cv::FONT_HERSHEY_SIMPLEX, 0.9, C_ACCENT, 2, cv::LINE_AA);
|
||||
cv::putText(img, "BATCH", cv::Point(14, 14), cv::FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv::LINE_AA);
|
||||
std::string batch_label = batch_num ? std::to_string(batch_num) : "--";
|
||||
cv::putText(img, batch_label, cv::Point(14, 32), cv::FONT_HERSHEY_SIMPLEX, 0.55, C_ACCENT, 1, cv::LINE_AA);
|
||||
|
||||
cv::putText(img, "COUNT", cv::Point(100, 20), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, std::to_string(batch_count), cv::Point(100, 44), cv::FONT_HERSHEY_SIMPLEX, 0.9, C_GREEN, 2, cv::LINE_AA);
|
||||
cv::putText(img, "COUNT", cv::Point(90, 14), cv::FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, std::to_string(batch_count), cv::Point(90, 32), cv::FONT_HERSHEY_SIMPLEX, 0.55, C_GREEN, 1, cv::LINE_AA);
|
||||
|
||||
cv::putText(img, "TOTAL", cv::Point(190, 20), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, std::to_string(total_ayam), cv::Point(190, 44), cv::FONT_HERSHEY_SIMPLEX, 0.7, C_TEXT, 1, cv::LINE_AA);
|
||||
cv::putText(img, "TOTAL", cv::Point(170, 14), cv::FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, std::to_string(total_ayam), cv::Point(170, 32), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_TEXT, 1, cv::LINE_AA);
|
||||
|
||||
cv::putText(img, "UPTIME", cv::Point(280, 20), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, "UPTIME", cv::Point(250, 14), cv::FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv::LINE_AA);
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%.1fh", elapsed_sec / 3600.0);
|
||||
cv::putText(img, buf, cv::Point(280, 44), cv::FONT_HERSHEY_SIMPLEX, 0.7, C_TEXT, 1, cv::LINE_AA);
|
||||
cv::putText(img, buf, cv::Point(250, 32), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_TEXT, 1, cv::LINE_AA);
|
||||
|
||||
cv::putText(img, "RATE", cv::Point(380, 20), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, "RATE", cv::Point(340, 14), cv::FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv::LINE_AA);
|
||||
snprintf(buf, sizeof(buf), "%.1f/min", rate);
|
||||
cv::putText(img, buf, cv::Point(380, 44), cv::FONT_HERSHEY_SIMPLEX, 0.7, C_ACCENT, 1, cv::LINE_AA);
|
||||
|
||||
std::string cam_label = "CAM " + camera_id;
|
||||
cv::putText(img, cam_label, cv::Point(w - 180, 20), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
cv::putText(img, buf, cv::Point(340, 32), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_ACCENT, 1, cv::LINE_AA);
|
||||
}
|
||||
|
||||
void draw_footer(cv::Mat& img, int w, int h, int frame_idx, const std::string& live_tag) {
|
||||
void draw_footer(cv::Mat& img, int w, int h, int frame_idx, const std::string& live_tag,
|
||||
float inf_ms, const std::string& model_name) {
|
||||
int bar_h = 28;
|
||||
overlay_rect(img, 0, h - bar_h, w, h, C_PANEL, 0.55f);
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%s | Frame %d", live_tag.c_str(), frame_idx);
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "%s | %s | Frame %d | Inf %.1fms",
|
||||
live_tag.c_str(), model_name.c_str(), frame_idx, inf_ms);
|
||||
cv::putText(img, buf, cv::Point(12, h - 9), cv::FONT_HERSHEY_SIMPLEX, 0.45, C_MUTED, 1, cv::LINE_AA);
|
||||
}
|
||||
|
||||
|
||||
+11
-10
@@ -5,16 +5,16 @@
|
||||
#include <tuple>
|
||||
#include <cstdint>
|
||||
|
||||
inline const cv::Scalar C_PANEL(18, 24, 28);
|
||||
inline const cv::Scalar C_BORDER(75, 85, 90);
|
||||
inline const cv::Scalar C_ACCENT(60, 200, 255);
|
||||
inline const cv::Scalar C_GREEN(100, 220, 80);
|
||||
inline const cv::Scalar C_PANEL(28, 24, 18);
|
||||
inline const cv::Scalar C_BORDER(90, 85, 75);
|
||||
inline const cv::Scalar C_ACCENT(255, 200, 60);
|
||||
inline const cv::Scalar C_GREEN(80, 220, 100);
|
||||
inline const cv::Scalar C_TEXT(235, 235, 235);
|
||||
inline const cv::Scalar C_MUTED(150, 150, 150);
|
||||
inline const cv::Scalar C_AYAM_BOX(255, 165, 0);
|
||||
inline const cv::Scalar C_TALENAN_BOX(60, 120, 220);
|
||||
inline const cv::Scalar C_LINE_CORE(255, 220, 180);
|
||||
inline const cv::Scalar C_LINE_GLOW(220, 160, 100);
|
||||
inline const cv::Scalar C_AYAM_BOX(255, 150, 60);
|
||||
inline const cv::Scalar C_TALENAN_BOX(60, 60, 255);
|
||||
inline const cv::Scalar C_LINE_CORE(180, 220, 255);
|
||||
inline const cv::Scalar C_LINE_GLOW(100, 160, 220);
|
||||
|
||||
extern const std::vector<std::pair<int, int>> SKELETON;
|
||||
extern const std::vector<cv::Scalar> SK_COLORS;
|
||||
@@ -30,8 +30,9 @@ void draw_pill(cv::Mat& img, const std::string& text, int x, int y,
|
||||
void draw_elegant_counting_line(cv::Mat& img, int line_x, int h, int pulse_remaining = 0);
|
||||
void draw_hero_count(cv::Mat& img, int line_x, int h, int count, int pulse_remaining = 0);
|
||||
void draw_hud(cv::Mat& img, int w, int batch_num, int batch_count, int total_ayam,
|
||||
double elapsed_sec, double rate, const std::string& camera_id, const std::string& clock);
|
||||
void draw_footer(cv::Mat& img, int w, int h, int frame_idx, const std::string& live_tag);
|
||||
double elapsed_sec, double rate);
|
||||
void draw_footer(cv::Mat& img, int w, int h, int frame_idx, const std::string& live_tag,
|
||||
float inf_ms = 0.0f, const std::string& model_name = "");
|
||||
void draw_skeleton_bold(cv::Mat& img, const std::vector<std::vector<cv::Point2f>>& kpts);
|
||||
|
||||
struct Popup {
|
||||
|
||||
+82
-34
@@ -50,6 +50,35 @@ static void warmup_stream(cv::VideoCapture& cap, int n) {
|
||||
std::cout << "Stream ready!" << std::endl;
|
||||
}
|
||||
|
||||
static bool connect_stream(cv::VideoCapture& cap, int& w, int& h, double& fps) {
|
||||
bool is_live = g_config.source.substr(0, 7) == "rtsp://" ||
|
||||
g_config.source.substr(0, 7) == "http://";
|
||||
int attempts = 0;
|
||||
while (!shutdown_requested) {
|
||||
cap = open_capture(g_config.source);
|
||||
if (cap.isOpened()) break;
|
||||
attempts++;
|
||||
if (g_config.max_reconnect_attempts > 0 && attempts >= g_config.max_reconnect_attempts) {
|
||||
std::cerr << "Cannot open source after " << attempts
|
||||
<< " attempts: " << g_config.source << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout << "Cannot open source, retry in " << g_config.reconnect_delay_sec
|
||||
<< "s..." << std::endl;
|
||||
std::this_thread::sleep_for(std::chrono::seconds(g_config.reconnect_delay_sec));
|
||||
}
|
||||
if (shutdown_requested) return false;
|
||||
|
||||
if (is_live && g_config.warmup_frames > 0)
|
||||
warmup_stream(cap, g_config.warmup_frames);
|
||||
|
||||
w = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
|
||||
h = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
|
||||
fps = cap.get(cv::CAP_PROP_FPS);
|
||||
if (fps <= 1) fps = g_config.output_fps;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct TrackedInfo {
|
||||
float cx;
|
||||
std::chrono::steady_clock::time_point ts;
|
||||
@@ -75,11 +104,23 @@ int main(int argc, char* argv[]) {
|
||||
std::cout << "Starting ByteTrack Counter (C++)" << std::endl;
|
||||
std::cout << "Camera: " << g_config.camera_name << std::endl;
|
||||
std::cout << "Source: " << g_config.source << std::endl;
|
||||
std::cout << "Model: " << g_config.model_path << std::endl;
|
||||
std::cout << "Model: " << g_config.model_path << " | imgsz=" << g_config.imgsz
|
||||
<< " | core_mask=" << g_config.core_mask << std::endl;
|
||||
std::cout << "DB: " << g_config.db_path << std::endl;
|
||||
std::cout << "State: " << g_config.state_file << std::endl;
|
||||
std::cout << "ByteTrack Index 0: high_thresh=" << g_config.track_high_thresh_0
|
||||
<< " low_thresh=" << g_config.track_low_thresh_0
|
||||
<< " match_thresh=" << g_config.track_match_thresh_0
|
||||
<< " buffer=" << g_config.track_buffer_0
|
||||
<< " min_hits=" << g_config.track_min_hits_0 << std::endl;
|
||||
std::cout << "ByteTrack Index 1: high_thresh=" << g_config.track_high_thresh_1
|
||||
<< " low_thresh=" << g_config.track_low_thresh_1
|
||||
<< " match_thresh=" << g_config.track_match_thresh_1
|
||||
<< " buffer=" << g_config.track_buffer_1
|
||||
<< " min_hits=" << g_config.track_min_hits_1 << std::endl;
|
||||
|
||||
int class_ayam = 0;
|
||||
int class_talenan = 1;
|
||||
int class_ayam = g_config.ayam_class_id;
|
||||
int class_talenan = g_config.talenan_class_id;
|
||||
|
||||
auto logger = [](const std::string& msg) {
|
||||
std::cout << "[" << now_str() << "] " << msg << std::endl;
|
||||
@@ -105,12 +146,12 @@ int main(int argc, char* argv[]) {
|
||||
g_config.imgsz, g_config.conf, 0.45f,
|
||||
g_config.num_classes, 0, g_config.score_sigmoid);
|
||||
|
||||
ByteTracker ayam_tracker(g_config.track_high_thresh, g_config.track_low_thresh,
|
||||
g_config.track_match_thresh, g_config.track_buffer,
|
||||
g_config.track_min_hits);
|
||||
ByteTracker talenan_tracker(g_config.track_high_thresh, g_config.track_low_thresh,
|
||||
g_config.track_match_thresh, g_config.track_buffer,
|
||||
g_config.track_min_hits);
|
||||
ByteTracker ayam_tracker(g_config.track_high_thresh_0, g_config.track_low_thresh_0,
|
||||
g_config.track_match_thresh_0, g_config.track_buffer_0,
|
||||
g_config.track_min_hits_0);
|
||||
ByteTracker talenan_tracker(g_config.track_high_thresh_1, g_config.track_low_thresh_1,
|
||||
g_config.track_match_thresh_1, g_config.track_buffer_1,
|
||||
g_config.track_min_hits_1);
|
||||
|
||||
std::unordered_set<int> ayam_line_crossed;
|
||||
std::unordered_set<int> talenan_line_crossed;
|
||||
@@ -119,27 +160,27 @@ int main(int argc, char* argv[]) {
|
||||
std::unordered_map<int, int> talenan_cross_flash;
|
||||
int line_pulse = 0, count_pulse = 0, batch_pulse = 0;
|
||||
std::vector<Popup> popups;
|
||||
std::deque<std::chrono::steady_clock::time_point> crossing_times;
|
||||
|
||||
auto session_start = std::chrono::steady_clock::now();
|
||||
int frame_idx = 0;
|
||||
float inf_ema = 0.0f;
|
||||
|
||||
cv::VideoCapture cap = open_capture(g_config.source);
|
||||
std::string model_name = g_config.model_path;
|
||||
auto slash = model_name.find_last_of("/\\");
|
||||
if (slash != std::string::npos) model_name = model_name.substr(slash + 1);
|
||||
|
||||
cv::VideoCapture cap;
|
||||
int w, h;
|
||||
double fps_prop;
|
||||
|
||||
if (!connect_stream(cap, w, h, fps_prop)) {
|
||||
store.shutdown();
|
||||
return shutdown_requested ? 0 : 1;
|
||||
}
|
||||
bool is_live = g_config.source.substr(0, 7) == "rtsp://" ||
|
||||
g_config.source.substr(0, 7) == "http://";
|
||||
|
||||
if (!cap.isOpened()) {
|
||||
std::cerr << "Cannot open source: " << g_config.source << std::endl;
|
||||
store.shutdown();
|
||||
return 1;
|
||||
}
|
||||
if (is_live && g_config.warmup_frames > 0)
|
||||
warmup_stream(cap, g_config.warmup_frames);
|
||||
|
||||
int w = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
|
||||
int h = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
|
||||
double fps_prop = cap.get(cv::CAP_PROP_FPS);
|
||||
if (fps_prop <= 1) fps_prop = g_config.output_fps;
|
||||
|
||||
int line_x = resolve_line_x(w, g_config.line_x, g_config.line_x_frac);
|
||||
|
||||
std::cout << "RKNN+ByteTrack counter | " << w << "x" << h << " @ "
|
||||
@@ -161,21 +202,22 @@ int main(int argc, char* argv[]) {
|
||||
<< "), reconnecting..." << std::endl;
|
||||
cap.release();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(g_config.reconnect_delay_sec));
|
||||
cap = open_capture(g_config.source);
|
||||
if (!cap.isOpened()) break;
|
||||
w = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
|
||||
h = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
|
||||
if (!connect_stream(cap, w, h, fps_prop)) break;
|
||||
line_x = resolve_line_x(w, g_config.line_x, g_config.line_x_frac);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto elapsed_sec = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
auto elapsed_sec = std::chrono::duration<double>(
|
||||
std::chrono::steady_clock::now() - session_start).count();
|
||||
auto mono = std::chrono::steady_clock::now();
|
||||
|
||||
bool ayam_crossed_frame = false, batch_closed_frame = false, batch_started_frame = false;
|
||||
|
||||
auto inf_start = std::chrono::steady_clock::now();
|
||||
std::vector<Detection> detections = model(frame);
|
||||
float inf_ms = std::chrono::duration<float, std::milli>(
|
||||
std::chrono::steady_clock::now() - inf_start).count();
|
||||
inf_ema = inf_ema * 0.9f + inf_ms * 0.1f;
|
||||
|
||||
if (!detections.empty()) {
|
||||
std::vector<Eigen::Vector4f> ayam_boxes, talenan_boxes;
|
||||
@@ -317,6 +359,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
ayam_crossed_frame = true;
|
||||
if (started_new) batch_started_frame = true;
|
||||
crossing_times.push_back(mono);
|
||||
ayam_cross_flash[tid] = g_config.cross_flash_frames;
|
||||
popups.push_back({
|
||||
static_cast<int>(cx) - 12,
|
||||
@@ -379,15 +422,19 @@ int main(int argc, char* argv[]) {
|
||||
int batch_num = store.current_batch_number();
|
||||
int batch_count = store.current_batch_count();
|
||||
int display_total = store.display_total();
|
||||
double elapsed = static_cast<double>(elapsed_sec);
|
||||
double rate = elapsed > 0 ? (display_total / elapsed * 60.0) : 0.0;
|
||||
|
||||
while (!crossing_times.empty() &&
|
||||
std::chrono::duration<double>(mono - crossing_times.front()).count() > g_config.rate_window_sec)
|
||||
crossing_times.pop_front();
|
||||
double rate = crossing_times.empty() ? 0.0 :
|
||||
(crossing_times.size() / static_cast<double>(g_config.rate_window_sec) * 60.0);
|
||||
|
||||
draw_elegant_counting_line(frame, line_x, h, line_pulse);
|
||||
draw_hero_count(frame, line_x, h, batch_count, count_pulse);
|
||||
draw_hud(frame, w, batch_num, batch_count, display_total,
|
||||
elapsed, rate, g_config.camera_name, now_str());
|
||||
elapsed_sec, rate);
|
||||
draw_batch_banner(frame, w, batch_num, batch_pulse);
|
||||
draw_footer(frame, w, h, frame_idx, is_live ? "LIVE-RKNN-BT" : "FILE-RKNN-BT");
|
||||
draw_footer(frame, w, h, frame_idx, is_live ? "LIVE" : "FILE", inf_ema, model_name);
|
||||
popups = draw_popups(frame, popups, frame_idx);
|
||||
|
||||
// Flash decay
|
||||
@@ -418,9 +465,10 @@ int main(int argc, char* argv[]) {
|
||||
frame_idx++;
|
||||
if (frame_idx % g_config.flush_every_n_frames == 0) {
|
||||
std::cout << "[" << now_str() << "] Frame " << frame_idx
|
||||
<< " | Batch " << batch_num << ": " << batch_count
|
||||
<< " | Batch " << (batch_num ? std::to_string(batch_num) : "-")
|
||||
<< ": " << (batch_num ? std::to_string(batch_count) : "-")
|
||||
<< " | Total: " << display_total
|
||||
<< " | Uptime " << (elapsed / 3600.0) << "h" << std::endl;
|
||||
<< " | Uptime " << (elapsed_sec / 3600.0) << "h" << std::endl;
|
||||
}
|
||||
|
||||
prune_stale_tracks(ayam_tracked, g_config.tracked_prune_sec);
|
||||
|
||||
Reference in new issue
Block a user