From e9ab06e82333c3bd1ba96a038e74e7dbcef17760 Mon Sep 17 00:00:00 2001 From: Alberto-Audrix Date: Wed, 5 Aug 2026 13:42:16 +0700 Subject: [PATCH] fix counter bug --- counter_live_rknn.py | 19 +++++++++++++------ counter_store.py | 22 ++++++++++++++++++++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/counter_live_rknn.py b/counter_live_rknn.py index 8e6ebf8..9190895 100644 --- a/counter_live_rknn.py +++ b/counter_live_rknn.py @@ -1309,8 +1309,9 @@ def run(): frames_since_infer = 0 video_writer = None crossing_times = deque() - counter_left = 0 - counter_right = 0 + # Overlay shows daily store totals (resume-safe, resets on counting-day change). + counter_left = store.current_count_left + counter_right = store.current_count_right last_snapshot_cleanup = 0.0 counting_active = True @@ -1595,12 +1596,17 @@ def run(): st["counted"] = True st["side"] = feeder last_count_mono[feeder] = mono + _, _, counted = store.record_zone_entry(tid, feeder) + counter_left = store.current_count_left + counter_right = store.current_count_right + if not counted: + # Dedup in the store rejected this event; skip overlay/CSV. + object_tracked[tid] = (cx, cy, mono) + continue if feeder == "left": - counter_left += 1 count_left_pulse = COUNT_PULSE_FRAMES feeder_total = counter_left else: - counter_right += 1 count_right_pulse = COUNT_PULSE_FRAMES feeder_total = counter_right # Frigate-style count log, e.g. @@ -1609,7 +1615,6 @@ def run(): f"Total {OBJECT_LABEL} di {feeder_display_name(feeder)}: {feeder_total}", flush=True, ) - store.record_zone_entry(tid, feeder) if cross_logger: cross_logger.write_row( [ @@ -1654,7 +1659,9 @@ def run(): if object_crossed_frame: zone_pulse = ZONE_PULSE_FRAMES - display_total = store.display_total() + # Keep overlay aligned with daily store (also resets after cutoff). + counter_left = store.current_count_left + counter_right = store.current_count_right while crossing_times and mono - crossing_times[0] > RATE_WINDOW_SEC: crossing_times.popleft() rate = (len(crossing_times) / RATE_WINDOW_SEC * 60) if crossing_times else 0.0 diff --git a/counter_store.py b/counter_store.py index 3de4e73..320705a 100644 --- a/counter_store.py +++ b/counter_store.py @@ -97,10 +97,23 @@ class CounterStore: self.state_file.unlink(missing_ok=True) return None state = self._normalize_state(state) + # Track IDs are process-local and restart from 1 after every process + # start. Persisted dedup keys like "5_left" would silently block new + # counts that reuse those IDs, so clear them on resume while keeping + # the day's totals. + stale_ids = state.get('counted_event_ids') or [] + if stale_ids: + self.log( + f"Cleared {len(stale_ids)} persisted track dedup keys " + f"(track IDs reset on restart)" + ) + state['counted_event_ids'] = [] self.log( f"Resumed {current_date} with total={state['count']} " f"(left={state['count_left']} right={state['count_right']})" ) + with open(self.state_file, 'w', encoding='utf-8') as f: + json.dump(state, f, indent=2, ensure_ascii=False) return state except Exception as exc: self.log(f'Failed to load state file: {exc}') @@ -134,7 +147,10 @@ class CounterStore: self.log(f'Started counting day {counting_date} ({self.object_label})') def record_zone_entry(self, track_id, feeder): - """Record a sack entering a feeder zone. feeder: 'left' | 'right'.""" + """Record a sack entering a feeder zone. feeder: 'left' | 'right'. + + Returns (total_count, day_started, counted). + """ if feeder not in ('left', 'right'): raise ValueError(f"feeder must be 'left' or 'right', got {feeder!r}") with self.state_lock: @@ -144,6 +160,7 @@ class CounterStore: self._start_new_day(counting_date) day_started = True + counted = False event_key = f"{track_id}_{feeder}" if event_key not in self.current_state['counted_event_ids']: self.current_state['count'] += 1 @@ -152,6 +169,7 @@ class CounterStore: else: self.current_state['count_right'] += 1 self.current_state['counted_event_ids'].append(event_key) + counted = True self.log( f'Counted {feeder} feeder (track {track_id}) | {counting_date} ' f'total: {self.current_state["count"]} ' @@ -162,7 +180,7 @@ class CounterStore: self.current_state['last_detection_time'] = datetime.now().isoformat() self.save_state() - return self.current_state['count'], day_started + return self.current_state['count'], day_started, counted def _persist_day(self): state = self.current_state