# Feedmill Recounter AI video analysis tool for counting objects (sacks, boxes) in feedmill videos. Built on top of [karung_counter_semarang](https://git.proit.id/andrew/karung-counting-feedmill-semarang). ## Features - **CLI**: Process videos from the command line with any model + class filter - **Web UI**: Upload videos, select models, download annotated output on port 9000 - **Live Preview**: MJPEG streaming — watch processing in real-time (15+ FPS at 640p) - **Multiple Models**: Run multiple model configurations on the same video for comparison - **Model Groups**: Models grouped by stem (e.g., `best.pt`, `best.engine`) with format dropdown - **Class Filtering**: Choose which classes to count (sack, box, truck) - **Auto Truck Detection**: Automatically loads `truck-detector` when selected model lacks truck class - **Video Reuse**: Re-analyze previously uploaded videos without re-uploading - **Annotated Output**: Download MP4 videos with detection overlays for human review - **Async Processing**: Background job queue — upload and poll status - **Abort**: Cancel running jobs mid-processing ## Quick Start ```bash pip install -e ".[dev]" # List available models recounter --list-models --models-dir ./models # Process a single video via CLI recounter --video input.mp4 --model v4-best.pt --filter sack --output-dir ./output # Start web UI recounter-web # Open http://localhost:9000 ``` ## CLI Reference ``` recounter --video PATH Input video file --model NAME Model filename (repeatable for multiple) --all-models Run all discovered models --list-models List available models and exit --filter NAME Class filter (repeatable): sack, box, truck --sack-conf FLOAT Sack confidence threshold (default: 0.4) --truck-conf FLOAT Truck confidence threshold (default: 0.5) --output PATH Output path (single model only) --output-dir DIR Output directory (default: ./output) --models-dir DIR Models directory (default: ./models) ``` ## Web UI - **Port**: 9000 (configurable via `WEB_PORT` env) - **Upload**: Drag-and-drop or click to upload video, or select from previously uploaded videos - **Model Selection**: Grouped cards with format dropdown (`.engine` / `.pt` / `.onnx`) and class filter - **Live Preview**: Real-time MJPEG stream during processing - **Job Status**: Auto-refreshing progress page with abort button - **Download**: Annotated MP4 per model result ## API Endpoints | Endpoint | Method | Description | |---|---|---| | `/` | GET | Upload form with model groups | | `/upload` | POST | Start processing job | | `/upload/reuse` | POST | Re-analyze an existing uploaded video | | `/status/` | GET | Job status with results | | `/jobs` | GET | All jobs listing | | `/download//` | GET | Download output video | | `/preview/thumb/` | GET | Thumbnail JPEG for a job's video | | `/api/preview/` | GET | MJPEG live stream during processing | | `/api/models` | GET | List model groups (JSON) | | `/api/videos` | GET | List uploaded videos (JSON) | | `/api/videos/` | DELETE | Delete an uploaded video | | `/api/jobs` | GET | List all jobs (JSON) | | `/api/jobs/` | GET | Job detail (JSON) | | `/api/jobs//cancel` | POST | Cancel a running job | | `/api/jobs//samples` | GET | Sample frame paths (JSON) | ## Configuration | Variable | Default | Description | |----------|---------|-------------| | `WEB_HOST` | `0.0.0.0` | Flask bind address | | `WEB_PORT` | `9000` | Flask port | | `FLASK_DEBUG` | `false` | Flask debug mode | | `MODELS_DIR` | `./models` | Model weights directory | | `UPLOAD_DIR` | `./uploads` | Uploaded videos directory | | `OUTPUT_DIR` | `./output` | Annotated output directory | ## Project Structure ``` src/ ├── interfaces.py # Detection dataclass + protocols ├── detection.py # YOLO detectors with class filtering ├── tracking.py # ByteTrack/FastTrack tracker ├── stabilizer.py # Bbox smoothing + occlusion hold ├── truck_roi.py # Truck ROI detection + EMA smoothing ├── counting.py # Line-crossing counter ├── batch.py # Batch lifecycle state machine ├── dashboard.py # Frame annotation overlay ├── video_writer.py # Annotated video writer ├── model_registry.py # Model discovery, grouping, class metadata ├── pipeline.py # Video processing pipeline ├── preview.py # Video probing, thumbnails, sample frames └── job.py # Async job queue ``` ## Model Formats Models are grouped by stem name. Each group has available formats: | Format | Extension | Speed | Notes | |--------|-----------|-------|-------| | TensorRT | `.engine` | Fastest | Preferred on Jetson (GPU-optimized) | | PyTorch | `.pt` | Medium | Works everywhere | | ONNX | `.onnx` | Medium | Requires `onnxruntime` (not available on Jetson) | Format preference order: `.engine` > `.pt` > `.onnx` ## Truck Detection The pipeline requires truck detection to start counting. If the selected model lacks a "truck" class (e.g., `best.engine` which only has "sack"), the system automatically loads the `truck-detector` model for truck detection. Models with "truck" class: `v4-best`, `model_karung_truk` Models without "truck" class: `best`, `karung-dimuat`, `yolo11n-bbox` (auto-loads truck-detector)