From f7ef038def7c9c27406322658e1057338043f888 Mon Sep 17 00:00:00 2001 From: Alberto-Audrix Date: Fri, 24 Jul 2026 11:04:20 +0700 Subject: [PATCH] first commit --- .gitignore | 220 +++++ CONTROL.md | 179 ++++ DEPLOY.md | 272 ++++++ config.env.example | 245 +++++ counter_dashboard.py | 770 ++++++++++++++++ counter_live_rknn.py | 1720 +++++++++++++++++++++++++++++++++++ counter_store.py | 256 ++++++ env.example | 117 +++ requirements.txt | 6 + templates/dashboard.html | 1220 +++++++++++++++++++++++++ templates/snapshots.html | 489 ++++++++++ zenai-ktc-counter.service | 32 + zenai-ktc-dashboard.service | 32 + zone_preview.jpg | Bin 0 -> 240106 bytes 14 files changed, 5558 insertions(+) create mode 100644 .gitignore create mode 100644 CONTROL.md create mode 100644 DEPLOY.md create mode 100644 config.env.example create mode 100644 counter_dashboard.py create mode 100644 counter_live_rknn.py create mode 100644 counter_store.py create mode 100644 env.example create mode 100644 requirements.txt create mode 100644 templates/dashboard.html create mode 100644 templates/snapshots.html create mode 100644 zenai-ktc-counter.service create mode 100644 zenai-ktc-dashboard.service create mode 100644 zone_preview.jpg diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3ec7d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,220 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +*.lcov +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +# Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +# poetry.lock +# poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +# pdm.lock +# pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +# pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi/* +!.pixi/config.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule* +celerybeat.pid + +# Redis +*.rdb +*.aof +*.pid + +# RabbitMQ +mnesia/ +rabbitmq/ +rabbitmq-data/ + +# ActiveMQ +activemq-data/ + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# .idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ +# Temporary file for partial code execution +tempCodeRunnerFile.py + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ + +# Streamlit +.streamlit/secrets.toml diff --git a/CONTROL.md b/CONTROL.md new file mode 100644 index 0000000..2579ac7 --- /dev/null +++ b/CONTROL.md @@ -0,0 +1,179 @@ +# Runtime Control — Start/Stop Counting + +The counter can pause and resume object detection & counting **on the fly**, +without restarting the process. There are three interchangeable ways to control +it, and they all converge on a single source of truth: the **control file**. + +- **Control file** — a small JSON file the counter polls. +- **TCP control socket** — line commands over the network that update the file. +- **Dashboard button** — a COUNTING ON/OFF toggle that writes the file via its API. + +When counting is **OFF**, the counter skips inference entirely (no detection, no +counting, lower CPU/NPU load), the video/live stream keeps running, and a +`COUNTING PAUSED` badge is drawn on the frame. When **ON**, normal counting +resumes. + +--- + +## 1. Enable runtime control + +Runtime control is opt-in. In your `.env`: + +```ini +# Master switch — required for ALL control methods (file, socket, dashboard). +CONTROL_ENABLED=true + +# Shared control file. MUST be identical for the counter and the dashboard. +CONTROL_FILE=/opt/zenai-ktc-counter/control.json + +# Counting state on startup / when the control file does not exist yet. +CONTROL_DEFAULT_COUNTING=true + +# How often (seconds) the counter re-reads the control file. +CONTROL_POLL_SEC=1.0 +``` + +When `CONTROL_ENABLED=false`, the counter always counts, the control file is +ignored, and the dashboard hides the toggle button. + +> Changes take effect within `CONTROL_POLL_SEC` seconds (default 1s), because the +> counter re-reads the file on a timer. + +--- + +## 2. Control file + +### Format + +```json +{ "counting": true } +``` + +- `"counting": true` → counting **ON** +- `"counting": false` → counting **OFF** (paused) + +The counter creates this file on startup (seeded from `CONTROL_DEFAULT_COUNTING`) +if it does not exist. All writers (counter, dashboard, socket) write it +**atomically** (temp file + rename), so readers never see a half-written file. + +### Toggle by editing the file + +Pause counting: + +```bash +printf '{"counting": false}\n' > /opt/bytetrack-counter/control.json +``` + +Resume counting: + +```bash +printf '{"counting": true}\n' > /opt/bytetrack-counter/control.json +``` + +Check current state: + +```bash +cat /opt/bytetrack-counter/control.json +``` + +> Use the exact path from your `CONTROL_FILE` setting. If you write it by hand, +> keep it valid JSON — an unreadable file falls back to `CONTROL_DEFAULT_COUNTING`. + +--- + +## 3. TCP control socket + +The socket lets you toggle counting over the network. It updates the same control +file, so changes still apply within `CONTROL_POLL_SEC`. + +### Enable + +```ini +# Requires CONTROL_ENABLED=true as well. +CONTROL_SOCKET_ENABLED=true + +# 127.0.0.1 = local only. Use 0.0.0.0 to allow remote clients. +CONTROL_SOCKET_HOST=127.0.0.1 + +# TCP port. +CONTROL_SOCKET_PORT=5090 +``` + +### Commands + +Newline-terminated, case-insensitive. One connection can send multiple commands. + +| Command | Effect | Reply | +|----------------------------|-------------------------------|-----------------------| +| `START` / `RESUME` / `ON` | Counting ON | `OK counting=on` | +| `STOP` / `PAUSE` / `OFF` | Counting OFF | `OK counting=off` | +| `TOGGLE` | Flip current state | `OK counting=on/off` | +| `STATUS` / `GET` | Report state (no change) | `OK counting=on/off` | +| *(anything else)* | — | `ERR unknown command` | + +### Examples + +Using `nc` (netcat): + +```bash +printf 'STOP\n' | nc 127.0.0.1 5090 +printf 'START\n' | nc 127.0.0.1 5090 +printf 'TOGGLE\n' | nc 127.0.0.1 5090 +printf 'STATUS\n' | nc 127.0.0.1 5090 +``` + +Using bash `/dev/tcp` (no netcat needed): + +```bash +exec 3<>/dev/tcp/127.0.0.1/5090 +printf 'STATUS\n' >&3 +head -n1 <&3 +exec 3>&- +``` + +Python client: + +```python +import socket + +def control(cmd, host="127.0.0.1", port=5090): + with socket.create_connection((host, port), timeout=2) as s: + s.sendall((cmd + "\n").encode()) + return s.recv(256).decode().strip() + +print(control("STATUS")) # OK counting=on +print(control("STOP")) # OK counting=off +``` + +> **Security:** the socket has **no authentication**. Keep `CONTROL_SOCKET_HOST` +> on `127.0.0.1`, or restrict access with a firewall / trusted network if you +> bind to `0.0.0.0`. + +--- + +## 4. Dashboard button + +When `CONTROL_ENABLED=true`, the dashboard header shows a **COUNTING ON/OFF** +button (green when on, red when off). Clicking it flips the state immediately. + +The dashboard must point at the **same** `CONTROL_FILE` as the counter (set it in +the dashboard's environment too). The dashboard exposes: + +- `GET /api/control` → `{ "enabled": true, "counting": true }` +- `POST /api/control` with body `{ "counting": false }` → writes the control file + (returns `403` if `CONTROL_ENABLED=false`) + +--- + +## Notes & behavior + +- **Single source of truth:** the socket and dashboard both write the control + file; the counter reacts only to the file. This avoids race conditions between + control methods. +- **Latency:** expect up to `CONTROL_POLL_SEC` (default 1s) between issuing a + command and the counter reacting. +- **Live stream keeps running** while paused, so you still see the camera feed + with the `COUNTING PAUSED` overlay. +- **Shared path requirement:** counter and dashboard must use the same + `CONTROL_FILE`. If they run on different machines, use the TCP socket (or a + shared network path) instead. diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 0000000..6e84133 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,272 @@ +# ZenAI KTC Counter — Edge Deployment Guide + +Production deployment for **RK3588** (or compatible RKNN NPU) edge devices running a +**zone-based sack feeder counter** (left / right feeders): + +| Component | Script | systemd unit | +|-----------|--------|--------------| +| RTSP counter (RKNN + ByteTrack + zones) | `counter_live_rknn.py` | `zenai-ktc-counter.service` | +| Web dashboard (Flask) | `counter_dashboard.py` | `zenai-ktc-dashboard.service` | + +Both processes share a single `.env` file and read/write the same SQLite database and state JSON. + +**Counting model:** two rectangular zones (left + right). A sack is counted once when its +centroid **enters** a zone. Left zone → left feeder; right zone → right feeder. + +--- + +## 1. Prerequisites + +### Hardware & OS + +- RK3588 board (or Jetson/RK device with RKNN Lite runtime) +- Linux with systemd +- Network access to the RTSP camera stream + +### System packages + +```bash +sudo apt update +sudo apt install -y python3 python3-venv python3-pip ffmpeg libgl1 +``` + +`ffmpeg` is required for low-latency RTSP capture via OpenCV. `libgl1` is often needed for `opencv-python` on headless systems. + +### RKNN model + +Export or copy your `.rknn` model to the device, e.g.: + +```text +/opt/models/your_model.rknn +``` + +Set `MODEL_PATH` in `.env` to match. The model class count must match `NUM_CLASSES`, and `OBJECT_CLASS_ID` must point at the class you count. + +--- + +## 2. Directory layout + +Default paths used by the service files and `env.example`: + +```text +/opt/zenai-ktc-python/ # application code (this repo) +├── counter_live_rknn.py +├── counter_dashboard.py +├── counter_store.py +├── templates/ +├── venv/ # Python virtual environment (created during install) +├── .env # runtime config (not in git) +├── env.example # template — copy to .env +└── DEPLOY.md + +/opt/zenai-ktc-counter/ # persistent runtime data (created automatically) +├── counter.db # SQLite daily records +├── current_counter.json # live counting-day state +├── snapshots/ # zone-entry/detect JPEGs (if enabled) +└── crossings.csv # optional per-event CSV + +/opt/models/ # RKNN models (deploy separately) +/dev/shm/zenai-ktc-counter/ # live JPEG frame for dashboard video (tmpfs) +``` + +--- + +## 3. Install application + +### 3.1 Copy code to the device + +```bash +sudo mkdir -p /opt/zenai-ktc-python +sudo rsync -av --exclude venv --exclude .env --exclude __pycache__ \ + ./ /opt/zenai-ktc-python/ +# Or: sudo git clone /opt/zenai-ktc-python +``` + +### 3.2 Create virtual environment and install dependencies + +```bash +cd /opt/zenai-ktc-python +sudo python3 -m venv venv +sudo ./venv/bin/pip install --upgrade pip +sudo ./venv/bin/pip install -r requirements.txt +``` + +> `rknn-toolkit-lite2` is platform-specific. Install on the target ARM device, not on a Windows dev machine. + +### 3.3 Create runtime config + +```bash +cd /opt/zenai-ktc-python +sudo cp env.example .env +sudo nano .env +``` + +**Minimum values to edit before starting:** + +| Variable | Description | +|----------|-------------| +| `SOURCE` | RTSP URL or local video file path | +| `MODEL_PATH` | Path to your `.rknn` model on device | +| `NUM_CLASSES` | Must match the exported model | +| `OBJECT_CLASS_ID` | Class index of the object being counted | +| `CLASS_OBJECT` / `OBJECT_LABEL` | Labels stored in DB (e.g. `karung`) | +| `ZONE_LEFT_*_FRAC` / `ZONE_RIGHT_*_FRAC` | Feeder zone rectangles (tune per camera) | +| `SECRET_KEY` | Random string for Flask sessions | + +Ensure `STATE_FILE` and `DB_PATH` both live under `/opt/zenai-ktc-counter/` so data survives reboots (avoid `/tmp` in production). + +### 3.4 Create data directories (optional — app creates most paths automatically) + +```bash +sudo mkdir -p /opt/zenai-ktc-counter /opt/models /dev/shm/zenai-ktc-counter +``` + +--- + +## 4. Install systemd services + +```bash +cd /opt/zenai-ktc-python +sudo cp zenai-ktc-counter.service zenai-ktc-dashboard.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable zenai-ktc-counter zenai-ktc-dashboard +sudo systemctl start zenai-ktc-counter +sudo systemctl start zenai-ktc-dashboard +``` + +The dashboard unit starts **after** the counter unit (`After=zenai-ktc-counter.service`). + +### Verify + +```bash +systemctl status zenai-ktc-counter +systemctl status zenai-ktc-dashboard +journalctl -u zenai-ktc-counter -f +``` + +Open the dashboard in a browser: + +```text +http://:5000 +``` + +(Port is set by `DASHBOARD_PORT` in `.env`, default `5000`.) + +--- + +## 5. Tuning feeder zones + +Zones are axis-aligned rectangles. Defaults cover the left and right sides of the frame: + +```ini +ZONE_LEFT_X1_FRAC=0.00 +ZONE_LEFT_Y1_FRAC=0.20 +ZONE_LEFT_X2_FRAC=0.35 +ZONE_LEFT_Y2_FRAC=0.85 + +ZONE_RIGHT_X1_FRAC=0.65 +ZONE_RIGHT_Y1_FRAC=0.20 +ZONE_RIGHT_X2_FRAC=1.00 +ZONE_RIGHT_Y2_FRAC=0.85 +``` + +For pixel-perfect placement, set absolute coordinates instead (they override fractions): + +```ini +ZONE_LEFT_X1=40 +ZONE_LEFT_Y1=120 +ZONE_LEFT_X2=420 +ZONE_LEFT_Y2=900 +``` + +Enable `DEBUG_TRACKING=true` temporarily to log zone entries in the journal. + +--- + +## 6. Operations + +### Restart after config change + +```bash +sudo systemctl restart zenai-ktc-counter +sudo systemctl restart zenai-ktc-dashboard +``` + +### View logs + +```bash +journalctl -u zenai-ktc-counter -n 100 --no-pager +journalctl -u zenai-ktc-dashboard -n 100 --no-pager +``` + +### Stop services + +```bash +sudo systemctl stop zenai-ktc-dashboard zenai-ktc-counter +``` + +The counter handles `SIGTERM` gracefully — it finishes the current frame, persists state to SQLite, then exits. + +### Update application code + +```bash +cd /opt/zenai-ktc-python +sudo systemctl stop zenai-ktc-dashboard zenai-ktc-counter +# rsync or git pull new code +sudo ./venv/bin/pip install -r requirements.txt # if dependencies changed +sudo systemctl start zenai-ktc-counter zenai-ktc-dashboard +``` + +--- + +## 7. Troubleshooting + +| Symptom | Things to check | +|---------|-----------------| +| Counter won't start | `journalctl -u zenai-ktc-counter`; verify `MODEL_PATH` exists; RKNN drivers installed | +| No RTSP frames | Ping camera; test with `ffplay `; check `OPENCV_FFMPEG_CAPTURE_OPTIONS` | +| Dashboard shows 0 count | `STATE_FILE` in `.env` must match between counter and dashboard; check file exists | +| Live video blank | `LIVE_STREAM_ENABLED=true`; path matches `LIVE_STREAM_FRAME_PATH` in both processes | +| Wrong feeder / missed counts | Tune `ZONE_*_FRAC`, `CONF`, ByteTrack thresholds; enable `DEBUG_TRACKING=true` | +| Service keeps restarting | `journalctl -u zenai-ktc-counter -e`; often missing model, bad RTSP URL, or venv not created | + +### Manual test (without systemd) + +```bash +cd /opt/zenai-ktc-python +source venv/bin/activate +python counter_live_rknn.py # terminal 1 +python counter_dashboard.py # terminal 2 +``` + +--- + +## 8. Optional: reverse proxy + +For HTTPS or port 80 access, put nginx in front of the dashboard: + +```nginx +server { + listen 80; + server_name counter.example.com; + + location / { + proxy_pass http://127.0.0.1:5000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_buffering off; # required for /api/live-video MJPEG stream + proxy_read_timeout 3600s; # keep long-lived MJPEG connections open + proxy_send_timeout 3600s; + } +} +``` + +--- + +## 9. Security notes + +- Change `SECRET_KEY` from the default before exposing the dashboard on a network. +- Services currently run as `root` for simplicity on edge devices. For hardened deployments, create a dedicated user, chown `/opt/zenai-ktc-counter`, and update the `User=` / `Group=` lines in the service files. +- Do not commit `.env` — it may contain RTSP credentials. +- Set `FLASK_DEBUG=false` in production. diff --git a/config.env.example b/config.env.example new file mode 100644 index 0000000..1961f5f --- /dev/null +++ b/config.env.example @@ -0,0 +1,245 @@ +# ============================================================================= +# ZenAI KTC — Edge RK3588 sack feeder zone counter + dashboard +# Shared config for: counter_live_rknn.py + counter_dashboard.py +# Copy to .env on device: cp config.env.example .env && nano .env +# ============================================================================= + +# --- Core paths --- +# Root output directory (logs, DB, video, CSV) +OUTPUT_DIR=/opt/zenai-ktc-counter +# SQLite database path for daily counter records & zone-entry logs +DB_PATH=/opt/zenai-ktc-counter/ktc_counter.db +# JSON file persisting the current active counting day state +STATE_FILE=/opt/zenai-ktc-counter/current_counter.json + +# --- Input source --- +# RTSP / HTTP live stream, or a local video file path +SOURCE=rtsp://user:pass@192.168.0.100:554/stream1 +# FFmpeg capture options passed to cv2.VideoCapture (RTSP low-latency flags) +OPENCV_FFMPEG_CAPTURE_OPTIONS=rtsp_transport;tcp|fflags;nobuffer|flags;low_delay + +# --- RKNN model --- +# Path to exported .rknn model (YOLO format, e.g. yolo11n.rknn) +MODEL_PATH=/opt/models/yolo9t.rknn +# Input image size for the model (square, e.g. 320 → 320×320) +IMGSZ=320 +# Use FP16 inference on NPU (true/false); currently unused in ByteTrack variant +HALF=false +# NPU core mask: 1=core0, 2=core1, 3=core0+core1, 7=all three +CORE_MASK=7 +# Compute device index (reserved; not used at runtime) +DEVICE=0 + +# --- YOLO decoder --- +# Number of object classes the model outputs +NUM_CLASSES=2 +# Apply sigmoid to raw class scores (true/false); set true if model head uses BCE logits +SCORE_SIGMOID=false + +# --- Detection --- +# Confidence threshold – detections below this are discarded before NMS +CONF=0.3 +# NMS IoU threshold (0-1): boxes overlapping the top box by more than this are +# suppressed. RAISE it (e.g. 0.6-0.7) if two close/overlapping objects are being +# merged into one and their separate boxes get suppressed. Lower = more aggressive +# merging. Default 0.45. +NMS_IOU=0.45 + +# --- ByteTrack tracking --- +# Detections with score >= this get priority matching in the first association stage +TRACK_HIGH_THRESH=0.5 +# Detections with score between this and TRACK_HIGH_THRESH are matched in the second stage +TRACK_LOW_THRESH=0.1 +# IoU threshold for the first-stage association (0–1). Higher = stricter overlap required +TRACK_MATCH_THRESH=0.8 +# Frames a track survives without a match before being permanently removed +TRACK_BUFFER=30 +# Minimum consecutive (or total) hits needed before a track is considered confirmed +TRACK_MIN_HITS=3 + +# --- ID-switch counting guards --- +# When a track's ID changes right at the counting line, one physical object can be +# counted twice (two IDs cross) or missed (neither ID sees the full transition). +# These two guards correct for that. +# +# Dedup guard (prevents double counting): after a zone entry, a second entry in +# the SAME feeder within DEDUP_FRAMES frames and DEDUP_PX centroid pixels is +# ignored (treated as the same object under a new ID). +DEDUP_FRAMES=15 +DEDUP_PX=60 +# To DISABLE the dedup guard, set DEDUP_PX=-1 (distance check can never match). +# +# Inheritance guard (prevents missed counting): when a brand-new track appears, it +# inherits the last position of a recently-seen nearby track (within INHERIT_SEC +# seconds and INHERIT_PX horizontal pixels) so zone entry is still detected +# across the ID switch. +INHERIT_SEC=1.0 +INHERIT_PX=60 +# To DISABLE the inheritance guard, set INHERIT_PX=-1 (distance check can never match). + +# --- Feeder cooldown (seconds) --- +# After a sack is counted on a feeder, ignore further counts on that same feeder +# for this many seconds. Useful when multiple detections/IDs fire for one sack. +# 0 = disabled. +ZONE_COOLDOWN_LEFT_SEC=3 +ZONE_COOLDOWN_RIGHT_SEC=3 + +# --- Display --- +# Site name shown on the dashboard header (top-right) +SITE_NAME=ZenAi + +# --- Object class names --- +# Camera / location identifier shown in HUD and stored in DB +CAMERA_NAME=ZenAi +# Label used for batch grouping in the database +OBJECT_LABEL=object +# Class name for the counted object (must match model class order) +CLASS_OBJECT=object +# Model class ID for the object being counted (default 0) +OBJECT_CLASS_ID=0 + +# --- Feeder zones (left / right) --- +# Rectangular zones mark the left and right sack feeders. +# Count once when a track centroid ENTERS a zone (outside → inside). +# Absolute pixel overrides (ZONE_*_X1/Y1/X2/Y2) win over fractions when set. +# +# Left feeder zone (default: left third of the frame) +ZONE_LEFT_X1= +ZONE_LEFT_Y1= +ZONE_LEFT_X2= +ZONE_LEFT_Y2= +ZONE_LEFT_X1_FRAC=0.02 +ZONE_LEFT_Y1_FRAC=0.10 +ZONE_LEFT_X2_FRAC=0.440 +ZONE_LEFT_Y2_FRAC=1.00 +# +# Right feeder zone (full right column) +ZONE_RIGHT_X1= +ZONE_RIGHT_Y1= +ZONE_RIGHT_X2= +ZONE_RIGHT_Y2= +ZONE_RIGHT_X1_FRAC=0.490 +ZONE_RIGHT_Y1_FRAC=0.10 +ZONE_RIGHT_X2_FRAC=0.98 +ZONE_RIGHT_Y2_FRAC=1.00 + +# --- Counting day management --- +# Daily cutoff time (HH:MM) – a new counting day starts after this time and the +# previous day's counter_left / counter_right totals are finalized in the database. +# CUTOFF_TIME is an alias used by the dashboard; DAILY_CUTOFF_TIME takes priority in counter_live_rknn.py. +DAILY_CUTOFF_TIME=17:00 +CUTOFF_TIME=17:00 + +# --- CSV export --- +# Write per-crossing events to a CSV file (true/false) +EXPORT_CSV=true +# Path where the crossing CSV is written +CROSS_CSV=/opt/batch-counter/crossings.csv + +# --- Crossing snapshots --- +# Save an annotated frame image every time an object enters a feeder zone and the +# counter increases (true/false, default: false). Written to /cross/ +# (filename: __id_f.jpg) +SAVE_CROSS_SNAPSHOT=false +# Also save one snapshot the first time each object is detected, before it enters +# a zone (true/false, default: false). Written to /detect/ with the same track id so +# it can be correlated with the zone-entry snapshot +# (filename: _detect_id_f.jpg) +SAVE_DETECT_SNAPSHOT=false +# Base directory for snapshots (detect/ and cross/ subfolders are created inside). +# The dashboard reads this same path to display the snapshot gallery, so keep it +# identical for both the counter and the dashboard. +CROSS_SNAPSHOT_DIR=/opt/batch-counter/snapshots +# JPEG quality for snapshots (1-100) +CROSS_SNAPSHOT_QUALITY=85 +# Retention: keep at most this many snapshot files (detect + cross combined); +# oldest are deleted first (0 = unlimited) +CROSS_SNAPSHOT_MAX_FILES=1000 +# Retention: delete snapshots older than this many days (0 = never by age) +CROSS_SNAPSHOT_MAX_AGE_DAYS=7 +# Run the cleanup sweep at most once every N seconds +CROSS_SNAPSHOT_CLEANUP_SEC=60 + +# --- Rate / performance --- +# Enable motion detection pre-filter: skip inference on frames with no movement +# (true/false, default: false), saving NPU/CPU load. Motion is measured by the +# fraction of pixels that changed (localized-motion aware), NOT the whole-frame +# average, so an object entering the edge of the frame is detected immediately. +MOTION_DETECTION_ENABLED=false +# Per-pixel intensity change (0-255) for a pixel to count as "moved". Lower = more +# sensitive to subtle movement. Default 25. +MOTION_PIXEL_DELTA=25 +# Fraction of frame pixels (0-1) that must change to trigger inference. Lower = +# more sensitive / detects smaller or farther objects sooner. Default 0.002 (0.2%). +MOTION_MIN_AREA_FRAC=0.002 +# Heartbeat: always run inference at least every N frames even with no detected +# motion, so a slow or barely-moving object is never missed for long. Default 15. +MOTION_HEARTBEAT_FRAMES=15 +# (Deprecated) old whole-frame mean-difference threshold; no longer used. +MOTION_THRESHOLD=5.0 + +# --- Runtime control (start/stop counting on the fly) --- +# When true, the counter watches a JSON control file and pauses/resumes object +# detection & counting based on its "counting" flag. The dashboard shows a +# COUNTING ON/OFF toggle button that writes this file. When false, the counter +# always counts and the dashboard hides the toggle. (true/false, default: false) +CONTROL_ENABLED=false +# Path to the shared control file. MUST be identical for the counter and the +# dashboard so the toggle takes effect. Contents: {"counting": true|false} +CONTROL_FILE=/opt/bytetrack-counter/control.json +# Counting state to assume on startup / when the control file does not exist yet. +CONTROL_DEFAULT_COUNTING=true +# How often (seconds) the counter re-reads the control file. Default 1.0. +CONTROL_POLL_SEC=1.0 +# Optional TCP control socket (requires CONTROL_ENABLED=true). Lets you toggle +# counting over the network with line commands. It updates the same control file, +# so changes apply within CONTROL_POLL_SEC. (true/false, default: false) +# Commands (newline-terminated): START|RESUME|ON, STOP|PAUSE|OFF, TOGGLE, STATUS +# e.g. printf 'STOP\n' | nc 127.0.0.1 5090 +CONTROL_SOCKET_ENABLED=false +# Bind address for the control socket. Use 127.0.0.1 for local-only, 0.0.0.0 to +# allow remote clients (no auth — protect with firewall / trusted network). +CONTROL_SOCKET_HOST=127.0.0.1 +# Control socket TCP port. +CONTROL_SOCKET_PORT=5090 + +# 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 +WARMUP_FRAMES=30 +# Delay in seconds between stream reconnection attempts +RECONNECT_DELAY_SEC=3 +# Maximum reconnection attempts (0 = infinite) +MAX_RECONNECT_ATTEMPTS=0 +# Seconds after which a tracked but unseen object is pruned from the active set +TRACKED_PRUNE_SEC=300 + +# --- Video recording --- +# Save annotated frames to segmented MP4 files (true/false) +RECORD_VIDEO=false +# Duration in seconds of each video segment file +VIDEO_SEGMENT_SEC=3600 +# Output video FPS (fallback if source FPS is unknown or ≤ 1) +OUTPUT_FPS=15 + +# --- Live stream snapshot --- +# Periodically write the latest annotated frame as JPEG for an external web server +LIVE_STREAM_ENABLED=false +# Path to the shared-memory snapshot file (served by nginx / lighttpd) +LIVE_STREAM_FRAME_PATH=/dev/shm/zenai-ktc-counter/live_frame.jpg +# JPEG quality (1–100) +LIVE_STREAM_QUALITY=75 +# Write the snapshot every N frames (lower = more frequent updates) +LIVE_STREAM_EVERY_N=2 + +# --- Dashboard (counter_dashboard.py) --- +# Flask secret key for session/cookie signing — change in production! +SECRET_KEY=change-me-in-production +# Bind address for the Flask web server +DASHBOARD_HOST=0.0.0.0 +# Listen port for the dashboard web UI +DASHBOARD_PORT=5000 +# Enable Flask debug mode (true/false) — auto-reloads on code changes; disable in production +FLASK_DEBUG=false +# Fallback name for the active counting-day JSON state file used by the dashboard +CURRENT_COUNTER_PATH=/opt/zenai-ktc-counter/current_counter.json \ No newline at end of file diff --git a/counter_dashboard.py b/counter_dashboard.py new file mode 100644 index 0000000..357d077 --- /dev/null +++ b/counter_dashboard.py @@ -0,0 +1,770 @@ +#!/usr/bin/env python3 +""" +Edge production counter dashboard. +Reads counter.db + current_counter.json from the counter stack. +Tracks daily left/right feeder sack counts per counting day (no batches). +Default port 5000. +""" + +import json +import os +import re +import sqlite3 +import time +from io import BytesIO +from pathlib import Path +from datetime import datetime, timedelta + +from openpyxl import Workbook +from openpyxl.styles import Font, Alignment, PatternFill, Border, Side + +from flask import Flask, render_template, jsonify, request, Response, send_file +from werkzeug.serving import WSGIRequestHandler + +from dotenv import load_dotenv +load_dotenv() + + +app = Flask(__name__, template_folder="templates") +app.config["SECRET_KEY"] = os.getenv("SECRET_KEY", "change-me-in-production") + +_DEFAULT_DIR = "/opt/jetson-counter" +DB_PATH = os.getenv("DB_PATH", f"{_DEFAULT_DIR}/jetson_counter.db") +CURRENT_COUNTER_PATH = os.getenv("STATE_FILE", os.getenv("CURRENT_COUNTER_PATH", f"{_DEFAULT_DIR}/current_counter.json")) +CUTOFF_TIME = os.getenv("CUTOFF_TIME", os.getenv("DAILY_CUTOFF_TIME", "20:00")) + +LIVE_STREAM_FRAME_PATH = os.getenv("LIVE_STREAM_FRAME_PATH", "/dev/shm/jetson-counter/live_frame.jpg") + +CROSS_SNAPSHOT_DIR = os.getenv("CROSS_SNAPSHOT_DIR", f"{_DEFAULT_DIR}/snapshots") +SAVE_DETECT_SNAPSHOT = os.getenv("SAVE_DETECT_SNAPSHOT", "false").lower() == "true" + +CONTROL_ENABLED = os.getenv("CONTROL_ENABLED", "false").lower() == "true" +CONTROL_FILE = os.getenv("CONTROL_FILE", f"{_DEFAULT_DIR}/control.json") +CONTROL_DEFAULT_COUNTING = os.getenv("CONTROL_DEFAULT_COUNTING", "true").lower() == "true" + +SITE_NAME = os.getenv("SITE_NAME", "LIVE") + +DASHBOARD_PORT = int(os.getenv("DASHBOARD_PORT", "5000")) +DASHBOARD_HOST = os.getenv("DASHBOARD_HOST", "0.0.0.0") +FLASK_DEBUG = os.getenv("FLASK_DEBUG", "false").lower() == "true" + +@app.route("/api/live-video") +def api_live_video(): + if not os.path.isfile(LIVE_STREAM_FRAME_PATH): + return jsonify({"success": False, "error": "Live stream frame not available yet"}), 503 + + def generate(): + consecutive_fails = 0 + MAX_FAILS = 30 + while True: + try: + with open(LIVE_STREAM_FRAME_PATH, "rb") as f: + jpeg = f.read() + if not jpeg or len(jpeg) < 2 or jpeg[:2] != b"\xff\xd8": + consecutive_fails += 1 + if consecutive_fails >= MAX_FAILS: + return + time.sleep(0.05) + continue + consecutive_fails = 0 + yield (b"--frame\r\n" + b"Content-Type: image/jpeg\r\n\r\n" + jpeg + b"\r\n") + except FileNotFoundError: + consecutive_fails += 1 + if consecutive_fails >= MAX_FAILS: + return + time.sleep(1.0) + continue + except Exception: + consecutive_fails += 1 + if consecutive_fails >= MAX_FAILS: + return + time.sleep(0.5) + continue + time.sleep(0.05) + return Response(generate(), mimetype="multipart/x-mixed-replace; boundary=frame") + + +_SNAP_RE = re.compile( + r"^(?P\d{8}_\d{6}_\d{3})_(?Pdetect|left|right)_id(?P\d+)_f(?P\d+)\.jpg$" +) + + +def _parse_snapshot(path, category): + m = _SNAP_RE.match(path.name) + if not m: + return None + try: + dt = datetime.strptime(m.group("ts"), "%Y%m%d_%H%M%S_%f") + except ValueError: + dt = datetime.fromtimestamp(path.stat().st_mtime) + kind = m.group("kind") + return { + "file": f"{category}/{path.name}", + "category": category, + "kind": kind, + "track_id": int(m.group("tid")), + "frame": int(m.group("frame")), + "timestamp": dt.isoformat(), + "mtime": path.stat().st_mtime, + } + + +def _collect_snapshots(): + base = os.path.abspath(CROSS_SNAPSHOT_DIR) + items = [] + for category in ("cross", "detect"): + sub = os.path.join(base, category) + if not os.path.isdir(sub): + continue + for name in os.listdir(sub): + if not name.lower().endswith(".jpg"): + continue + info = _parse_snapshot(Path(sub) / name, category) + if info: + items.append(info) + items.sort(key=lambda x: x["mtime"], reverse=True) + return items + + +@app.route("/api/snapshots") +def api_snapshots(): + try: + kind = request.args.get("kind", "all") + track_id = request.args.get("track_id", type=int) + date = request.args.get("date") + limit = request.args.get("limit", 200, type=int) + + items = _collect_snapshots() + if kind and kind != "all": + if kind == "cross": + items = [i for i in items if i["category"] == "cross"] + elif kind == "detect": + items = [i for i in items if i["category"] == "detect"] + elif kind in ("left", "right"): + items = [i for i in items if i["kind"] == kind] + if track_id is not None: + items = [i for i in items if i["track_id"] == track_id] + if date: + items = [i for i in items if i["timestamp"][:10] == date] + + total = len(items) + items = items[:limit] + for i in items: + i.pop("mtime", None) + return jsonify({"success": True, "total": total, "count": len(items), "snapshots": items}) + except Exception as e: + return jsonify({"success": False, "error": str(e), "snapshots": []}), 200 + + +@app.route("/api/snapshot-image//") +def api_snapshot_image(category, filename): + if category not in ("cross", "detect"): + return jsonify({"success": False, "error": "invalid category"}), 404 + base = os.path.abspath(os.path.join(CROSS_SNAPSHOT_DIR, category)) + requested = os.path.abspath(os.path.join(base, filename)) + if not requested.startswith(base + os.sep) or not os.path.isfile(requested): + return jsonify({"success": False, "error": "not found"}), 404 + return send_file(requested, mimetype="image/jpeg") + + +def _ensure_db(): + conn = sqlite3.connect(DB_PATH) + cur = conn.cursor() + cur.execute( + """ + CREATE TABLE IF NOT EXISTS daily_counters ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + counting_date TEXT NOT NULL, + camera_name TEXT NOT NULL, + object_label TEXT NOT NULL, + total_count INTEGER NOT NULL DEFAULT 0, + total_left INTEGER NOT NULL DEFAULT 0, + total_right INTEGER NOT NULL DEFAULT 0, + start_time TEXT, + end_time TEXT, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(counting_date, camera_name, object_label) + ) + """ + ) + conn.commit() + conn.close() + +_ensure_db() + + +def get_db(): + conn = sqlite3.connect(DB_PATH) + conn.row_factory = sqlite3.Row + return conn + + +def get_counting_date(dt=None, cutoff_str=CUTOFF_TIME): + if dt is None: + dt = datetime.now() + cutoff = datetime.strptime(cutoff_str, "%H:%M").time() + if dt.time() < cutoff: + return dt.date().isoformat() + return (dt.date() + timedelta(days=1)).isoformat() + + +@app.route("/") +def index(): + return render_template( + "dashboard.html", + site_name=SITE_NAME, + show_detect=SAVE_DETECT_SNAPSHOT, + control_enabled=CONTROL_ENABLED, + ) + + +def _read_counting_flag(): + try: + with open(CONTROL_FILE, "r", encoding="utf-8") as f: + return bool(json.load(f).get("counting", CONTROL_DEFAULT_COUNTING)) + except FileNotFoundError: + return CONTROL_DEFAULT_COUNTING + except Exception: + return CONTROL_DEFAULT_COUNTING + + +def _write_counting_flag(counting): + os.makedirs(os.path.dirname(CONTROL_FILE) or ".", exist_ok=True) + tmp = f"{CONTROL_FILE}.tmp" + with open(tmp, "w", encoding="utf-8") as f: + json.dump({"counting": bool(counting)}, f) + os.replace(tmp, CONTROL_FILE) + + +@app.route("/api/control", methods=["GET"]) +def api_control_get(): + return jsonify({ + "success": True, + "enabled": CONTROL_ENABLED, + "counting": _read_counting_flag(), + }) + + +@app.route("/api/control", methods=["POST"]) +def api_control_set(): + if not CONTROL_ENABLED: + return jsonify({"success": False, "error": "Runtime control is disabled (set CONTROL_ENABLED=true)"}), 403 + data = request.get_json(silent=True) or {} + if "counting" not in data: + return jsonify({"success": False, "error": "Missing 'counting' field"}), 400 + try: + counting = bool(data["counting"]) + _write_counting_flag(counting) + return jsonify({"success": True, "counting": counting}) + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + + +@app.route("/snapshots") +def snapshots_page(): + return render_template("snapshots.html", site_name=SITE_NAME, show_detect=SAVE_DETECT_SNAPSHOT) + + +def _empty_current(): + return { + "counting_date": get_counting_date(), + "count": 0, + "count_left": 0, + "count_right": 0, + "start_time": None, + "last_detection_time": None, + } + + +def _load_current_state(): + """Load live counter state from current_counter.json.""" + with open(CURRENT_COUNTER_PATH, "r", encoding="utf-8") as f: + data = json.load(f) + return { + "counting_date": data.get("counting_date") or get_counting_date(), + "count": int(data.get("count", 0) or 0), + "count_left": int(data.get("count_left", 0) or 0), + "count_right": int(data.get("count_right", 0) or 0), + "start_time": data.get("start_time"), + "last_detection_time": data.get("last_detection_time"), + } + + +def _query_history(date_from=None, date_to=None, days=None, limit=None, offset=0): + """Query daily_counters with optional date range and pagination.""" + conn = get_db() + cur = conn.cursor() + + clauses = [] + params = [] + + if days is not None and date_from is None and date_to is None: + date_from = (datetime.now() - timedelta(days=days)).date().isoformat() + + if date_from: + clauses.append("counting_date >= ?") + params.append(date_from) + if date_to: + clauses.append("counting_date <= ?") + params.append(date_to) + + where = f"WHERE {' AND '.join(clauses)}" if clauses else "" + + cur.execute(f"SELECT COUNT(*) AS total FROM daily_counters {where}", params) + total = cur.fetchone()["total"] + + sql = f""" + SELECT counting_date, camera_name, object_label, + total_count, total_left, total_right, start_time, end_time, updated_at + FROM daily_counters + {where} + ORDER BY counting_date DESC + """ + page_params = list(params) + if limit is not None: + sql += " LIMIT ? OFFSET ?" + page_params.extend([limit, offset]) + + cur.execute(sql, page_params) + rows = [ + { + "date": row["counting_date"], + "camera_name": row["camera_name"], + "object_label": row["object_label"], + "total_count": row["total_count"], + "total_left": row["total_left"], + "total_right": row["total_right"], + "diff": (row["total_left"] or 0) + (row["total_right"] or 0), + "start_time": row["start_time"], + "end_time": row["end_time"], + "updated_at": row["updated_at"], + } + for row in cur.fetchall() + ] + conn.close() + return rows, total + + +@app.route("/api/current") +@app.route("/api/current-counter") +def api_current(): + """Current counting-day totals from live state file.""" + try: + state = _load_current_state() + return jsonify( + { + "success": True, + "active": True, + "site_name": SITE_NAME, + "counting": _read_counting_flag() if CONTROL_ENABLED else True, + **state, + } + ) + except FileNotFoundError: + return jsonify( + { + "success": True, + "site_name": SITE_NAME, + "counting": _read_counting_flag() if CONTROL_ENABLED else True, + "active": False, + "error": "No active counter — state file missing", + **_empty_current(), + } + ), 200 + except Exception as e: + return jsonify( + { + "success": False, + "error": f"Failed to read current counter from {CURRENT_COUNTER_PATH}: {e}", + "site_name": SITE_NAME, + **_empty_current(), + } + ), 500 + + +@app.route("/api/history") +def api_history(): + """ + Historical daily counters. + + Query params: + days – last N calendar days (default 30; ignored if date_from/date_to set) + date_from – inclusive YYYY-MM-DD + date_to – inclusive YYYY-MM-DD + limit – page size (default: all matching) + offset – page offset (default 0) + """ + try: + days = request.args.get("days", type=int) + date_from = request.args.get("date_from") + date_to = request.args.get("date_to") + limit = request.args.get("limit", type=int) + offset = request.args.get("offset", 0, type=int) + + if date_from: + try: + datetime.strptime(date_from, "%Y-%m-%d") + except ValueError: + return jsonify({ + "success": False, + "error": { + "code": "VALIDATION_ERROR", + "message": f"Invalid date_from '{date_from}'. Use YYYY-MM-DD.", + }, + }), 400 + if date_to: + try: + datetime.strptime(date_to, "%Y-%m-%d") + except ValueError: + return jsonify({ + "success": False, + "error": { + "code": "VALIDATION_ERROR", + "message": f"Invalid date_to '{date_to}'. Use YYYY-MM-DD.", + }, + }), 400 + + if days is None and date_from is None and date_to is None: + days = 30 + if offset < 0: + offset = 0 + if limit is not None and limit < 1: + return jsonify({ + "success": False, + "error": { + "code": "VALIDATION_ERROR", + "message": "limit must be a positive integer", + }, + }), 400 + + rows, total = _query_history( + date_from=date_from, + date_to=date_to, + days=days, + limit=limit, + offset=offset, + ) + payload = { + "success": True, + "site_name": SITE_NAME, + "filters": { + "days": days, + "date_from": date_from, + "date_to": date_to, + }, + "count": len(rows), + "data": rows, + } + if limit is not None: + payload["pagination"] = { + "offset": offset, + "limit": limit, + "total": total, + "has_next": offset + limit < total, + "has_prev": offset > 0, + } + else: + payload["total"] = total + return jsonify(payload) + except sqlite3.OperationalError as e: + return jsonify({ + "success": False, + "error": { + "code": "DATABASE_UNAVAILABLE", + "message": f"Database unavailable at {DB_PATH}: {e}", + }, + "data": [], + "count": 0, + "total": 0, + }), 200 + except Exception as e: + return jsonify({ + "success": False, + "error": { + "code": "INTERNAL_ERROR", + "message": str(e), + }, + }), 500 + + +@app.route("/api/history/") +def api_history_day(counting_date): + """Single counting-day record by YYYY-MM-DD.""" + try: + datetime.strptime(counting_date, "%Y-%m-%d") + except ValueError: + return jsonify({ + "success": False, + "error": { + "code": "VALIDATION_ERROR", + "message": f"Invalid counting_date '{counting_date}'. Use YYYY-MM-DD.", + }, + }), 400 + + try: + rows, _ = _query_history(date_from=counting_date, date_to=counting_date) + if not rows: + return jsonify({ + "success": False, + "error": { + "code": "NOT_FOUND", + "message": f"No history found for counting date {counting_date}", + }, + }), 404 + return jsonify({ + "success": True, + "site_name": SITE_NAME, + "data": rows[0] if len(rows) == 1 else rows, + }) + except sqlite3.OperationalError as e: + return jsonify({ + "success": False, + "error": { + "code": "DATABASE_UNAVAILABLE", + "message": f"Database unavailable at {DB_PATH}: {e}", + }, + }), 503 + except Exception as e: + return jsonify({ + "success": False, + "error": { + "code": "INTERNAL_ERROR", + "message": str(e), + }, + }), 500 + + +@app.route("/api/summary") +def api_summary(): + try: + conn = get_db() + cur = conn.cursor() + today = get_counting_date() + cur.execute( + """ + SELECT COALESCE(total_count, 0) as total_count, + COALESCE(total_left, 0) as total_left, + COALESCE(total_right, 0) as total_right + FROM daily_counters + WHERE counting_date = ? + """, + (today,), + ) + today_row = cur.fetchone() + yesterday = (datetime.strptime(today, "%Y-%m-%d").date() - timedelta(days=1)).isoformat() + cur.execute( + """ + SELECT COALESCE(total_count, 0) as total_count, + COALESCE(total_left, 0) as total_left, + COALESCE(total_right, 0) as total_right + FROM daily_counters + WHERE counting_date = ? + """, + (yesterday,), + ) + yesterday_row = cur.fetchone() + cur.execute( + """ + SELECT COALESCE(SUM(total_count), 0) as grand_total, + COALESCE(SUM(total_left), 0) as grand_left, + COALESCE(SUM(total_right), 0) as grand_right, + COUNT(DISTINCT counting_date) as total_days + FROM daily_counters + """ + ) + all_time = cur.fetchone() + cur.execute("SELECT ROUND(AVG(total_count), 1) as avg_per_day FROM daily_counters") + avg = cur.fetchone() + cur.execute( + """ + SELECT counting_date, total_count + FROM daily_counters + ORDER BY total_count DESC + LIMIT 1 + """ + ) + best = cur.fetchone() + conn.close() + return jsonify( + { + "today": { + "date": today, + "total_count": today_row["total_count"] if today_row else 0, + "total_left": today_row["total_left"] if today_row else 0, + "total_right": today_row["total_right"] if today_row else 0, + }, + "yesterday": { + "date": yesterday, + "total_count": yesterday_row["total_count"] if yesterday_row else 0, + "total_left": yesterday_row["total_left"] if yesterday_row else 0, + "total_right": yesterday_row["total_right"] if yesterday_row else 0, + }, + "all_time": { + "grand_total": all_time["grand_total"], + "grand_left": all_time["grand_left"], + "grand_right": all_time["grand_right"], + "total_days": all_time["total_days"], + }, + "average_per_day": avg["avg_per_day"] or 0, + "best_day": { + "date": best["counting_date"] if best else None, + "count": best["total_count"] if best else 0, + }, + } + ) + except sqlite3.OperationalError as e: + return jsonify({"success": False, "error": f"Database unavailable: {e}", "today": {"date": datetime.now().date().isoformat(), "total_count": 0, "total_left": 0, "total_right": 0}, "yesterday": {"date": "", "total_count": 0, "total_left": 0, "total_right": 0}, "all_time": {"grand_total": 0, "grand_left": 0, "grand_right": 0, "total_days": 0}, "average_per_day": 0, "best_day": {"date": None, "count": 0}}), 200 + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + + +@app.route("/api/daily-data") +def api_daily_data(): + try: + days = request.args.get("days", 30, type=int) + date_from = (datetime.now() - timedelta(days=days)).date().isoformat() + conn = get_db() + cur = conn.cursor() + cur.execute( + """ + SELECT counting_date, total_count, total_left, total_right + FROM daily_counters + WHERE counting_date >= ? + ORDER BY counting_date ASC + """, + (date_from,), + ) + daily_data = [ + { + "date": row["counting_date"], + "total_count": row["total_count"], + "total_left": row["total_left"], + "total_right": row["total_right"], + } + for row in cur.fetchall() + ] + conn.close() + return jsonify(daily_data) + except sqlite3.OperationalError: + return jsonify([]), 200 + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + + +@app.route("/api/available-dates") +def api_available_dates(): + try: + conn = get_db() + cur = conn.cursor() + cur.execute( + """ + SELECT counting_date, total_count, total_left, total_right, start_time, end_time + FROM daily_counters + ORDER BY counting_date DESC + """ + ) + dates = [ + { + "date": row["counting_date"], + "total_count": row["total_count"], + "total_left": row["total_left"], + "total_right": row["total_right"], + "start_time": row["start_time"], + "end_time": row["end_time"], + } + for row in cur.fetchall() + ] + conn.close() + return jsonify(dates) + except sqlite3.OperationalError: + return jsonify([]), 200 + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + + +def _excel_response(wb, filename): + output = BytesIO() + wb.save(output) + output.seek(0) + return Response( + output.getvalue(), + mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + headers={"Content-Disposition": f"attachment; filename={filename}"}, + ) + + +def _style_header(ws, cols): + header_font = Font(bold=True, color="FFFFFF", size=11) + header_fill = PatternFill(start_color="2F5496", end_color="2F5496", fill_type="solid") + thin_border = Border( + left=Side(style="thin"), right=Side(style="thin"), + top=Side(style="thin"), bottom=Side(style="thin"), + ) + for col_idx, (col_letter, text) in enumerate(cols, 1): + cell = ws.cell(row=1, column=col_idx, value=text) + cell.font = header_font + cell.fill = header_fill + cell.alignment = Alignment(horizontal="center") + cell.border = thin_border + ws.freeze_panes = "A2" + + +def _auto_width(ws): + for col in ws.columns: + max_len = 0 + col_letter = col[0].column_letter + for cell in col: + if cell.value is not None: + max_len = max(max_len, len(str(cell.value))) + ws.column_dimensions[col_letter].width = max_len + 4 + + +@app.route("/api/export-daily-csv") +def export_daily_xlsx(): + try: + days = request.args.get("days", 30, type=int) + date_from = (datetime.now() - timedelta(days=days)).date().isoformat() + conn = get_db() + cur = conn.cursor() + cur.execute( + """ + SELECT counting_date, total_count, total_left, total_right, start_time, end_time + FROM daily_counters + WHERE counting_date >= ? + ORDER BY counting_date ASC + """, + (date_from,), + ) + rows = cur.fetchall() + conn.close() + except sqlite3.OperationalError as e: + return jsonify({"success": False, "error": f"Database unavailable: {e}"}), 503 + except Exception as e: + return jsonify({"success": False, "error": str(e)}), 500 + + wb = Workbook() + ws = wb.active + ws.title = "Daily Counters" + _style_header(ws, [("A", "Date"), ("B", "Total"), ("C", "Left"), ("D", "Right"), ("E", "Total (L+R)"), ("F", "First Count"), ("G", "Last Count")]) + + for r_idx, row in enumerate(rows, 2): + ws.cell(row=r_idx, column=1, value=row["counting_date"]) + ws.cell(row=r_idx, column=2, value=row["total_count"]) + ws.cell(row=r_idx, column=3, value=row["total_left"]) + ws.cell(row=r_idx, column=4, value=row["total_right"]) + ws.cell(row=r_idx, column=5, value=(row["total_left"] or 0) + (row["total_right"] or 0)) + ws.cell(row=r_idx, column=6, value=row["start_time"]) + ws.cell(row=r_idx, column=7, value=row["end_time"]) + + _auto_width(ws) + filename = f"{SITE_NAME}_daily_records_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx" + return _excel_response(wb, filename) + + +if __name__ == "__main__": + WSGIRequestHandler.protocol_version = "HTTP/1.1" + print(f"ZenAI KTC zone counter dashboard at http://{DASHBOARD_HOST}:{DASHBOARD_PORT}") + print(f"DB: {DB_PATH}") + print(f"State: {CURRENT_COUNTER_PATH}") + app.run(host=DASHBOARD_HOST, port=DASHBOARD_PORT, debug=FLASK_DEBUG) \ No newline at end of file diff --git a/counter_live_rknn.py b/counter_live_rknn.py new file mode 100644 index 0000000..0dbe288 --- /dev/null +++ b/counter_live_rknn.py @@ -0,0 +1,1720 @@ +""" +Edge production live counter — RTSP + YOLO RKNN + ByteTrack + zone counting. +Runs on RK3588 hardware with RKNN model (320×320 input). +Uses ByteTrack (Kalman filter + two-stage IoU association) for tracking. + +Left / right rectangular zones mark the left and right sack feeders. +A sack is counted once when its centroid enters a zone. +""" + +import numpy as np +import cv2 +import csv +import json +import os +import signal +import socket +import threading +import time +from collections import deque +from datetime import datetime +from pathlib import Path + +from dotenv import load_dotenv + +load_dotenv() + +from rknnlite.api import RKNNLite +from counter_store import CounterStore + +# --- config (override via env / .env) --- +OUTPUT_DIR = os.getenv("OUTPUT_DIR", "/opt/jetson-counter") +DB_PATH = os.getenv("DB_PATH", f"{OUTPUT_DIR}/jetson_counter.db") +STATE_FILE = os.getenv("STATE_FILE", f"{OUTPUT_DIR}/current_counter.json") +SOURCE = os.getenv("SOURCE", "rtsp://user:pass@192.168.0.100:554/stream1") +MODEL_PATH = os.getenv("MODEL_PATH", "/opt/jetson-counter/yolo11n.rknn") +CAMERA_NAME = os.getenv("CAMERA_NAME", "CC1") +OBJECT_LABEL = os.getenv("OBJECT_LABEL", "object") +CLASS_OBJECT = os.getenv("CLASS_OBJECT", "object") + +# Left feeder zone (fractions of frame width/height). Absolute pixel overrides +# win when set (ZONE_LEFT_X1 … ZONE_LEFT_Y2). +ZONE_LEFT_X1 = int(os.getenv("ZONE_LEFT_X1")) if os.getenv("ZONE_LEFT_X1") else None +ZONE_LEFT_Y1 = int(os.getenv("ZONE_LEFT_Y1")) if os.getenv("ZONE_LEFT_Y1") else None +ZONE_LEFT_X2 = int(os.getenv("ZONE_LEFT_X2")) if os.getenv("ZONE_LEFT_X2") else None +ZONE_LEFT_Y2 = int(os.getenv("ZONE_LEFT_Y2")) if os.getenv("ZONE_LEFT_Y2") else None +ZONE_LEFT_X1_FRAC = float(os.getenv("ZONE_LEFT_X1_FRAC", "0.00")) +ZONE_LEFT_Y1_FRAC = float(os.getenv("ZONE_LEFT_Y1_FRAC", "0.20")) +ZONE_LEFT_X2_FRAC = float(os.getenv("ZONE_LEFT_X2_FRAC", "0.35")) +ZONE_LEFT_Y2_FRAC = float(os.getenv("ZONE_LEFT_Y2_FRAC", "0.85")) + +# Right feeder zone +ZONE_RIGHT_X1 = int(os.getenv("ZONE_RIGHT_X1")) if os.getenv("ZONE_RIGHT_X1") else None +ZONE_RIGHT_Y1 = int(os.getenv("ZONE_RIGHT_Y1")) if os.getenv("ZONE_RIGHT_Y1") else None +ZONE_RIGHT_X2 = int(os.getenv("ZONE_RIGHT_X2")) if os.getenv("ZONE_RIGHT_X2") else None +ZONE_RIGHT_Y2 = int(os.getenv("ZONE_RIGHT_Y2")) if os.getenv("ZONE_RIGHT_Y2") else None +ZONE_RIGHT_X1_FRAC = float(os.getenv("ZONE_RIGHT_X1_FRAC", "0.65")) +ZONE_RIGHT_Y1_FRAC = float(os.getenv("ZONE_RIGHT_Y1_FRAC", "0.20")) +ZONE_RIGHT_X2_FRAC = float(os.getenv("ZONE_RIGHT_X2_FRAC", "1.00")) +ZONE_RIGHT_Y2_FRAC = float(os.getenv("ZONE_RIGHT_Y2_FRAC", "0.85")) + +IMGSZ = int(os.getenv("IMGSZ", "320")) +HALF = os.getenv("HALF", "false").lower() == "true" +CONF = float(os.getenv("CONF", "0.3")) +NMS_IOU = float(os.getenv("NMS_IOU", "0.45")) +DEVICE = int(os.getenv("DEVICE", "0")) + +# RKNN NPU core mask +CORE_MASK = int(os.getenv("CORE_MASK", "1")) + +# YOLO decoder config +NUM_CLASSES = int(os.getenv("NUM_CLASSES", "2")) +SCORE_SIGMOID = os.getenv("SCORE_SIGMOID", "false").lower() == "true" + +# ByteTrack settings +TRACK_HIGH_THRESH = float(os.getenv("TRACK_HIGH_THRESH", "0.5")) +TRACK_LOW_THRESH = float(os.getenv("TRACK_LOW_THRESH", "0.1")) +TRACK_MATCH_THRESH = float(os.getenv("TRACK_MATCH_THRESH", "0.8")) +TRACK_BUFFER = int(os.getenv("TRACK_BUFFER", "30")) +TRACK_MIN_HITS = int(os.getenv("TRACK_MIN_HITS", "3")) + +# Dedup guard against ID-switch double counts: ignore a second zone entry in the +# same feeder within DEDUP_FRAMES and DEDUP_PX (centroid distance) of a recent count. +DEDUP_FRAMES = int(os.getenv("DEDUP_FRAMES", "15")) +DEDUP_PX = float(os.getenv("DEDUP_PX", "60")) + +# Trajectory inheritance across ID switches: when a new track appears, inherit the +# last position of a recently-seen nearby track so zone entry is not missed when +# the ID changes at the zone boundary. +INHERIT_SEC = float(os.getenv("INHERIT_SEC", "1.0")) +INHERIT_PX = float(os.getenv("INHERIT_PX", "60")) + +# Per-feeder cooldown: after a count on that feeder, ignore further counts on the +# same feeder for N seconds. 0 = disabled. +ZONE_COOLDOWN_LEFT_SEC = float(os.getenv("ZONE_COOLDOWN_LEFT_SEC", "0")) +ZONE_COOLDOWN_RIGHT_SEC = float(os.getenv("ZONE_COOLDOWN_RIGHT_SEC", "0")) + +DAILY_CUTOFF_TIME = os.getenv("DAILY_CUTOFF_TIME", "20:00") + +EXPORT_CSV = os.getenv("EXPORT_CSV", "true").lower() == "true" +CROSS_CSV = os.getenv("CROSS_CSV", f"{OUTPUT_DIR}/crossings.csv") + +# Save an annotated frame snapshot each time an object enters a feeder zone and +# the counter increases. +SAVE_CROSS_SNAPSHOT = os.getenv("SAVE_CROSS_SNAPSHOT", "false").lower() == "true" +# Also save one snapshot the first time each object is detected (before it enters +# a zone), named with the same track id so it can be correlated with the count snapshot. +SAVE_DETECT_SNAPSHOT = os.getenv("SAVE_DETECT_SNAPSHOT", "false").lower() == "true" +CROSS_SNAPSHOT_DIR = os.getenv("CROSS_SNAPSHOT_DIR", f"{OUTPUT_DIR}/snapshots") +CROSS_SNAPSHOT_QUALITY = int(os.getenv("CROSS_SNAPSHOT_QUALITY", "85")) +# Retention: delete oldest snapshots when either limit is exceeded (0 = disabled). +CROSS_SNAPSHOT_MAX_FILES = int(os.getenv("CROSS_SNAPSHOT_MAX_FILES", "1000")) +CROSS_SNAPSHOT_MAX_AGE_DAYS = float(os.getenv("CROSS_SNAPSHOT_MAX_AGE_DAYS", "7")) +# Run the cleanup sweep at most every N seconds to limit filesystem scans. +CROSS_SNAPSHOT_CLEANUP_SEC = int(os.getenv("CROSS_SNAPSHOT_CLEANUP_SEC", "3600")) + +RATE_WINDOW_SEC = int(os.getenv("RATE_WINDOW_SEC", "60")) +WARMUP_FRAMES = int(os.getenv("WARMUP_FRAMES", "30")) +RECONNECT_DELAY_SEC = int(os.getenv("RECONNECT_DELAY_SEC", "3")) +MAX_RECONNECT_ATTEMPTS = int(os.getenv("MAX_RECONNECT_ATTEMPTS", "0")) +TRACKED_PRUNE_SEC = int(os.getenv("TRACKED_PRUNE_SEC", "300")) +RECORD_VIDEO = os.getenv("RECORD_VIDEO", "false").lower() == "true" +VIDEO_SEGMENT_SEC = int(os.getenv("VIDEO_SEGMENT_SEC", "3600")) +OUTPUT_FPS = int(os.getenv("OUTPUT_FPS", "15")) + +LIVE_STREAM_ENABLED = os.getenv("LIVE_STREAM_ENABLED", "false").lower() == "true" +LIVE_STREAM_FRAME_PATH = os.getenv( + "LIVE_STREAM_FRAME_PATH", "/dev/shm/jetson-counter/live_frame.jpg" +) +LIVE_STREAM_QUALITY = int(os.getenv("LIVE_STREAM_QUALITY", "75")) +LIVE_STREAM_EVERY_N = int(os.getenv("LIVE_STREAM_EVERY_N", "2")) + +RTSP_FFMPEG_OPTIONS = os.getenv( + "OPENCV_FFMPEG_CAPTURE_OPTIONS", + "rtsp_transport;tcp|fflags;nobuffer|flags;low_delay", +) + +IS_LIVE = SOURCE.lower().startswith(("rtsp://", "http://")) + +MOTION_DETECTION_ENABLED = os.getenv("MOTION_DETECTION_ENABLED", "false").lower() == "true" +MOTION_THRESHOLD = float(os.getenv("MOTION_THRESHOLD", "5.0")) +# Per-pixel intensity change (0-255) for a pixel to count as "moved". +MOTION_PIXEL_DELTA = int(os.getenv("MOTION_PIXEL_DELTA", "25")) +# Fraction of frame pixels that must change (0-1) to trigger inference. Small, +# so an object entering the edge of the frame is detected immediately. +MOTION_MIN_AREA_FRAC = float(os.getenv("MOTION_MIN_AREA_FRAC", "0.002")) +# Always run inference at least every N frames even if no motion (heartbeat), so a +# slow/stationary object is never missed for long. +MOTION_HEARTBEAT_FRAMES = int(os.getenv("MOTION_HEARTBEAT_FRAMES", "15")) + +# --- Runtime control (toggle counting on/off on the fly) --- +# When enabled, the process watches a small JSON control file and honors its +# "counting" flag. Set false to always count (ignore the control file). +CONTROL_ENABLED = os.getenv("CONTROL_ENABLED", "false").lower() == "true" +CONTROL_FILE = os.getenv("CONTROL_FILE", f"{OUTPUT_DIR}/control.json") +# Whether counting is active on startup when no control file exists yet. +CONTROL_DEFAULT_COUNTING = os.getenv("CONTROL_DEFAULT_COUNTING", "true").lower() == "true" +# Re-read the control file at most every N seconds. +CONTROL_POLL_SEC = float(os.getenv("CONTROL_POLL_SEC", "1.0")) +# Optional TCP control socket. When enabled, the counter listens for line-based +# commands so counting can be toggled over the network (in addition to the file). +CONTROL_SOCKET_ENABLED = os.getenv("CONTROL_SOCKET_ENABLED", "false").lower() == "true" +CONTROL_SOCKET_HOST = os.getenv("CONTROL_SOCKET_HOST", "127.0.0.1") +CONTROL_SOCKET_PORT = int(os.getenv("CONTROL_SOCKET_PORT", "5090")) + +CROSS_FLASH_FRAMES = 12 +POPUP_LIFETIME = 20 +ZONE_PULSE_FRAMES = 12 +COUNT_PULSE_FRAMES = 15 + +C_ZONE_LEFT = (80, 220, 100) # green — left feeder +C_ZONE_RIGHT = (0, 165, 255) # orange — right feeder +C_ZONE_FILL_ALPHA = 0.18 + +SKELETON = [(0, 1), (4, 3), (1, 2), (3, 2), (2, 6), (2, 5), (2, 7), (7, 8)] +SK_COLORS = [ + (0, 255, 255), + (0, 255, 255), + (255, 0, 255), + (255, 0, 255), + (0, 255, 0), + (255, 255, 0), + (0, 0, 255), + (200, 200, 0), +] + +C_PANEL = (28, 24, 18) +C_BORDER = (90, 85, 75) +C_ACCENT = (255, 200, 60) +C_GREEN = (80, 220, 100) +C_TEXT = (235, 235, 235) +C_MUTED = (150, 150, 150) +C_OBJECT_BOX = (0, 165, 255) + +shutdown_requested = False + + +def request_shutdown(signum, frame): + global shutdown_requested + shutdown_requested = True + print("\nShutdown requested — finishing current frame...") + + +signal.signal(signal.SIGINT, request_shutdown) +signal.signal(signal.SIGTERM, request_shutdown) + + +# ============================================================================= +# YOLO output decoder (NMS only — boxes are pre-decoded by the model) +# ============================================================================= + + +def _nms(boxes, scores, iou_thr=0.45): + order = np.argsort(scores)[::-1] + keep = [] + while len(order) > 0: + idx = order[0] + keep.append(idx) + if len(order) == 1: + break + xx1 = np.maximum(boxes[idx, 0], boxes[order[1:], 0]) + yy1 = np.maximum(boxes[idx, 1], boxes[order[1:], 1]) + xx2 = np.minimum(boxes[idx, 2], boxes[order[1:], 2]) + yy2 = np.minimum(boxes[idx, 3], boxes[order[1:], 3]) + w = np.maximum(0.0, xx2 - xx1) + h = np.maximum(0.0, yy2 - yy1) + inter = w * h + area_i = (boxes[idx, 2] - boxes[idx, 0]) * (boxes[idx, 3] - boxes[idx, 1]) + area_o = (boxes[order[1:], 2] - boxes[order[1:], 0]) * ( + boxes[order[1:], 3] - boxes[order[1:], 1] + ) + iou = inter / (area_i + area_o - inter + 1e-16) + order = order[1:][iou < iou_thr] + return np.array(keep) + + +# ============================================================================= +# IoU helpers (xyxy format) +# ============================================================================= + + +def _ious_xyxy(boxes_a, boxes_b): + """Pairwise IoU: (N,4) vs (M,4) → (N,M) matrix.""" + n, m = len(boxes_a), len(boxes_b) + if n == 0 or m == 0: + return np.zeros((n, m), dtype=np.float32) + xx1 = np.maximum(boxes_a[:, None, 0], boxes_b[None, :, 0]) + yy1 = np.maximum(boxes_a[:, None, 1], boxes_b[None, :, 1]) + xx2 = np.minimum(boxes_a[:, None, 2], boxes_b[None, :, 2]) + yy2 = np.minimum(boxes_a[:, None, 3], boxes_b[None, :, 3]) + iw = np.maximum(0.0, xx2 - xx1) + ih = np.maximum(0.0, yy2 - yy1) + inter = iw * ih + area_a = (boxes_a[:, 2] - boxes_a[:, 0]) * (boxes_a[:, 3] - boxes_a[:, 1]) + area_b = (boxes_b[:, 2] - boxes_b[:, 0]) * (boxes_b[:, 3] - boxes_b[:, 1]) + return inter / (area_a[:, None] + area_b[None, :] - inter + 1e-16) + + +def _greedy_match(cost_matrix, threshold=0.3): + """Greedy linear assignment. Returns pairs (row_idx, col_idx).""" + if cost_matrix.size == 0: + return [] + n, m = cost_matrix.shape + flat = [(cost_matrix[i, j], i, j) for i in range(n) for j in range(m)] + flat.sort() + row_used = set() + col_used = set() + pairs = [] + for cost, i, j in flat: + if cost >= threshold: + break + if i in row_used or j in col_used: + continue + row_used.add(i) + col_used.add(j) + pairs.append((i, j)) + return pairs + + +# ============================================================================= +# Kalman filter box tracker (state: x, y, w, h, vx, vy, vw, vh) +# ============================================================================= + + +class KalmanBoxTracker: + count = 0 + + def __init__(self, bbox_xyxy): + KalmanBoxTracker.count += 1 + self.track_id = KalmanBoxTracker.count + + x1, y1, x2, y2 = bbox_xyxy + w, h = x2 - x1, y2 - y1 + x, y = x1 + w / 2, y1 + h / 2 + + self.kf = _KalmanFilter() + self.kf.x[:4, 0] = np.array([x, y, w, h], dtype=np.float32) + + self.time_since_update = 0 + self.hits = 1 + self.hit_streak = 1 + self.age = 1 + + def predict(self): + if self.kf.x[6] + self.kf.x[2] <= 0: + self.kf.x[6] *= 0.0 + self.kf.predict() + self.age += 1 + self.time_since_update += 1 + + def update(self, bbox_xyxy): + self.time_since_update = 0 + self.hits += 1 + self.hit_streak += 1 + + x1, y1, x2, y2 = bbox_xyxy + w, h = x2 - x1, y2 - y1 + x, y = x1 + w / 2, y1 + h / 2 + self.kf.update(np.array([x, y, w, h], dtype=np.float32)) + + def get_state(self): + """Returns xyxy bbox from Kalman state.""" + xx = self.kf.x[:4, 0] + x, y, w, h = xx[0], xx[1], xx[2], xx[3] + x1 = x - w / 2 + y1 = y - h / 2 + x2 = x + w / 2 + y2 = y + h / 2 + return np.array([x1, y1, x2, y2], dtype=np.float32) + + def get_cx(self): + return float(self.kf.x[0, 0]) + + def get_cy(self): + return float(self.kf.x[1, 0]) + + +class _KalmanFilter: + """8-state constant-velocity Kalman filter for bounding box tracking.""" + + def __init__(self): + ndim, dt = 4, 1.0 + self.motion_mat = np.eye(2 * ndim, 2 * ndim, dtype=np.float32) + for i in range(ndim): + self.motion_mat[i, ndim + i] = dt + self.update_mat = np.eye(ndim, 2 * ndim, dtype=np.float32) + + self._std_weight_position = 1.0 / 20 + self._std_weight_velocity = 1.0 / 160 + + self.x = np.zeros((8, 1), dtype=np.float32) + self.P = np.eye(8, dtype=np.float32) * 10.0 + + def predict(self): + std_pos = [ + self._std_weight_position * self.x[2], + self._std_weight_position * self.x[3], + self._std_weight_position * self.x[2], + self._std_weight_position * self.x[3], + ] + std_vel = [ + self._std_weight_velocity * self.x[2], + self._std_weight_velocity * self.x[3], + self._std_weight_velocity * self.x[2], + self._std_weight_velocity * self.x[3], + ] + Q = np.diag(np.square(np.concatenate([std_pos, std_vel]))) + + self.x = self.motion_mat @ self.x + self.P = self.motion_mat @ self.P @ self.motion_mat.T + Q + + def update(self, z): + R = np.diag( + np.square( + [ + self._std_weight_position * z[2], + self._std_weight_position * z[3], + self._std_weight_position * z[2], + self._std_weight_position * z[3], + ] + ) + ) + + H = self.update_mat + S = H @ self.P @ H.T + R + K = self.P @ H.T @ np.linalg.inv(S) + + y = z.reshape(4, 1) - H @ self.x + self.x = self.x + K @ y + I_KH = np.eye(8) - K @ H + self.P = I_KH @ self.P @ I_KH.T + K @ R @ K.T + + +# ============================================================================= +# ByteTrack multi-object tracker +# ============================================================================= + + +class ByteTracker: + """ByteTrack: two-stage association with Kalman filter prediction.""" + + def __init__( + self, + track_high_thresh=0.5, + track_low_thresh=0.1, + match_thresh=0.8, + track_buffer=30, + min_hits=3, + ): + self.high_thresh = track_high_thresh + self.low_thresh = track_low_thresh + self.match_thresh = match_thresh + self.track_buffer = track_buffer + self.min_hits = min_hits + self.tracked_tracks = [] + self.lost_tracks = [] + self.removed_tracks = [] + self.frame_id = 0 + + def update(self, boxes_xyxy, scores): + self.frame_id += 1 + + # --- separate detections by score --- + if len(boxes_xyxy) > 0: + remain = scores > self.low_thresh + remain_orig_idx = np.where(remain)[0] + dets = boxes_xyxy[remain] + det_scores = scores[remain] + is_high = det_scores > self.high_thresh + is_low = ~is_high + else: + remain_orig_idx = np.zeros(0, dtype=np.int64) + dets = np.zeros((0, 4), dtype=np.float32) + det_scores = np.zeros(0, dtype=np.float32) + is_high = np.zeros(0, dtype=bool) + is_low = np.zeros(0, dtype=bool) + + # --- Kalman predict all existing tracks --- + track_pool = self.tracked_tracks + self.lost_tracks + num_tracks = len(track_pool) + + # Per-frame tracking results + matched_track_idx = set() + det_to_track = {} + tracked_map = {} + lost_map = {} + + # Pre-allocate these for scoping + high_idx = np.array([], dtype=np.int64) + low_idx = np.array([], dtype=np.int64) + match_pairs_high = [] + + if num_tracks > 0: + track_boxes = np.zeros((num_tracks, 4), dtype=np.float32) + for ti, trk in enumerate(track_pool): + trk.predict() + track_boxes[ti] = trk.get_state() + + # --- first association: high-score ↔ all tracks --- + high_idx = np.where(is_high)[0] + high_dets = dets[is_high] + + unmatched_tracks = list(range(num_tracks)) + + if len(high_dets) > 0: + iou_mat = _ious_xyxy(high_dets, track_boxes) + cost_mat = 1.0 - iou_mat + matches = _greedy_match(cost_mat, threshold=1.0 - self.match_thresh) + + for di, ti in matches: + det_global = int(high_idx[di]) + orig_idx = int(remain_orig_idx[det_global]) + track_pool[ti].update(dets[det_global]) + track_pool[ti].hit_streak = max(1, track_pool[ti].hit_streak) + matched_track_idx.add(ti) + det_to_track[orig_idx] = track_pool[ti].track_id + tracked_map[track_pool[ti].track_id] = (track_pool[ti].get_cx(), track_pool[ti].get_cy()) + match_pairs_high.append((det_global, ti)) + + unmatched_tracks = [ + t for t in range(num_tracks) if t not in matched_track_idx + ] + + # --- second association: low-score ↔ unmatched tracks --- + low_idx = np.where(is_low)[0] + low_dets = dets[is_low] + + if len(low_dets) > 0 and len(unmatched_tracks) > 0: + unmatched_boxes = track_boxes[unmatched_tracks] + iou_mat = _ious_xyxy(low_dets, unmatched_boxes) + cost_mat = 1.0 - iou_mat + matches2 = _greedy_match( + cost_mat, threshold=1.0 - self.match_thresh + ) + + for di, uti in matches2: + det_global = int(low_idx[di]) + pool_idx = unmatched_tracks[uti] + orig_idx = int(remain_orig_idx[det_global]) + track_pool[pool_idx].update(dets[det_global]) + track_pool[pool_idx].hit_streak = max( + 1, track_pool[pool_idx].hit_streak + ) + matched_track_idx.add(pool_idx) + det_to_track[orig_idx] = track_pool[pool_idx].track_id + tracked_map[track_pool[pool_idx].track_id] = ( + track_pool[pool_idx].get_cx(), + track_pool[pool_idx].get_cy(), + ) + + # --- reset hit_streak for unmatched tracks --- + for ti, trk in enumerate(track_pool): + if ti not in matched_track_idx: + trk.hit_streak = 0 + + # --- lifecycle management --- + new_tracked = [] + new_lost = [] + for trk in track_pool: + if trk.time_since_update > self.track_buffer: + self.removed_tracks.append(trk) + elif trk.time_since_update > 0: + new_lost.append(trk) + else: + new_tracked.append(trk) + self.tracked_tracks = new_tracked + self.lost_tracks = new_lost + + # --- confirmed tracks (both tracked and lost) --- + for trk in self.tracked_tracks + self.lost_tracks: + if trk.hit_streak >= self.min_hits or trk.hits >= self.min_hits: + tracked_map.setdefault(trk.track_id, (trk.get_cx(), trk.get_cy())) + + for trk in self.lost_tracks: + if trk.hit_streak >= self.min_hits or trk.hits >= self.min_hits: + lost_map[trk.track_id] = (trk.get_cx(), trk.get_cy()) + + # --- new tracks from unmatched high-score dets --- + high_all = np.where(is_high)[0] + matched_det_ids = set(det_to_track.keys()) + for dg in high_all: + orig_idx = int(remain_orig_idx[int(dg)]) + if orig_idx not in matched_det_ids: + trk = KalmanBoxTracker(dets[int(dg)]) + self.tracked_tracks.append(trk) + det_to_track[orig_idx] = trk.track_id + tracked_map[trk.track_id] = (trk.get_cx(), trk.get_cy()) + + return tracked_map, det_to_track, lost_map + + +# ============================================================================= +# RKNN YOLO wrapper (detect output format: (1, 4+num_classes, N)) +# ============================================================================= + + +class RKNNYOLO: + def __init__( + self, + model_path, + core_mask=1, + imgsz=320, + conf=0.3, + iou=0.45, + num_classes=2, + num_keypoints=0, + score_sigmoid=False, + ): + self.imgsz = imgsz + self.conf = conf + self.iou = iou + self.num_classes = num_classes + self.num_keypoints = num_keypoints + self.score_sigmoid = score_sigmoid + + self.rknn = RKNNLite(verbose=False) + ret = self.rknn.load_rknn(model_path) + if ret != 0: + raise RuntimeError(f"Failed to load RKNN model: {model_path}") + ret = self.rknn.init_runtime(core_mask=core_mask) + if ret != 0: + raise RuntimeError(f"Failed to init RKNN runtime (core_mask={core_mask})") + + try: + sdk_ver = self.rknn.get_sdk_version() + print(f"RKNN SDK version: {sdk_ver}") + except Exception: + pass + + print(f"RKNN model loaded: {model_path} imgsz={imgsz} core_mask={core_mask}") + + def _preprocess(self, frame): + h0, w0 = frame.shape[:2] + scale = min(self.imgsz / h0, self.imgsz / w0) + nh, nw = int(h0 * scale), int(w0 * scale) + resized = cv2.resize(frame, (nw, nh), interpolation=cv2.INTER_LINEAR) + + letterbox = np.full((self.imgsz, self.imgsz, 3), 114, dtype=np.uint8) + dy = (self.imgsz - nh) // 2 + dx = (self.imgsz - nw) // 2 + letterbox[dy : dy + nh, dx : dx + nw] = resized + + rgb = cv2.cvtColor(letterbox, cv2.COLOR_BGR2RGB) + gains = np.array([scale, scale, dy, dx], dtype=np.float32) + return rgb, gains + + def __call__(self, frame): + h0, w0 = frame.shape[:2] + rgb, gains = self._preprocess(frame) + scale, _, pad_y, pad_x = gains + + inp = np.expand_dims(rgb, axis=0) + inp = np.ascontiguousarray(inp.astype(np.uint8)) + + outputs = self.rknn.inference(inputs=[inp]) + + if len(outputs) == 0: + return [] + + out = outputs[0] + out = np.squeeze(out, axis=0) + + if out.shape[0] == self.num_classes + 4: + out = out.T + + boxes_cxcywh = out[:, :4].copy() + cls_raw = out[:, 4:].copy() + + if self.score_sigmoid: + cls_scores = 1.0 / (1.0 + np.exp(-np.clip(cls_raw, -10, 10))) + else: + cls_scores = cls_raw + + boxes_xyxy = np.stack( + [ + boxes_cxcywh[:, 0] - boxes_cxcywh[:, 2] / 2, + boxes_cxcywh[:, 1] - boxes_cxcywh[:, 3] / 2, + boxes_cxcywh[:, 0] + boxes_cxcywh[:, 2] / 2, + boxes_cxcywh[:, 1] + boxes_cxcywh[:, 3] / 2, + ], + axis=1, + ) + + max_scores = cls_scores.max(axis=1) + class_ids = cls_scores.argmax(axis=1) + mask = max_scores > self.conf + + if mask.sum() == 0: + return [] + + bboxes = boxes_xyxy[mask].astype(np.float32) + scores = max_scores[mask].astype(np.float32) + clses = class_ids[mask] + + bboxes[:, 0] = (bboxes[:, 0] - pad_x) / scale + bboxes[:, 1] = (bboxes[:, 1] - pad_y) / scale + bboxes[:, 2] = (bboxes[:, 2] - pad_x) / scale + bboxes[:, 3] = (bboxes[:, 3] - pad_y) / scale + + bboxes[:, 0] = np.clip(bboxes[:, 0], 0, w0) + bboxes[:, 1] = np.clip(bboxes[:, 1], 0, h0) + bboxes[:, 2] = np.clip(bboxes[:, 2], 0, w0) + bboxes[:, 3] = np.clip(bboxes[:, 3], 0, h0) + + detections = [] + for cls_id in range(self.num_classes): + idx = np.where(clses == cls_id)[0] + if len(idx) == 0: + continue + keep = _nms(bboxes[idx], scores[idx], iou_thr=self.iou) + for k in keep: + j = idx[k] + detections.append( + { + "bbox": bboxes[j].tolist(), + "score": float(scores[j]), + "cls": int(clses[j]), + "keypoints": None, + } + ) + return detections + + def release(self): + self.rknn.release() + + +# ============================================================================= +# Drawing helpers +# ============================================================================= + + +def _zone_coord(abs_val, frac, span): + if abs_val is not None: + return int(abs_val) + return int(span * frac) + + +def resolve_zone_left(frame_width, frame_height): + """Return (x1, y1, x2, y2) for the left feeder zone.""" + x1 = _zone_coord(ZONE_LEFT_X1, ZONE_LEFT_X1_FRAC, frame_width) + y1 = _zone_coord(ZONE_LEFT_Y1, ZONE_LEFT_Y1_FRAC, frame_height) + x2 = _zone_coord(ZONE_LEFT_X2, ZONE_LEFT_X2_FRAC, frame_width) + y2 = _zone_coord(ZONE_LEFT_Y2, ZONE_LEFT_Y2_FRAC, frame_height) + return (min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2)) + + +def resolve_zone_right(frame_width, frame_height): + """Return (x1, y1, x2, y2) for the right feeder zone.""" + x1 = _zone_coord(ZONE_RIGHT_X1, ZONE_RIGHT_X1_FRAC, frame_width) + y1 = _zone_coord(ZONE_RIGHT_Y1, ZONE_RIGHT_Y1_FRAC, frame_height) + x2 = _zone_coord(ZONE_RIGHT_X2, ZONE_RIGHT_X2_FRAC, frame_width) + y2 = _zone_coord(ZONE_RIGHT_Y2, ZONE_RIGHT_Y2_FRAC, frame_height) + return (min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2)) + + +def point_in_zone(cx, cy, zone): + x1, y1, x2, y2 = zone + return x1 <= cx <= x2 and y1 <= cy <= y2 + + +def is_duplicate_cross(recent, cx, cy, frame_idx): + """True if a count near (cx, cy) happened within the dedup window (ID-switch guard).""" + while recent and frame_idx - recent[0][0] > DEDUP_FRAMES: + recent.popleft() + for _, prev_cx, prev_cy in recent: + if abs(prev_cx - cx) <= DEDUP_PX and abs(prev_cy - cy) <= DEDUP_PX: + return True + return False + + +def feeder_cooldown_sec(feeder): + if feeder == "left": + return ZONE_COOLDOWN_LEFT_SEC + return ZONE_COOLDOWN_RIGHT_SEC + + +def feeder_in_cooldown(feeder, mono, last_count_mono): + """True if this feeder is still inside its post-count cooldown window.""" + cooldown = feeder_cooldown_sec(feeder) + if cooldown <= 0: + return False + last = last_count_mono.get(feeder) + if last is None: + return False + return (mono - last) < cooldown + + +def _inherit_prev(tracked, new_tid, cx, cy, mono, max_age, max_px): + """Find a recently-seen nearby track for ID-switch continuation. + + Returns (cx, cy, mono, source_tid) or None. + """ + best = None + best_dist = max_px + for tid, (tcx, tcy, ts) in tracked.items(): + if tid == new_tid: + continue + if mono - ts > max_age: + continue + if abs(tcy - cy) > max_px: + continue + dist = abs(tcx - cx) + if dist <= best_dist: + best_dist = dist + best = (tcx, tcy, ts, tid) + return best + + +def _default_zone_state(): + """Per-track feeder-zone state. + + counted: already contributed one LEFT or RIGHT count (at most one per object). + side: 'left' | 'right' | None after a count. + """ + return {"counted": False, "side": None} + + +def _copy_zone_state(src): + return { + "counted": bool(src.get("counted", False)), + "side": src.get("side"), + } + + +def now_str(): + return datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + +def read_counting_flag(default=True): + """Read the 'counting' flag from the control file. Returns default on any error.""" + try: + with open(CONTROL_FILE, "r", encoding="utf-8") as f: + data = json.load(f) + return bool(data.get("counting", default)) + except FileNotFoundError: + return default + except Exception: + return default + + +def write_control_file(counting): + """Create/update the control file atomically (used to seed defaults).""" + try: + Path(CONTROL_FILE).parent.mkdir(parents=True, exist_ok=True) + tmp = f"{CONTROL_FILE}.tmp" + with open(tmp, "w", encoding="utf-8") as f: + json.dump({"counting": bool(counting)}, f) + os.replace(tmp, CONTROL_FILE) + except Exception as exc: + print(f"[{now_str()}] Failed to write control file: {exc}") + + +def start_control_socket(): + """Start a TCP server for runtime control. Commands (newline-terminated): + START | RESUME | ON -> counting on + STOP | PAUSE | OFF -> counting off + TOGGLE -> flip + STATUS | GET -> report current state + It writes the shared control file, so the main loop's file-poll applies it. + Returns the server socket (call .close() to stop).""" + srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + srv.bind((CONTROL_SOCKET_HOST, CONTROL_SOCKET_PORT)) + srv.listen(5) + + def handle(conn, addr): + with conn: + conn.settimeout(30) + try: + buf = b"" + while not shutdown_requested: + try: + chunk = conn.recv(256) + except socket.timeout: + break + if not chunk: + break + buf += chunk + while b"\n" in buf: + line, buf = buf.split(b"\n", 1) + cmd = line.decode("utf-8", "ignore").strip().upper() + if not cmd: + continue + current = read_counting_flag(CONTROL_DEFAULT_COUNTING) + if cmd in ("START", "RESUME", "ON"): + write_control_file(True) + resp = "OK counting=on" + elif cmd in ("STOP", "PAUSE", "OFF"): + write_control_file(False) + resp = "OK counting=off" + elif cmd == "TOGGLE": + write_control_file(not current) + resp = f"OK counting={'off' if current else 'on'}" + elif cmd in ("STATUS", "GET"): + resp = f"OK counting={'on' if current else 'off'}" + else: + resp = "ERR unknown command" + conn.sendall((resp + "\n").encode("utf-8")) + except Exception: + pass + + def loop(): + print(f"Control socket listening on {CONTROL_SOCKET_HOST}:{CONTROL_SOCKET_PORT}") + while not shutdown_requested: + try: + conn, addr = srv.accept() + except OSError: + break + t = threading.Thread(target=handle, args=(conn, addr), daemon=True) + t.start() + + threading.Thread(target=loop, daemon=True).start() + return srv + + +def open_capture(source): + if source.lower().startswith(("rtsp://", "http://")): + os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = RTSP_FFMPEG_OPTIONS + cap = cv2.VideoCapture(source, cv2.CAP_FFMPEG) + cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) + return cap + + +def warmup_stream(cap, n=WARMUP_FRAMES): + print("Warming up stream...") + for _ in range(n): + cap.read() + print("Stream ready!") + + +def open_video_writer(path, w, h, fps): + return cv2.VideoWriter(path, cv2.VideoWriter_fourcc(*"avc1"), fps, (w, h)) + + +class CsvLogger: + def __init__(self, path, header): + Path(path).parent.mkdir(parents=True, exist_ok=True) + new_file = not Path(path).exists() or Path(path).stat().st_size == 0 + self.file = open(path, "a", newline="", buffering=1) + self.writer = csv.writer(self.file) + if new_file: + self.writer.writerow(header) + self.file.flush() + + def write_row(self, row): + self.writer.writerow(row) + self.file.flush() + + def close(self): + self.file.close() + + +class VideoSegmentWriter: + def __init__(self, output_dir, w, h, fps, segment_sec): + self.output_dir = Path(output_dir) + self.output_dir.mkdir(parents=True, exist_ok=True) + self.w, self.h, self.fps = w, h, fps + self.segment_sec = segment_sec + self.segment_start = time.monotonic() + self.writer = None + self._open_next() + + def _segment_path(self): + ts = datetime.now().strftime("%Y%m%d_%H%M%S") + return str(self.output_dir / f"live_{ts}.mp4") + + def _open_next(self): + if self.writer is not None: + self.writer.release() + path = self._segment_path() + self.writer = open_video_writer(path, self.w, self.h, self.fps) + self.segment_start = time.monotonic() + print(f"Recording segment: {path}") + + def write(self, frame): + if time.monotonic() - self.segment_start >= self.segment_sec: + self._open_next() + self.writer.write(frame) + + def release(self): + if self.writer is not None: + self.writer.release() + + +def prune_stale_tracks(tracked, now_mono): + stale = [ + tid for tid, (_, _, ts) in tracked.items() if now_mono - ts > TRACKED_PRUNE_SEC + ] + for tid in stale: + del tracked[tid] + + +def cleanup_snapshots(snapshot_dir, max_files, max_age_days): + """Delete oldest / expired crossing snapshots to bound disk usage.""" + d = Path(snapshot_dir) + if not d.is_dir(): + return + files = sorted(d.rglob("*.jpg"), key=lambda p: p.stat().st_mtime) + if max_age_days > 0: + cutoff = time.time() - max_age_days * 86400 + for p in list(files): + if p.stat().st_mtime < cutoff: + p.unlink(missing_ok=True) + files.remove(p) + if max_files > 0 and len(files) > max_files: + for p in files[: len(files) - max_files]: + p.unlink(missing_ok=True) + + +def overlay_rect(img, x1, y1, x2, y2, color, alpha=0.65): + x1, y1 = max(0, x1), max(0, y1) + x2, y2 = min(img.shape[1], x2), min(img.shape[0], y2) + if x2 <= x1 or y2 <= y1: + return + roi = img[y1:y2, x1:x2] + patch = np.full_like(roi, color, dtype=np.uint8) + cv2.addWeighted(patch, alpha, roi, 1 - alpha, 0, roi) + + +def draw_pill(img, text, x, y, bg, fg=C_TEXT, font_scale=0.45, pad_x=6, pad_y=4): + font = cv2.FONT_HERSHEY_SIMPLEX + (tw, th), baseline = cv2.getTextSize(text, font, font_scale, 1) + x1, y1 = x, y - th - pad_y + x2, y2 = x + tw + pad_x * 2, y + baseline + pad_y + cv2.rectangle(img, (x1, y1), (x2, y2), bg, -1) + cv2.rectangle(img, (x1, y1), (x2, y2), C_BORDER, 1) + cv2.putText(img, text, (x + pad_x, y), font, font_scale, fg, 1, cv2.LINE_AA) + + +def draw_elegant_zone(img, zone, pulse_remaining=0, label="ZONE", color=C_ZONE_LEFT): + x1, y1, x2, y2 = zone + strength = pulse_remaining / max(ZONE_PULSE_FRAMES, 1) + fill_alpha = C_ZONE_FILL_ALPHA + 0.12 * strength + overlay_rect(img, x1, y1, x2, y2, color, alpha=fill_alpha) + thickness = 2 + int(2 * strength) + cv2.rectangle(img, (x1, y1), (x2, y2), color, thickness, cv2.LINE_AA) + # Corner ticks + tick = max(12, min(x2 - x1, y2 - y1) // 8) + for (ax, ay, dx, dy) in ( + (x1, y1, 1, 1), + (x2, y1, -1, 1), + (x1, y2, 1, -1), + (x2, y2, -1, -1), + ): + cv2.line(img, (ax, ay), (ax + dx * tick, ay), color, 2, cv2.LINE_AA) + cv2.line(img, (ax, ay), (ax, ay + dy * tick), color, 2, cv2.LINE_AA) + cv2.putText( + img, + label, + (x1 + 10, y1 + 22), + cv2.FONT_HERSHEY_SIMPLEX, + 0.5, + color, + 1, + cv2.LINE_AA, + ) + + +def draw_zone_count(img, zone, count, label, color, pulse_remaining=0): + text = str(count) + font = cv2.FONT_HERSHEY_SIMPLEX + boost = 0.35 * (pulse_remaining / max(COUNT_PULSE_FRAMES, 1)) + font_scale, thickness = 1.2 + boost, 3 + (tw, th), _ = cv2.getTextSize(text, font, font_scale, thickness) + (lw, lh), _ = cv2.getTextSize(label, font, 0.45, 1) + pad = 12 + box_w = max(tw, lw) + pad * 2 + box_h = th + lh + pad * 2 + 6 + + x1, y1, x2, y2 = zone + bx1 = x1 + ((x2 - x1) - box_w) // 2 + by1 = max(8, y1 - box_h - 8) + bx2 = bx1 + box_w + by2 = by1 + box_h + + overlay_rect(img, bx1, by1, bx2, by2, C_PANEL, alpha=0.78) + cv2.rectangle(img, (bx1, by1), (bx2, by2), color, 2) + + tx = bx1 + (box_w - tw) // 2 + ty = by1 + pad + th + cv2.putText(img, text, (tx, ty), font, font_scale, color, thickness, cv2.LINE_AA) + + slx = bx1 + (box_w - lw) // 2 + sly = ty + lh + 6 + cv2.putText(img, label, (slx, sly), font, 0.45, C_MUTED, 1, cv2.LINE_AA) + + +def draw_hud(img, w, total, total_left, total_right, elapsed_sec, rate): + bar_h = 40 + overlay_rect(img, 0, 0, w, bar_h, C_PANEL, alpha=0.72) + cv2.line(img, (0, bar_h), (w, bar_h), C_BORDER, 1) + cv2.putText( + img, "TOTAL", (14, 14), cv2.FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv2.LINE_AA + ) + cv2.putText( + img, + str(total), + (14, 32), + cv2.FONT_HERSHEY_SIMPLEX, + 0.55, + C_GREEN, + 1, + cv2.LINE_AA, + ) + cv2.putText( + img, "LEFT", (100, 14), cv2.FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv2.LINE_AA + ) + cv2.putText( + img, + str(total_left), + (100, 32), + cv2.FONT_HERSHEY_SIMPLEX, + 0.55, + C_ZONE_LEFT, + 1, + cv2.LINE_AA, + ) + cv2.putText( + img, "RIGHT", (180, 14), cv2.FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv2.LINE_AA + ) + cv2.putText( + img, + str(total_right), + (180, 32), + cv2.FONT_HERSHEY_SIMPLEX, + 0.55, + C_ZONE_RIGHT, + 1, + cv2.LINE_AA, + ) + cv2.putText( + img, + "UPTIME", + (270, 14), + cv2.FONT_HERSHEY_SIMPLEX, + 0.32, + C_MUTED, + 1, + cv2.LINE_AA, + ) + cv2.putText( + img, + f"{elapsed_sec / 3600:.1f}h", + (270, 32), + cv2.FONT_HERSHEY_SIMPLEX, + 0.45, + C_TEXT, + 1, + cv2.LINE_AA, + ) + cv2.putText( + img, "RATE", (360, 14), cv2.FONT_HERSHEY_SIMPLEX, 0.32, C_MUTED, 1, cv2.LINE_AA + ) + cv2.putText( + img, + f"{rate:.1f}/min", + (360, 32), + cv2.FONT_HERSHEY_SIMPLEX, + 0.45, + C_ACCENT, + 1, + cv2.LINE_AA, + ) + + +def draw_footer(img, w, h, frame_idx, live_tag, inf_ms=0.0, model_name=""): + bar_h = 28 + overlay_rect(img, 0, h - bar_h, w, h, C_PANEL, alpha=0.55) + cv2.putText( + img, + f"{live_tag} | {model_name} | Frame {frame_idx} | Inf {inf_ms:.1f}ms", + (12, h - 9), + cv2.FONT_HERSHEY_SIMPLEX, + 0.45, + C_MUTED, + 1, + cv2.LINE_AA, + ) + + +def draw_skeleton_bold(img, kpts): + for (a, b), color in zip(SKELETON, SK_COLORS): + if a < len(kpts) and b < len(kpts): + xa, ya = int(kpts[a][0]), int(kpts[a][1]) + xb, yb = int(kpts[b][0]), int(kpts[b][1]) + if xa > 0 and ya > 0 and xb > 0 and yb > 0: + cv2.line(img, (xa, ya), (xb, yb), color, 3, cv2.LINE_AA) + for kp in kpts: + x, y = int(kp[0]), int(kp[1]) + if x > 0 and y > 0: + cv2.circle(img, (x, y), 6, (255, 255, 255), -1, cv2.LINE_AA) + cv2.circle(img, (x, y), 6, (40, 40, 40), 2, cv2.LINE_AA) + + +def draw_popups(img, popups, frame_idx): + alive = [] + for pop in popups: + age = frame_idx - pop["born"] + if age > POPUP_LIFETIME: + continue + alive.append(pop) + fade = 1.0 - age / POPUP_LIFETIME + y = pop["y"] - int(age * 1.8) + color = (int(C_GREEN[0] * fade), int(C_GREEN[1] * fade), int(C_GREEN[2] * fade)) + cv2.putText( + img, + pop["text"], + (pop["x"], y), + cv2.FONT_HERSHEY_SIMPLEX, + 0.7, + color, + 2, + cv2.LINE_AA, + ) + return alive + + +def connect_stream(source, warmup=WARMUP_FRAMES): + attempts = 0 + while not shutdown_requested: + cap = open_capture(source) + if not cap.isOpened(): + attempts += 1 + if MAX_RECONNECT_ATTEMPTS and attempts >= MAX_RECONNECT_ATTEMPTS: + raise RuntimeError( + f"Cannot open source after {attempts} attempts: {source}" + ) + print(f"Cannot open source, retry in {RECONNECT_DELAY_SEC}s...") + time.sleep(RECONNECT_DELAY_SEC) + continue + if warmup > 0 and source.lower().startswith(("rtsp://", "http://")): + warmup_stream(cap, warmup) + w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = cap.get(cv2.CAP_PROP_FPS) + if not fps or fps <= 1: + fps = OUTPUT_FPS + return cap, w, h, fps + return None, 0, 0, OUTPUT_FPS + + +# ============================================================================= +# Main loop +# ============================================================================= + + +def run(): + global shutdown_requested + + store = CounterStore( + db_path=DB_PATH, + state_file=STATE_FILE, + camera_name=CAMERA_NAME, + object_label=OBJECT_LABEL, + cutoff_time=DAILY_CUTOFF_TIME, + logger=lambda msg: print(f"[{now_str()}] {msg}"), + ) + store.start_cutoff_watcher() + + cross_logger = None + if EXPORT_CSV: + cross_logger = CsvLogger( + CROSS_CSV, ["counting_date", "frame", "feeder", "object_id"] + ) + + model = RKNNYOLO( + model_path=MODEL_PATH, + core_mask=CORE_MASK, + imgsz=IMGSZ, + conf=CONF, + iou=NMS_IOU, + num_classes=NUM_CLASSES, + score_sigmoid=SCORE_SIGMOID, + ) + + object_cls = int(os.getenv("OBJECT_CLASS_ID", "0")) + + object_tracker = ByteTracker( + track_high_thresh=TRACK_HIGH_THRESH, + track_low_thresh=TRACK_LOW_THRESH, + match_thresh=TRACK_MATCH_THRESH, + track_buffer=TRACK_BUFFER, + min_hits=TRACK_MIN_HITS, + ) + + # Per-track zone state: enter left → LEFT feeder; enter right → RIGHT feeder. + # Keys survive ID switches via inheritance (see _inherit_prev). + object_zone_state = {} + + recent_cross_left = deque() + recent_cross_right = deque() + # Monotonic timestamp of last successful count per feeder (for cooldown). + last_count_mono = {"left": None, "right": None} + + detect_snapshot_ids = set() + + object_cross_flash = {} + zone_pulse = count_left_pulse = count_right_pulse = 0 + popups = [] + + session_start = time.time() + frame_idx = 0 + inf_ms = 0.0 + prev_gray = None + frames_since_infer = 0 + video_writer = None + crossing_times = deque() + counter_left = 0 + counter_right = 0 + last_snapshot_cleanup = 0.0 + + counting_active = True + last_control_poll = 0.0 + control_socket = None + if CONTROL_ENABLED: + if not Path(CONTROL_FILE).exists(): + write_control_file(CONTROL_DEFAULT_COUNTING) + counting_active = read_counting_flag(CONTROL_DEFAULT_COUNTING) + print( + f"Runtime control enabled | file={CONTROL_FILE} | " + f"counting={'ON' if counting_active else 'OFF'}" + ) + if CONTROL_SOCKET_ENABLED: + try: + control_socket = start_control_socket() + except Exception as exc: + print(f"[{now_str()}] Failed to start control socket: {exc}") + + cap, w, h, fps = connect_stream(SOURCE) + if cap is None: + store.shutdown() + model.release() + return + + zone_left = resolve_zone_left(w, h) + zone_right = resolve_zone_right(w, h) + print( + f"RKNN+ByteTrack zone counter | {w}x{h} @ {fps}fps | " + f"LEFT feeder {zone_left} RIGHT feeder {zone_right}" + ) + print( + f"Cooldownoldown: left={ZONE_COOLDOWN_LEFT_SEC}s right={ZONE_COOLDOWN_RIGHT_SEC}s " + f"(0=off)" + ) + print(f"Model: {MODEL_PATH} | imgsz={IMGSZ} | core_mask={CORE_MASK}") + print( + f"ByteTrack: high_thresh={TRACK_HIGH_THRESH} low_thresh={TRACK_LOW_THRESH} " + f"match_thresh={TRACK_MATCH_THRESH} buffer={TRACK_BUFFER}" + ) + print(f"DB: {DB_PATH}") + print(f"State: {STATE_FILE}") + + if RECORD_VIDEO: + video_writer = VideoSegmentWriter(OUTPUT_DIR, w, h, fps, VIDEO_SEGMENT_SEC) + + reconnect_count = 0 + + while not shutdown_requested: + ret, frame = cap.read() + if not ret: + if not IS_LIVE: + break + reconnect_count += 1 + print( + f"Stream dropped (attempt {reconnect_count}), reconnecting in {RECONNECT_DELAY_SEC}s..." + ) + cap.release() + time.sleep(RECONNECT_DELAY_SEC) + cap, w, h, fps = connect_stream(SOURCE) + if cap is None: + break + zone_left = resolve_zone_left(w, h) + zone_right = resolve_zone_right(w, h) + continue + + now = time.time() + elapsed = now - session_start + mono = time.monotonic() + object_crossed_frame = False + cross_events_frame = [] + detect_events_frame = [] + + if CONTROL_ENABLED and (now - last_control_poll) >= CONTROL_POLL_SEC: + last_control_poll = now + new_flag = read_counting_flag(CONTROL_DEFAULT_COUNTING) + if new_flag != counting_active: + counting_active = new_flag + print(f"[{now_str()}] Counting {'RESUMED' if counting_active else 'PAUSED'} via control file") + + skip_inference = False + if not counting_active: + skip_inference = True + elif MOTION_DETECTION_ENABLED: + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + if prev_gray is not None: + diff = cv2.absdiff(gray, prev_gray) + moved = int(np.count_nonzero(diff > MOTION_PIXEL_DELTA)) + moved_frac = moved / diff.size + skip_inference = moved_frac < MOTION_MIN_AREA_FRAC + if frames_since_infer >= MOTION_HEARTBEAT_FRAMES: + skip_inference = False + prev_gray = gray + + detections = [] + if not skip_inference: + frames_since_infer = 0 + inf_start = time.time() + detections = model(frame) + inf_ms = inf_ms * 0.9 + (time.time() - inf_start) * 1000 * 0.1 + else: + frames_since_infer += 1 + + object_boxes_xyxy = [] + object_scores = [] + object_kpts_list = [] + object_cx_list = [] + object_cy_list = [] + + for det in detections: + bbox = det["bbox"] + score = det["score"] + cls_id = det["cls"] + kpts = det["keypoints"] + cx = (bbox[0] + bbox[2]) / 2.0 + cy = (bbox[1] + bbox[3]) / 2.0 + + if cls_id == object_cls: + object_boxes_xyxy.append(bbox) + object_scores.append(score) + object_kpts_list.append(kpts) + object_cx_list.append(cx) + object_cy_list.append(cy) + + object_boxes_xyxy = np.array(object_boxes_xyxy, dtype=np.float32).reshape(-1, 4) + object_scores = np.array(object_scores, dtype=np.float32) + + object_track_map, object_det_to_track, object_lost_map = object_tracker.update( + object_boxes_xyxy, object_scores + ) + + if os.getenv("DEBUG_TRACKING", "").lower() == "true": + if len(object_boxes_xyxy) > 0: + scores_str = ( + f" scores: {object_scores.round(3).tolist()}" + if len(object_scores) > 0 + else "" + ) + tracks_str = ( + f" det->track: {dict(object_det_to_track)}" + if object_det_to_track + else "" + ) + zone_str = "" + if object_zone_state: + left_ids = sorted( + tid + for tid, st in object_zone_state.items() + if st.get("side") == "left" + ) + right_ids = sorted( + tid + for tid, st in object_zone_state.items() + if st.get("side") == "right" + ) + if left_ids: + zone_str += f" left_counted: {left_ids}" + if right_ids: + zone_str += f" right_counted: {right_ids}" + print( + f"[DEBUG F{frame_idx}] dets={len(object_boxes_xyxy)} " + f"tracks={len(object_track_map)} " + f"zone_L={zone_left} zone_R={zone_right}{scores_str}" + f"{tracks_str}{zone_str}" + ) + + # --- zone entry detection only on DETECTED objects this frame --- + # (tracker still updates every frame to preserve IDs, but we do NOT + # count on Kalman-predicted/coasting tracks to avoid double counts) + for di in range(len(object_boxes_xyxy)): + tid = object_det_to_track.get(di) + if tid is None: + continue + cx = object_cx_list[di] + cy = object_cy_list[di] + + if tid not in detect_snapshot_ids: + detect_snapshot_ids.add(tid) + detect_events_frame.append(tid) + + if tid not in object_tracked: + inherited = _inherit_prev( + object_tracked, tid, cx, cy, mono, INHERIT_SEC, INHERIT_PX + ) + if inherited is not None: + object_tracked[tid] = inherited[:3] + src_tid = inherited[3] + if src_tid in object_zone_state: + object_zone_state[tid] = _copy_zone_state( + object_zone_state[src_tid] + ) + if os.getenv("DEBUG_TRACKING", "").lower() == "true": + src_st = object_zone_state.get(tid, {}) + print( + f"[DEBUG F{frame_idx}] INHERIT prev for new tid={tid} " + f"from tid={src_tid} ({inherited[0]:.1f},{inherited[1]:.1f})" + f" counted={src_st.get('counted', False)}" + f" side={src_st.get('side')}" + ) + + if tid not in object_zone_state: + object_zone_state[tid] = _default_zone_state() + st = object_zone_state[tid] + + now_left = point_in_zone(cx, cy, zone_left) + now_right = point_in_zone(cx, cy, zone_right) + + entered_left = False + entered_right = False + if tid in object_tracked: + prev_cx, prev_cy = object_tracked[tid][0], object_tracked[tid][1] + prev_left = point_in_zone(prev_cx, prev_cy, zone_left) + prev_right = point_in_zone(prev_cx, prev_cy, zone_right) + entered_left = now_left and not prev_left + entered_right = now_right and not prev_right + else: + # First observation: count if the centroid already sits in a zone. + entered_left = now_left + entered_right = now_right + + if (entered_left or entered_right) and not st["counted"]: + # Prefer the zone whose center is closer if both fire in one jump. + feeder = None + if entered_left and entered_right: + lx1, ly1, lx2, ly2 = zone_left + rx1, ry1, rx2, ry2 = zone_right + dl = abs(cx - (lx1 + lx2) / 2) + abs(cy - (ly1 + ly2) / 2) + dr = abs(cx - (rx1 + rx2) / 2) + abs(cy - (ry1 + ry2) / 2) + feeder = "left" if dl <= dr else "right" + elif entered_left: + feeder = "left" + else: + feeder = "right" + + recent = ( + recent_cross_left if feeder == "left" else recent_cross_right + ) + if is_duplicate_cross(recent, cx, cy, frame_idx): + st["counted"] = True + st["side"] = feeder + if os.getenv("DEBUG_TRACKING", "").lower() == "true": + print( + f"[DEBUG F{frame_idx}] DUP ZONE IGNORED: tid={tid} " + f"cx={cx:.1f} cy={cy:.1f} feeder={feeder}" + ) + object_tracked[tid] = (cx, cy, mono) + continue + + if feeder_in_cooldown(feeder, mono, last_count_mono): + st["counted"] = True + st["side"] = feeder + if os.getenv("DEBUG_TRACKING", "").lower() == "true": + cool = feeder_cooldown_sec(feeder) + elapsed = mono - (last_count_mono.get(feeder) or mono) + print( + f"[DEBUG F{frame_idx}] COOLDOWN IGNORED: tid={tid} " + f"feeder={feeder} elapsed={elapsed:.2f}s / {cool}s" + ) + object_tracked[tid] = (cx, cy, mono) + continue + + if os.getenv("DEBUG_TRACKING", "").lower() == "true": + print( + f"[DEBUG F{frame_idx}] ZONE ENTER: tid={tid} " + f"cx={cx:.1f} cy={cy:.1f} feeder={feeder}" + ) + + recent.append((frame_idx, cx, cy)) + st["counted"] = True + st["side"] = feeder + last_count_mono[feeder] = mono + if feeder == "left": + counter_left += 1 + count_left_pulse = COUNT_PULSE_FRAMES + else: + counter_right += 1 + count_right_pulse = COUNT_PULSE_FRAMES + store.record_zone_entry(tid, feeder) + if cross_logger: + cross_logger.write_row( + [ + store.get_counting_date(), + frame_idx, + feeder, + tid, + ] + ) + object_crossed_frame = True + cross_events_frame.append((tid, feeder)) + crossing_times.append(mono) + object_cross_flash[tid] = CROSS_FLASH_FRAMES + popups.append( + { + "x": int(cx) - 12, + "y": int(cy), + "born": frame_idx, + "text": f"+1 {feeder.upper()}", + } + ) + object_tracked[tid] = (cx, cy, mono) + + for tid, (cx, cy) in object_lost_map.items(): + if tid not in object_tracked: + object_tracked[tid] = (cx, cy, mono) + + for di in range(len(object_boxes_xyxy)): + tid = object_det_to_track.get(di) + if tid is None: + continue + bbox = object_boxes_xyxy[di] + x1, y1, x2, y2 = int(bbox[0]), int(bbox[1]), int(bbox[2]), int(bbox[3]) + flash = object_cross_flash.get(tid, 0) + color = C_GREEN if flash > 0 else C_OBJECT_BOX + cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3 if flash > 0 else 2) + draw_pill(frame, f"ID {tid}", x1, y1 - 4, color) + kpts = object_kpts_list[di] if di < len(object_kpts_list) else None + if kpts is not None: + draw_skeleton_bold(frame, kpts) + + if object_crossed_frame: + zone_pulse = ZONE_PULSE_FRAMES + + display_total = store.display_total() + 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 + + draw_elegant_zone( + frame, zone_left, zone_pulse, label="LEFT FEEDER", color=C_ZONE_LEFT + ) + draw_elegant_zone( + frame, zone_right, zone_pulse, label="RIGHT FEEDER", color=C_ZONE_RIGHT + ) + draw_zone_count( + frame, zone_left, counter_left, "LEFT", C_ZONE_LEFT, count_left_pulse + ) + draw_zone_count( + frame, zone_right, counter_right, "RIGHT", C_ZONE_RIGHT, count_right_pulse + ) + draw_hud( + frame, + w, + counter_left + counter_right, + counter_left, + counter_right, + elapsed, + rate, + ) + draw_footer( + frame, + w, + h, + frame_idx, + "LIVE" if IS_LIVE else "FILE", + inf_ms, + Path(MODEL_PATH).name, + ) + popups = draw_popups(frame, popups, frame_idx) + + if CONTROL_ENABLED and not counting_active: + badge = "COUNTING PAUSED" + (bw, bh), _ = cv2.getTextSize(badge, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2) + bx = w // 2 - bw // 2 + overlay_rect(frame, bx - 14, 48, bx + bw + 14, 48 + bh + 18, C_PANEL, alpha=0.75) + cv2.rectangle(frame, (bx - 14, 48), (bx + bw + 14, 48 + bh + 18), C_ACCENT, 2) + cv2.putText(frame, badge, (bx, 48 + bh + 6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, C_ACCENT, 2, cv2.LINE_AA) + + for tid in list(object_cross_flash): + object_cross_flash[tid] -= 1 + if object_cross_flash[tid] <= 0: + del object_cross_flash[tid] + zone_pulse = max(0, zone_pulse - 1) + count_left_pulse = max(0, count_left_pulse - 1) + count_right_pulse = max(0, count_right_pulse - 1) + + if video_writer is not None: + video_writer.write(frame) + + if LIVE_STREAM_ENABLED and frame_idx % LIVE_STREAM_EVERY_N == 0: + try: + Path(LIVE_STREAM_FRAME_PATH).parent.mkdir(parents=True, exist_ok=True) + ok, jpeg = cv2.imencode( + ".jpg", frame, [cv2.IMWRITE_JPEG_QUALITY, LIVE_STREAM_QUALITY] + ) + if ok: + tmp_path = f"{LIVE_STREAM_FRAME_PATH}.tmp" + with open(tmp_path, "wb") as f: + f.write(jpeg.tobytes()) + os.replace(tmp_path, LIVE_STREAM_FRAME_PATH) + except Exception: + pass + + if (SAVE_DETECT_SNAPSHOT and detect_events_frame) or ( + SAVE_CROSS_SNAPSHOT and cross_events_frame + ): + try: + ts = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3] + if SAVE_DETECT_SNAPSHOT and detect_events_frame: + detect_dir = Path(CROSS_SNAPSHOT_DIR) / "detect" + detect_dir.mkdir(parents=True, exist_ok=True) + for tid in detect_events_frame: + fname = f"{ts}_detect_id{tid}_f{frame_idx}.jpg" + cv2.imwrite( + str(detect_dir / fname), + frame, + [cv2.IMWRITE_JPEG_QUALITY, CROSS_SNAPSHOT_QUALITY], + ) + if SAVE_CROSS_SNAPSHOT and cross_events_frame: + cross_dir = Path(CROSS_SNAPSHOT_DIR) / "cross" + cross_dir.mkdir(parents=True, exist_ok=True) + for tid, feeder in cross_events_frame: + fname = f"{ts}_{feeder}_id{tid}_f{frame_idx}.jpg" + cv2.imwrite( + str(cross_dir / fname), + frame, + [cv2.IMWRITE_JPEG_QUALITY, CROSS_SNAPSHOT_QUALITY], + ) + if now - last_snapshot_cleanup >= CROSS_SNAPSHOT_CLEANUP_SEC: + cleanup_snapshots( + CROSS_SNAPSHOT_DIR, + CROSS_SNAPSHOT_MAX_FILES, + CROSS_SNAPSHOT_MAX_AGE_DAYS, + ) + last_snapshot_cleanup = now + except Exception as exc: + print(f"[{now_str()}] Failed to save snapshot: {exc}") + + frame_idx += 1 + prune_stale_tracks(object_tracked, mono) + + cap.release() + if video_writer is not None: + video_writer.release() + if cross_logger: + cross_logger.close() + if control_socket is not None: + try: + control_socket.close() + except Exception: + pass + model.release() + store.shutdown() + + print("\n=== Daily Counter Summary (SQLite) ===") + print(f"Database: {DB_PATH}") + + +object_tracked = {} + + +if __name__ == "__main__": + run() \ No newline at end of file diff --git a/counter_store.py b/counter_store.py new file mode 100644 index 0000000..3de4e73 --- /dev/null +++ b/counter_store.py @@ -0,0 +1,256 @@ +""" +Production daily counter persistence for edge sack feeder counter. +Tracks left / right feeder zone entries and the daily total per counting day, +delimited by the daily cutoff time. SQLite schema + current_counter.json state. + +Feeders: + left → left feeder zone + right → right feeder zone +""" +import json +import sqlite3 +import threading +import time +from datetime import datetime, timedelta +from pathlib import Path + + +class CounterStore: + def __init__( + self, + db_path, + state_file, + camera_name, + object_label='object', + cutoff_time='20:00', + carry_ids=50, + logger=print, + ): + self.db_path = db_path + self.state_file = Path(state_file) + self.camera_name = camera_name + self.object_label = object_label + self.cutoff_time_str = cutoff_time + datetime.strptime(cutoff_time, '%H:%M') + + self.carry_ids = int(carry_ids) + self.log = logger + + self.state_lock = threading.Lock() + self.shutdown_event = threading.Event() + + Path(db_path).parent.mkdir(parents=True, exist_ok=True) + self.state_file.parent.mkdir(parents=True, exist_ok=True) + + self.db = sqlite3.connect(db_path, check_same_thread=False) + self._init_db() + self.current_state = self._load_state() + + def _init_db(self): + cur = self.db.cursor() + cur.execute( + """ + CREATE TABLE IF NOT EXISTS daily_counters ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + counting_date TEXT NOT NULL, + camera_name TEXT NOT NULL, + object_label TEXT NOT NULL, + total_count INTEGER NOT NULL DEFAULT 0, + total_left INTEGER NOT NULL DEFAULT 0, + total_right INTEGER NOT NULL DEFAULT 0, + start_time TEXT, + end_time TEXT, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(counting_date, camera_name, object_label) + ) + """ + ) + self.db.commit() + + def get_counting_date(self, dt=None): + if dt is None: + dt = datetime.now() + cutoff = datetime.strptime(self.cutoff_time_str, '%H:%M').time() + if dt.time() < cutoff: + return dt.date().isoformat() + return (dt.date() + timedelta(days=1)).isoformat() + + def _normalize_state(self, state): + state.setdefault('count_left', 0) + state.setdefault('count_right', 0) + state.setdefault('count', state['count_left'] + state['count_right']) + state.setdefault('counted_event_ids', []) + return state + + def _load_state(self): + if not self.state_file.exists(): + return None + try: + with open(self.state_file, 'r', encoding='utf-8') as f: + state = json.load(f) + current_date = self.get_counting_date() + if state.get('counting_date') != current_date: + self.log( + f"State file belongs to previous counting day " + f"({state.get('counting_date')}). Starting fresh." + ) + self.state_file.unlink(missing_ok=True) + return None + state = self._normalize_state(state) + self.log( + f"Resumed {current_date} with total={state['count']} " + f"(left={state['count_left']} right={state['count_right']})" + ) + return state + except Exception as exc: + self.log(f'Failed to load state file: {exc}') + return None + + def save_state(self): + if self.current_state is None: + self.state_file.unlink(missing_ok=True) + return + with open(self.state_file, 'w', encoding='utf-8') as f: + json.dump(self.current_state, f, indent=2, ensure_ascii=False) + + def _start_new_day(self, counting_date): + now = datetime.now().isoformat() + carried = [] + if self.current_state is not None: + try: + carried = self.current_state['counted_event_ids'][-self.carry_ids:] + except (KeyError, TypeError): + carried = [] + self.current_state = { + 'counting_date': counting_date, + 'count': 0, + 'count_left': 0, + 'count_right': 0, + 'start_time': now, + 'last_detection_time': now, + 'counted_event_ids': carried, + } + self.save_state() + 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'.""" + if feeder not in ('left', 'right'): + raise ValueError(f"feeder must be 'left' or 'right', got {feeder!r}") + with self.state_lock: + counting_date = self.get_counting_date() + day_started = False + if self.current_state is None or self.current_state['counting_date'] != counting_date: + self._start_new_day(counting_date) + day_started = True + + event_key = f"{track_id}_{feeder}" + if event_key not in self.current_state['counted_event_ids']: + self.current_state['count'] += 1 + if feeder == 'left': + self.current_state['count_left'] += 1 + else: + self.current_state['count_right'] += 1 + self.current_state['counted_event_ids'].append(event_key) + self.log( + f'Counted {feeder} feeder (track {track_id}) | {counting_date} ' + f'total: {self.current_state["count"]} ' + f'(left={self.current_state["count_left"]} ' + f'right={self.current_state["count_right"]})' + ) + self._persist_day() + + self.current_state['last_detection_time'] = datetime.now().isoformat() + self.save_state() + return self.current_state['count'], day_started + + def _persist_day(self): + state = self.current_state + cur = self.db.cursor() + cur.execute( + """ + INSERT INTO daily_counters + (counting_date, camera_name, object_label, + total_count, total_left, total_right, start_time, end_time) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(counting_date, camera_name, object_label) + DO UPDATE SET + total_count = excluded.total_count, + total_left = excluded.total_left, + total_right = excluded.total_right, + end_time = excluded.end_time, + updated_at = CURRENT_TIMESTAMP + """, + ( + state['counting_date'], self.camera_name, self.object_label, + state['count'], state['count_left'], state['count_right'], + state['start_time'], datetime.now().isoformat(), + ), + ) + self.db.commit() + + def cutoff_watcher_loop(self): + while not self.shutdown_event.is_set(): + time.sleep(60) + with self.state_lock: + if self.current_state is None: + continue + if self.current_state['counting_date'] != self.get_counting_date(): + self.log('Daily cutoff reached - finalizing day totals') + self._persist_day() + self.current_state = None + self.save_state() + + def start_cutoff_watcher(self): + t = threading.Thread(target=self.cutoff_watcher_loop, daemon=True) + t.start() + return t + + @property + def current_count(self): + if self.current_state is None: + return 0 + return self.current_state['count'] + + @property + def current_count_left(self): + if self.current_state is None: + return 0 + return self.current_state.get('count_left', 0) + + @property + def current_count_right(self): + if self.current_state is None: + return 0 + return self.current_state.get('count_right', 0) + + def _day_totals(self, counting_date=None): + if counting_date is None: + counting_date = self.get_counting_date() + cur = self.db.cursor() + cur.execute( + """ + SELECT COALESCE(total_count, 0), COALESCE(total_left, 0), COALESCE(total_right, 0) + FROM daily_counters + WHERE counting_date = ? AND camera_name = ? AND object_label = ? + """, + (counting_date, self.camera_name, self.object_label), + ) + row = cur.fetchone() + return row if row else (0, 0, 0) + + def display_total(self): + return self._day_totals()[0] + + def display_left(self): + return self._day_totals()[1] + + def display_right(self): + return self._day_totals()[2] + + def shutdown(self): + self.shutdown_event.set() + with self.state_lock: + if self.current_state is not None: + self._persist_day() + self.db.close() diff --git a/env.example b/env.example new file mode 100644 index 0000000..cd4ca2c --- /dev/null +++ b/env.example @@ -0,0 +1,117 @@ +# ============================================================================= +# ZenAI KTC — sack feeder zone counter (ByteTrack + left/right zones) +# Shared config for: counter_live_rknn.py + counter_dashboard.py +# Copy to .env on device: cp env.example .env && nano .env +# ============================================================================= + +# --- Core paths --- +OUTPUT_DIR=/opt/zenai-ktc-counter +DB_PATH=/opt/zenai-ktc-counter/counter.db +STATE_FILE=/opt/zenai-ktc-counter/current_counter.json + +# --- Input source --- +#SOURCE=rtsp://user:pass@192.168.0.100:554/stream1 +SOURCE=rtsp://10.38.30.64:8554/my_stream +OPENCV_FFMPEG_CAPTURE_OPTIONS=rtsp_transport;tcp|fflags;nobuffer|flags;low_delay + +# --- RKNN model --- +MODEL_PATH=/opt/models/zenai_kac_sukawarna_20260716.rknn +IMGSZ=320 +HALF=false +CORE_MASK=1 +DEVICE=0 + +# --- YOLO decoder --- +NUM_CLASSES=4 +SCORE_SIGMOID=false + +# --- Detection --- +CONF=0.5 + +# --- ByteTrack tracking --- +TRACK_HIGH_THRESH=0.5 +TRACK_LOW_THRESH=0.3 +TRACK_MATCH_THRESH=0.7 +TRACK_BUFFER=60 +TRACK_MIN_HITS=3 + +# --- Display --- +SITE_NAME=ZenAi + +# --- Object class names --- +CAMERA_NAME=ZenAi +OBJECT_LABEL=karung +CLASS_OBJECT=karung +OBJECT_CLASS_ID=0 + +# --- Feeder zones (left / right) --- +# Rectangular zones as fractions of frame width/height. +# Absolute pixel overrides: ZONE_LEFT_X1, ZONE_LEFT_Y1, ZONE_LEFT_X2, ZONE_LEFT_Y2 +# (and the matching ZONE_RIGHT_*). Absolute values win when set. +# +# A sack is counted once when its centroid ENTERS a zone. +# LEFT zone → left feeder +# RIGHT zone → right feeder +ZONE_LEFT_X1_FRAC=0.02 +ZONE_LEFT_Y1_FRAC=0.10 +ZONE_LEFT_X2_FRAC=0.440 +ZONE_LEFT_Y2_FRAC=1.00 + +ZONE_RIGHT_X1_FRAC=0.490 +ZONE_RIGHT_Y1_FRAC=0.10 +ZONE_RIGHT_X2_FRAC=0.98 +ZONE_RIGHT_Y2_FRAC=1.00 + +# --- Counting day management --- +DAILY_CUTOFF_TIME=17:00 +CUTOFF_TIME=17:00 + +# --- CSV export --- +EXPORT_CSV=false +CROSS_CSV=/tmp/ktc_crossings.csv + +# --- Rate / performance --- +MOTION_DETECTION_ENABLED=true +MOTION_THRESHOLD=5.0 +RATE_WINDOW_SEC=60 +WARMUP_FRAMES=30 +RECONNECT_DELAY_SEC=3 +MAX_RECONNECT_ATTEMPTS=0 +TRACKED_PRUNE_SEC=300 + +# --- ID-switch counting guards --- +DEDUP_FRAMES=15 +DEDUP_PX=60 +INHERIT_SEC=1.0 +INHERIT_PX=60 + +# --- Feeder cooldown (seconds) --- +# After a sack is counted on a feeder, ignore further counts on that same feeder +# for this many seconds. 0 = disabled. +ZONE_COOLDOWN_LEFT_SEC=15 +ZONE_COOLDOWN_RIGHT_SEC=15 + +# --- Video recording --- +RECORD_VIDEO=false +VIDEO_SEGMENT_SEC=3600 +OUTPUT_FPS=15 + +# --- Live stream snapshot --- +LIVE_STREAM_ENABLED=true +LIVE_STREAM_FRAME_PATH=/dev/shm/zenai-ktc-counter/live_frame.jpg +LIVE_STREAM_QUALITY=75 +LIVE_STREAM_EVERY_N=2 + +# --- Dashboard --- +SECRET_KEY=change-me-in-production +DASHBOARD_HOST=0.0.0.0 +DASHBOARD_PORT=5000 +FLASK_DEBUG=false +CURRENT_COUNTER_PATH=/tmp/ktc_current_counter.json + +SAVE_CROSS_SNAPSHOT=true +CROSS_SNAPSHOT_DIR=/opt/zenai-ktc-snaps/snapshots +CROSS_SNAPSHOT_CLEANUP_SEC=3600 +CROSS_SNAPSHOT_MAX_AGE_DAYS=7 + + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f9305e3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +numpy<2 +rknn-toolkit-lite2 +opencv-python +flask +python-dotenv +openpyxl diff --git a/templates/dashboard.html b/templates/dashboard.html new file mode 100644 index 0000000..9e54ef0 --- /dev/null +++ b/templates/dashboard.html @@ -0,0 +1,1220 @@ + + + + + +ZenAI KTC Dashboard + + + + + + +
+
+
+
+ +
+ +
+
+
◆
+
+

