Legacy manual batch start locked until plate entered: - POST /api/batch/start manual branch returns 400 missing_plate when plate empty (strip + uppercase, no format regex) - operator + monitoring start modals gain required plate input, confirm button disabled until filled - operator plate tile also shows for manual batches (was do_manual only) - do_manual unchanged (plate from DOs)
Karung Counter
Repo:
https://git.proit.id/andrew/karung-counting-feedmill-semarang
AI video-analytics system that counts feed sacks (karung-pakan) being loaded onto /
unloaded from trucks at a feedmill loading gate. It watches an RTSP camera, detects the
truck bed, tracks sacks with persistent IDs, counts line-crossings per truck (batch),
persists results to SQLite/CSV, and serves a live Flask dashboard.
Language note: UI strings, logs and comments are largely in Indonesian (
karung= sack/bag,truk= truck,muat= load). Class names inside the YOLO models are English (sack,box,truck,person).
Pipeline (production, predict.py)
Frame → TruckDetect → ROI → SackTrack → Stabilize → Count → Dashboard / DB
| Stage | Module | What it does |
|---|---|---|
| Stream | src/streaming.py |
RTSP (RTSPSource) or video file (VideoFileSource) |
| Truck detect | src/detection.py (TruckDetector) |
Dedicated truck model, run every 15 frames |
| ROI | src/truck_roi.py (TruckROITracker) |
Picks main truck in lane, EMA-smooths bbox, derives counting line |
| Sack track | src/tracking.py (ByteTrackTracker) |
YOLO + FastTrack/ByteTrack, tuned via cfg/tracker.yaml |
| Stabilize | src/stabilizer.py (BboxStabilizer) |
EMA bbox smoothing + occlusion hold + height clamps |
| Count | src/counting.py (LineCrossCounter) |
Zone-based line crossing: loading / unloading / net, 3-layer dedup |
| Batch | src/batch.py (BatchLifecycleManager) |
4-state FSM: IDLE → TRUCK_STABILIZING → COUNTING_SACKS ⇄ WAITING_FOR_ACTIVITY |
| Output | src/logger.py, src/dashboard.py |
CSV logs + on-frame overlay |
Full detail: docs/architecture.md.
Quickstart
pip install -r requirements.txt # Jetson: never pip-install torch from PyPI, use NVIDIA wheels
cp .env.example .env # then edit RTSP_URL / paths
# Dev / offline (any flags omitted = production defaults):
python predict.py --source path/to/video.mp4 --env .env
python predict.py --source vid.mp4 --no-dashboard --no-db --output-dir /tmp/out --max-frames 500
python predict.py --help # all flags: --config/--model/--model-mode/--output-json/--sack-conf/--truck-conf/--box-conf/--box-model/--batch-timeout
# Production (Jetson systemd, zero flags):
sudo systemctl restart karung-counter karung-counter-dashboard
Production on the Jetson runs predict.py + counter_dashboard.py as systemd services
(see docs/deployment.md) — predict.py is the production
pipeline (SQLite persistence, live-frame publishing to /dev/shm, zone polygons);
the src/ package is the shared detection/tracking/counting library it builds on
(the old v3 src/main.py loop is deprecated). Retired experiments live in archive/.
Models
All weights live in models/ (see models/modelREADME.md for the
per-mode detector/filter matrix).
| File | Classes | Role |
|---|---|---|
models/truck-detector.{pt,engine} |
truck |
Specialized truck detector (ROI, batch lifecycle) |
models/v4-best.{pt,onnx,engine} / models/model_karung_truk.{pt,onnx,engine} |
sack, truck |
Combined sack+truck (Modes A/B/C/D truck; Modes A/C sack) |
models/karung-dimuat-…-seg-200e.{pt,onnx,engine} |
person, sack |
Segmentation model: sacks counted, persons drawn/skipped |
models/yolo11n-bbox-100ep-sack+box-20260909-best.{pt,onnx,engine} |
sack, box |
Unified sack+box (Modes B/C/D) |
models/best.{pt,onnx,engine} |
sack |
Sack-only specialist (Mode D sack) |
.pt = PyTorch, .engine = TensorRT FP16 (Jetson GPU, what production loads),
.onnx = ONNX export artifact.
See docs/models.md for the multi-model / multi-class / hybrid
support matrix.
Configuration
| File | Purpose |
|---|---|
config.yaml |
Canonical config: stream, model modes/presets, counting knobs, batch, output paths, camera |
.env (see .env.example) |
Secrets + deployment only: RTSP URL, dashboard host/ports/secret/site |
zones.json |
Calibrated pallet / truck / counting polygons + left/right limits (geometry only) |
cfg/tracker.yaml |
FastTrack/ByteTrack occlusion tuning (buffer 60, re-ID windows) |
See docs/configuration.md for every variable.
Dashboard (counter_dashboard.py, port 5000 / office 5721)
Pages in templates/: monitoring.html, operator.html (batch start/stop;
DO panel in do_manual), history.html, analytics.html. JSON APIs under
/api/* (live video MJPEG, current/previous batch, summary, daily data,
batch mode, DO upload/staged/settings, CSV/Excel export). Data source:
jetson_counter.db + current_batch.json + batch_mode.json
(batch flow: auto | do_manual | manual; model mode in config.yaml).
Batch modes
| Mode | Who opens/closes batch | DO gate |
|---|---|---|
auto (default) |
AI truck FSM | — |
do_manual |
Operator + DO photo scan | yes |
manual |
Operator buttons (legacy) | no |
Office (:5721) switches mode / model mode / require_plate / ocr_engine (403
on operator POST). DO manual flow: open http://<jetson>:5000/operator on a phone →
Ambil Foto DO → review/edit OCR fields → Mulai Batch → count → Selesai
(soft-warn if zone busy). Discard only when both sack and box nets are 0.
ERD: ERD.md.
Repository layout
src/ Shared library (streaming, detection, tracking, stabilizer,
truck_roi, counting, batch, dashboard, logger, config_loader, main)
config.yaml Canonical config (stream/models/counting/batch/output/camera)
cfg/tracker.yaml Tracker tuning
predict.py Single entrypoint: production service + dev CLI (see --help)
counter_dashboard.py Flask dashboard + APIs | templates/*.html pages
tests/ Pytest smoke tests (counting, batch, config, config_loader)
archive/ Retired experiments (predict_new.py, rpo_iki/, simple_predict.py,
check/merge/test scripts) — history preserved, not imported
export_model.py Export .pt → TensorRT .engine (FP16) | export_v4.py variant
deploy_to_jetson.py Paramiko sync + service restart
*.service systemd units (counter, dashboard, mediamtx)
zones.json Calibrated zone geometry
batch_history_folder/ Per-batch JSON reports
CHANGELOG.md Release history (dated entries, Keep-a-Changelog style)
Script-by-script reference: docs/scripts.md.
Docs
docs/architecture.md— pipeline stages, modules, batch FSMdocs/models.md— model inventory & detection-mode support matrixdocs/configuration.md— all config files/variablesdocs/deployment.md— Jetson services, TensorRT, deploy flowERD.md— SQLite ERD (Mermaid): batches / delivery_orders / daily_summariesdocs/operator-tiles-history-plan.md— operator tiles + history cleanup plandocs/scripts.md— entry points & utility scriptsCHANGELOG.md— release history