From 936e547dc3c6bbf241daaa99f9a8c58b8764536c Mon Sep 17 00:00:00 2001 From: miketsai Date: Wed, 29 Jul 2026 17:04:31 +0800 Subject: [PATCH] feat(detect): add debounce for alert/collision and tune default thresholds - stdc_post_process.c: add consecutive frame counters for left/right alert (5 frames) and collision_risk (3 frames) to suppress single-frame noise - raise alert threshold defaults to 0.20 across all classes; tree_alert raised to 0.30 (trees are common background, prone to false positives) - grass_roi default raised from 0.75 to 0.80 - remove per-frame verbose log from stdc_post_process.c (consolidated into app_header_init.c) - app_header_init.c: add STDC-VIO / STDC-COL / STDC-ALT tuning logs showing actual%/threshold% side-by-side for field calibration - ini/host_stream.ini, kp_firmware.c: sync fallback defaults to match --- ini/host_stream.ini | 2 +- src/host_stream/app_header_init.c | 42 ++++++++++++ src/host_stream/kp_firmware.c | 10 +-- src/pre_post_proc/stdc_post_process.c | 94 ++++++++++++++------------- 4 files changed, 96 insertions(+), 52 deletions(-) diff --git a/ini/host_stream.ini b/ini/host_stream.ini index 7c91748..0c2650f 100644 --- a/ini/host_stream.ini +++ b/ini/host_stream.ini @@ -127,6 +127,6 @@ thr_bunker_col = 200 # bunker ratio → collision thr_pond_col = 200 # pond ratio → collision thr_person_alt = 200 # person ratio in side ROI → alert thr_car_alt = 200 # car ratio → alert -thr_tree_alt = 200 # tree ratio → alert +thr_tree_alt = 300 # tree ratio → alert (higher: trees are common background) thr_bunker_alt = 200 # bunker ratio → alert thr_pond_alt = 200 # pond ratio → alert diff --git a/src/host_stream/app_header_init.c b/src/host_stream/app_header_init.c index 151bde7..54ba478 100644 --- a/src/host_stream/app_header_init.c +++ b/src/host_stream/app_header_init.c @@ -11,6 +11,7 @@ #include "kdp2_inf_app_yolo.h" //#include "demo_customize_inf_single_model.h" #include "stdc_app.h" +#include "stdc_post_process.h" #include "kdp2_host_stream.h" #include "event_recorder.h" #include "can_bus.h" @@ -549,6 +550,47 @@ int app_header_recv_inference(uint32_t buf_addr, bool *bl_run_next_inference) printf("[STDC] ON GRASS: %.1fs%s\n",ana->grass_duration_sec,ana->grass_warning ? " *** GRASS WARNING ***" : ""); else printf("[STDC] ON ROAD\n"); + + /* 3. ROI threshold tuning log (value%/threshold%) */ + /* [VIO] Grass / violation ROI */ + printf("[STDC-VIO] f=%u grass_roi=%.1f%%/%.0f%% time=%.1fs moving=%d diff=%.2f" + " | ON_GRASS=%d GRASS_WARN=%d\n", + ana->frame_count, + ana->grass_roi_ratio * 100.0f, g_thr_grass_roi * 100.0f, + ana->grass_duration_sec, + ana->is_moving, ana->motion_diff, + ana->on_grass, ana->grass_warning); + + /* [COL] Collision ROI — forward trapezoid */ + printf("[STDC-COL] person=%.1f%%/%.0f%% car=%.1f%%/%.0f%% tree=%.1f%%/%.0f%%" + " bunker=%.1f%%/%.0f%% pond=%.1f%%/%.0f%%" + " | COLLISION=%d\n", + ana->col_person_ratio * 100.0f, g_thr_person_collision * 100.0f, + ana->col_car_ratio * 100.0f, g_thr_car_collision * 100.0f, + ana->col_tree_ratio * 100.0f, g_thr_tree_collision * 100.0f, + ana->col_bunker_ratio * 100.0f, g_thr_bunker_collision * 100.0f, + ana->col_pond_ratio * 100.0f, g_thr_pond_collision * 100.0f, + ana->collision_risk); + + /* [ALT] Left / Right alert ROI */ + printf("[STDC-ALT] L: person=%.1f%%/%.0f%% car=%.1f%%/%.0f%% tree=%.1f%%/%.0f%%" + " pond=%.1f%%/%.0f%% bunker=%.1f%%/%.0f%%" + " | ALERT=%d[%s]\n", + ana->left_person_ratio * 100.0f, g_thr_person_alert * 100.0f, + ana->left_car_ratio * 100.0f, g_thr_car_alert * 100.0f, + ana->left_tree_ratio * 100.0f, g_thr_tree_alert * 100.0f, + ana->left_pond_ratio * 100.0f, g_thr_pond_alert * 100.0f, + ana->left_bunker_ratio * 100.0f, g_thr_bunker_alert * 100.0f, + ana->left_alert, ana->left_alert ? ana->left_type : "-"); + printf("[STDC-ALT] R: person=%.1f%%/%.0f%% car=%.1f%%/%.0f%% tree=%.1f%%/%.0f%%" + " pond=%.1f%%/%.0f%% bunker=%.1f%%/%.0f%%" + " | ALERT=%d[%s]\n", + ana->right_person_ratio * 100.0f, g_thr_person_alert * 100.0f, + ana->right_car_ratio * 100.0f, g_thr_car_alert * 100.0f, + ana->right_tree_ratio * 100.0f, g_thr_tree_alert * 100.0f, + ana->right_pond_ratio * 100.0f, g_thr_pond_alert * 100.0f, + ana->right_bunker_ratio * 100.0f, g_thr_bunker_alert * 100.0f, + ana->right_alert, ana->right_alert ? ana->right_type : "-"); } } } diff --git a/src/host_stream/kp_firmware.c b/src/host_stream/kp_firmware.c index d75d2b1..32f526b 100644 --- a/src/host_stream/kp_firmware.c +++ b/src/host_stream/kp_firmware.c @@ -334,11 +334,11 @@ int loadConfig(HOST_STREAM_INIT_OPT_T* pHostStreamInit) g_thr_tree_collision = iniparser_getint(ini, "detect:thr_tree_col", 200) / 1000.0f; g_thr_bunker_collision = iniparser_getint(ini, "detect:thr_bunker_col", 200) / 1000.0f; g_thr_pond_collision = iniparser_getint(ini, "detect:thr_pond_col", 200) / 1000.0f; - g_thr_person_alert = iniparser_getint(ini, "detect:thr_person_alt", 100) / 1000.0f; - g_thr_car_alert = iniparser_getint(ini, "detect:thr_car_alt", 100) / 1000.0f; - g_thr_tree_alert = iniparser_getint(ini, "detect:thr_tree_alt", 200) / 1000.0f; - g_thr_bunker_alert = iniparser_getint(ini, "detect:thr_bunker_alt", 100) / 1000.0f; - g_thr_pond_alert = iniparser_getint(ini, "detect:thr_pond_alt", 100) / 1000.0f; + g_thr_person_alert = iniparser_getint(ini, "detect:thr_person_alt", 200) / 1000.0f; + g_thr_car_alert = iniparser_getint(ini, "detect:thr_car_alt", 200) / 1000.0f; + g_thr_tree_alert = iniparser_getint(ini, "detect:thr_tree_alt", 300) / 1000.0f; + g_thr_bunker_alert = iniparser_getint(ini, "detect:thr_bunker_alt", 200) / 1000.0f; + g_thr_pond_alert = iniparser_getint(ini, "detect:thr_pond_alt", 200) / 1000.0f; printf("[FW] detect thresholds: grass=%.3f p_col=%.3f c_col=%.3f t_col=%.3f" " p_alt=%.3f c_alt=%.3f\n", g_thr_grass_roi, g_thr_person_collision, g_thr_car_collision, diff --git a/src/pre_post_proc/stdc_post_process.c b/src/pre_post_proc/stdc_post_process.c index 5f565f8..6fe163b 100644 --- a/src/pre_post_proc/stdc_post_process.c +++ b/src/pre_post_proc/stdc_post_process.c @@ -7,27 +7,29 @@ #include #include #include -#include #include "kp_struct.h" #include "ncpu_gen_struct.h" #include "demo_post_utils.h" #include "stdc_post_process.h" -extern unsigned int g_verbose_log; - /* Detection thresholds — runtime tunable via BLE SET / INI [detect] section */ -float g_thr_grass_roi = 0.75f; -float g_thr_person_collision = 0.10f; +float g_thr_grass_roi = 0.80f; +float g_thr_person_collision = 0.20f; float g_thr_car_collision = 0.20f; float g_thr_tree_collision = 0.20f; float g_thr_bunker_collision = 0.20f; float g_thr_pond_collision = 0.20f; -float g_thr_person_alert = 0.10f; -float g_thr_car_alert = 0.10f; -float g_thr_tree_alert = 0.20f; -float g_thr_bunker_alert = 0.10f; -float g_thr_pond_alert = 0.10f; +float g_thr_person_alert = 0.20f; +float g_thr_car_alert = 0.20f; +float g_thr_tree_alert = 0.30f; +float g_thr_bunker_alert = 0.20f; +float g_thr_pond_alert = 0.20f; + +/* Consecutive frames required before left/right alert fires (debounce) */ +#define ALERT_DEBOUNCE_FRAMES 5 +/* Consecutive frames required before collision_risk fires (shorter: safety signal) */ +#define COLLISION_DEBOUNCE_FRAMES 3 typedef struct { uint8_t *prev_roi_luma; @@ -35,6 +37,9 @@ typedef struct { uint32_t prev_roi_count; uint32_t frame_count; uint32_t consecutive_grass_frames; + uint32_t consecutive_left_frames; /* debounce counter for left alert */ + uint32_t consecutive_right_frames; /* debounce counter for right alert */ + uint32_t consecutive_collision_frames; /* debounce counter for collision_risk */ float prev_tree_roi_ratio; } stdc_runtime_state_t; @@ -260,10 +265,13 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p) ana->right_pond_ratio = (float)right_count[STDC_CLASS_POND] * inv_right; ana->right_bunker_ratio = (float)right_count[STDC_CLASS_BUNKER] * inv_right; - /* Left alert: highest-ratio class that exceeds its collision threshold */ - ana->left_alert = 0; - ana->left_type[0] = '\0'; + /* Left alert: highest-ratio class that exceeds threshold. + * Debounced: must exceed threshold for ALERT_DEBOUNCE_FRAMES consecutive + * frames before ana->left_alert fires. left_type always tracks current + * dominant class so it is correct when the debounce finally triggers. */ { + int raw_alert = 0; + ana->left_type[0] = '\0'; struct { float ratio; float thr; const char *name; } lc[] = { { ana->left_person_ratio, g_thr_person_alert, "person" }, { ana->left_car_ratio, g_thr_car_alert, "vehicle" }, @@ -274,19 +282,24 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p) float best = 0.0f; for (int i = 0; i < 5; i++) { if (lc[i].ratio >= lc[i].thr) { - ana->left_alert = 1; + raw_alert = 1; if (lc[i].ratio > best) { best = lc[i].ratio; snprintf(ana->left_type, sizeof(ana->left_type), "%s", lc[i].name); } } } + if (raw_alert) + g_stdc_state.consecutive_left_frames++; + else + g_stdc_state.consecutive_left_frames = 0; + ana->left_alert = (g_stdc_state.consecutive_left_frames >= ALERT_DEBOUNCE_FRAMES) ? 1 : 0; } - /* Right alert: same logic */ - ana->right_alert = 0; - ana->right_type[0] = '\0'; + /* Right alert: same logic with debounce */ { + int raw_alert = 0; + ana->right_type[0] = '\0'; struct { float ratio; float thr; const char *name; } rc[] = { { ana->right_person_ratio, g_thr_person_alert, "person" }, { ana->right_car_ratio, g_thr_car_alert, "vehicle" }, @@ -297,13 +310,18 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p) float best = 0.0f; for (int i = 0; i < 5; i++) { if (rc[i].ratio >= rc[i].thr) { - ana->right_alert = 1; + raw_alert = 1; if (rc[i].ratio > best) { best = rc[i].ratio; snprintf(ana->right_type, sizeof(ana->right_type), "%s", rc[i].name); } } } + if (raw_alert) + g_stdc_state.consecutive_right_frames++; + else + g_stdc_state.consecutive_right_frames = 0; + ana->right_alert = (g_stdc_state.consecutive_right_frames >= ALERT_DEBOUNCE_FRAMES) ? 1 : 0; } /* ------------------------------------------------------- @@ -325,34 +343,18 @@ int stdc_post_process(int model_id, struct kdp_image_s *image_p) ana->tree_dense = (ana->class_ratio[STDC_CLASS_TREE] > THR_TREE_DENSE) ? 1 : 0; ana->tree_approaching = (ana->tree_roi_growth > STDC_TREE_GROWTH_THR) ? 1 : 0; - ana->collision_risk = 0; - if (ana->col_person_ratio >= g_thr_person_collision) ana->collision_risk = 1; - if (ana->col_car_ratio >= g_thr_car_collision) ana->collision_risk = 1; - if (ana->col_tree_ratio >= g_thr_tree_collision) ana->collision_risk = 1; - if (ana->col_bunker_ratio >= g_thr_bunker_collision) ana->collision_risk = 1; - if (ana->col_pond_ratio >= g_thr_pond_collision) ana->collision_risk = 1; - - /* ------------------------------------------------------- - * 4. Log summary (throttled to 1Hz, verbose_log only) - * ------------------------------------------------------- */ - if (g_verbose_log) { - static struct timeval s_last_post_log = {0, 0}; - struct timeval now; - gettimeofday(&now, NULL); - long elapsed_us = (now.tv_sec - s_last_post_log.tv_sec) * 1000000L - + (now.tv_usec - s_last_post_log.tv_usec); - if (elapsed_us >= 1000000L) { - s_last_post_log = now; - printf("[STDC] frame=%u moving=%d diff=%.2f grass_roi=%.1f%% grass_time=%.1fs grass_warn=%d " - "person=%.1f%% car=%.1f%% tree=%.1f%% tree_growth=%.1f%% collision=%d\n", - ana->frame_count, ana->is_moving, ana->motion_diff, - ana->grass_roi_ratio * 100.0f, ana->grass_duration_sec, ana->grass_warning, - ana->class_ratio[STDC_CLASS_PERSON] * 100.0f, - ana->class_ratio[STDC_CLASS_CAR] * 100.0f, - ana->class_ratio[STDC_CLASS_TREE] * 100.0f, - ana->tree_roi_growth * 100.0f, - ana->collision_risk); - } + { + int raw_collision = 0; + if (ana->col_person_ratio >= g_thr_person_collision) raw_collision = 1; + if (ana->col_car_ratio >= g_thr_car_collision) raw_collision = 1; + if (ana->col_tree_ratio >= g_thr_tree_collision) raw_collision = 1; + if (ana->col_bunker_ratio >= g_thr_bunker_collision) raw_collision = 1; + if (ana->col_pond_ratio >= g_thr_pond_collision) raw_collision = 1; + if (raw_collision) + g_stdc_state.consecutive_collision_frames++; + else + g_stdc_state.consecutive_collision_frames = 0; + ana->collision_risk = (g_stdc_state.consecutive_collision_frames >= COLLISION_DEBOUNCE_FRAMES) ? 1 : 0; } return KP_SUCCESS;