ZenAI KTC Module

+
Sack feeder zone counter — YOLO RockChip + ByteTrack
+
+
+
+
+ -- + Counting Day +
+
+ + {{ site_name }} +
+ SNAPSHOTS + {% if control_enabled %}{% endif %} + +
+
+ + +
+
+ LIVE +
+
--
+
Total Today (Left + Right)
+
+
+
Left
+
--
+
+
+
Right
+
--
+
+
+
+
+ Yesterday +
+
--
+
Total Yesterday (Left + Right)
+
+
+
Left
+
--
+
+
+
Right
+
--
+
+
+
+
+ + +
+ -- + -- + -- + -- + -- + -- + -- + -- + -- +
+ + +
+ -- + -- +
+ + +
+
+ ◉ Live Camera Feed +
+ + + waiting... + + +
+
+
+
+
▦
+
Live Feed Unavailable
+
Enable LIVE_STREAM_ENABLED=true in counter .env
+
+ +
Connection lost — retrying...
+
+
+ + +
+
+
+ ◉ Daily Trends +
+ + + +
+
+
+ +
+
+
+ ◉ Quick Stats +
+
+
+
+
+
Grand Total
+
All time (Left + Right)
+
+
+ -- +
+
+
+
+
+
Total Left
+
All time
+
+
+ -- +
+
+
+
+
+
Total Right
+
All time
+
+
+ -- +
+
+ +
+
◉ Recent Days
+
+ +
+
+
+
+ + +
+
+
+ ◉ Daily Records +
Daily counter totals at cut-off
+
+
+ + + + +
+
+
+ + + + + + + + + + + + + +
DateTotalLeftRightStatus
+
+
+ + +
+ + + + + + + \ No newline at end of file diff --git a/templates/snapshots.html b/templates/snapshots.html new file mode 100644 index 0000000..37dee24 --- /dev/null +++ b/templates/snapshots.html @@ -0,0 +1,489 @@ + + + + + +ZenAI KPC Snapshots + + + + + +
+
+
+ +
+ +
+
+
◆
+
+

