Files
zenai-ktc-python/config.env.example
T

258 lines
11 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 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).
# Per-zone cooldown / dwell are set on ZONE_i_COOLDOWN_SEC and ZONE_i_DWELL_SEC below.
# --- Display ---
# Site name shown on the dashboard header
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=karung
# Class name for the counted object (must match model class order)
CLASS_OBJECT=karung
# Model class ID for the object being counted (default 0)
OBJECT_CLASS_ID=0
# Feeder / zone display names come from ZONE_i_NAME (see zones below).
# Verbose tracking debug (inherit / dup / cooldown / per-frame dets)
DEBUG_TRACKING=false
# --- Counting zones (1…N) ---
# Rectangular zones. Count once after dwell. Absolute pixels win over fracs.
ZONE_COUNT=1
ZONE_1_NAME=kandang_bawah_feeder
ZONE_1_X1=
ZONE_1_Y1=
ZONE_1_X2=
ZONE_1_Y2=
ZONE_1_X1_FRAC=0.10
ZONE_1_Y1_FRAC=0.10
ZONE_1_X2_FRAC=0.90
ZONE_1_Y2_FRAC=1.00
ZONE_1_COOLDOWN_SEC=3
ZONE_1_DWELL_SEC=2
# Example two-zone setup (uncomment + set ZONE_COUNT=2):
# ZONE_COUNT=2
# ZONE_1_NAME=kandang_bawah_feeder_kiri
# ZONE_1_X1_FRAC=0.02
# ZONE_1_Y1_FRAC=0.10
# ZONE_1_X2_FRAC=0.440
# ZONE_1_Y2_FRAC=1.00
# ZONE_1_COOLDOWN_SEC=3
# ZONE_1_DWELL_SEC=2
# ZONE_2_NAME=kandang_bawah_feeder_kanan
# ZONE_2_X1=
# ZONE_2_Y1=
# ZONE_2_X2=
# ZONE_2_Y2=
# ZONE_2_X1_FRAC=0.490
# ZONE_2_Y1_FRAC=0.10
# ZONE_2_X2_FRAC=0.98
# ZONE_2_Y2_FRAC=1.00
# ZONE_2_COOLDOWN_SEC=3
# ZONE_2_DWELL_SEC=2
# --- Counting day management ---
# Daily cutoff time (HH:MM) – a new counting day starts after this time and the
# previous day's zone 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 <DIR>/cross/
# (filename: <YYYYmmdd_HHMMSS_mmm>_<zone_i>_id<track>_f<frame>.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 <DIR>/detect/ with the same track id so
# it can be correlated with the zone-entry snapshot
# (filename: <YYYYmmdd_HHMMSS_mmm>_detect_id<track>_f<frame>.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
# Max stream-error log lines per outage (Cannot open / Stream dropped).
# After this, further errors are silent until the stream recovers; then the
# budget resets for the next outage. 0 = unlimited.
STREAM_ERROR_LOG_MAX=3
# 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