ZenAI KPC Snapshots

+
Detected & counted frames — correlate by track ID
+
+
+
+
+ + {{ site_name }} +
+ DASHBOARD + SNAPSHOTS + +
+
+ + +
+
+
+ ◉ Zone Entry Snapshots +
--
+
+
+
+ + + + {% if show_detect %}{% endif %} +
+ + + + +
+
+
+ +
+
+ +
+ + +
+ + + + + + + + diff --git a/zenai-ktc-counter.service b/zenai-ktc-counter.service new file mode 100644 index 0000000..9bbb47b --- /dev/null +++ b/zenai-ktc-counter.service @@ -0,0 +1,32 @@ +[Unit] +Description=ZenAI KTC Edge Zone Counter (RTSP + RKNN + ByteTrack) +Documentation=file:///opt/zenai-ktc-python/DEPLOY.md +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=root +Group=root + +WorkingDirectory=/opt/zenai-ktc-python +EnvironmentFile=/opt/zenai-ktc-python/.env +Environment=PYTHONNOUSERSITE=1 +Environment=PATH=/opt/zenai-ktc-python/venv/bin:/usr/local/bin:/usr/bin:/bin + +ExecStart=/opt/zenai-ktc-python/venv/bin/python counter_live_rknn.py + +TimeoutStopSec=30 +KillSignal=SIGTERM + +Restart=always +RestartSec=10 +StartLimitInterval=120s +StartLimitBurst=5 + +NoNewPrivileges=true +ProtectHome=true +PrivateTmp=false + +[Install] +WantedBy=multi-user.target diff --git a/zenai-ktc-dashboard.service b/zenai-ktc-dashboard.service new file mode 100644 index 0000000..e156bab --- /dev/null +++ b/zenai-ktc-dashboard.service @@ -0,0 +1,32 @@ +[Unit] +Description=ZenAI KTC Dashboard (Flask) +Documentation=file:///opt/zenai-ktc-python/DEPLOY.md +After=network-online.target zenai-ktc-counter.service +Wants=network-online.target + +[Service] +Type=simple +User=root +Group=root + +WorkingDirectory=/opt/zenai-ktc-python +EnvironmentFile=/opt/zenai-ktc-python/.env +Environment=PATH=/opt/zenai-ktc-python/venv/bin:/usr/local/bin:/usr/bin:/bin +Environment=FLASK_DEBUG=false + +ExecStart=/opt/zenai-ktc-python/venv/bin/python counter_dashboard.py + +TimeoutStopSec=15 +KillSignal=SIGTERM + +Restart=always +RestartSec=5 +StartLimitInterval=60s +StartLimitBurst=3 + +NoNewPrivileges=true +ProtectHome=true +PrivateTmp=false + +[Install] +WantedBy=multi-user.target diff --git a/zone_preview.jpg b/zone_preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..af58de0aae48e8a44c6c5e7e04377000cfd7b6e6 GIT binary patch literal 240106 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

>D=DZA{{kC;-oBcMYR7-*F$_T&EUJ!6 zk$F2R--w&~3lL!|yOLfs4ocV9z5g~SPv2{umrK6&?bXu!o^WkaEy-dRi%i&#l%aO3 zoJoa0OS~#(uHy_xi4_e`)CCU#Dxr(ur+dAX>p}@-qiKKwS4m#{p~ri+Pc4yWrUH<@ zTt~I;x0xw>*#cl?QfslKoJM?|4?%_6`ueLsN}S!H!5W&wn%8;fY%Bb?#vl+q(o+J}hpK>M|XnifRrjq1%9A z%6T=+lfB!HXpw+lseuNPI~wxm9%P|gKf{`067Jr?5&S5<>oSB1UQum_V^EVh$5X;O z>Fgu5dc!w%)%&O{s~?mk*X@>0iH099NNwdmSow~jlv4rxS&w`B6WQ}REjeTA%d?McVfCc!Hl z+L4pWkrGx^bXB0hw7Brj#_5`L#t)UJxFLeNQ8W<3BOYg*%9`(e^lMmhk!254pDKC> zez)kL2WOuWb=!q%!rUU6np7XSn|wSy{P-F^)Iy}#7=Dc;h&QHM*gk%zGCuHJ+!&Ws z*cY6Sr}mhpB@AZ4aaVB3h!p~R=D_&vkB1r#?z}s@BzU=1Om9*76b$6*{lbdZ-q-N- zDOu4ygv49@<}hkaDbI8%6o?^4JwEBYHbnjc*S}pFCP zf(kk1?-oN=6dSa=_;|LrN9D{7fFYELV7iz0pk|nA+E=(_* z(Ga1tE}gSxSxDisD3EpV_J`zoXP+7?oIMeI1vCXNP5#$khyDikkVmUs*qB~Ti^evKZ zhCQZcD2BjyRJ!VDi89_wY&f_IUTQEVMBxsdxxz+ zmyy{{Tw7CTCeD+C+lo{h4X*5`asfhyP#&;lHGE* z^-NmD^;O~&)|4!vo{JRW{y!BZW-x`g*N>%K*PLMIZ85$N@A40Q=}>s>2Cq;qCPgU2 z^`N|8;5;w`l_GcZMN`rX7O%`7YcbDF9;T7OGMteFzzSS&>V|EHZ2*F;Ct=0b{1T9O zSr}AFv$ETlFZ<+&BwZM@

eBf<*WdDrf^j`Fg^abZ>qPsQ1C6YGI?6? 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%0A>Bp$0#^yjyJ7|7jl8 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

njv1kn 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 z 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

x4_@9+m=dB)Eo?ttpH~x-`qNOwUi_z&gmx+ZxTR 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 literal 0 HcmV?d00001