A minimal local Python proof of concept for detecting coin-like objects from a laptop webcam or video file.
The app can run in two modes:
yolo: uses a coin-trained Ultralytics YOLO model, expected atmodels/best.pt.circle: uses OpenCV Hough circle detection so the webcam pipeline can be tested without a trained model.
- Opens a webcam or MP4/video file.
- Detects coins or coin-like circles in each frame.
- Draws bounding boxes, labels, and confidence scores where available.
- Shows live video in an OpenCV window.
- Optionally saves an annotated MP4 output video.
- Press
qto quit cleanly. - Press
sto save a screenshot and matching detection metadata JSON. - Emits a
coin_out_of_frameevent when a previously visible coin disappears.
Use Python 3.10 or 3.11.
cd coin-webcam-detector
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtOn Windows PowerShell:
cd coin-webcam-detector
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txtYOLO mode with a coin-trained model:
python main.py --webcam --mode yolo --model models/best.ptCircle fallback mode:
python main.py --webcam --mode circleDifferent webcam index:
python main.py --webcam --mode circle --camera 1Print JSON detections:
python main.py --webcam --mode yolo --print-jsonRun with the local event API enabled:
python main.py --webcam --mode circle --event-serverProcess an MP4/video file:
python main.py --video path/to/input.mp4 --mode yolo --model models/best.ptFilter out giant false-positive boxes and use thinner rectangles:
python main.py \
--video path/to/input.mp4 \
--mode yolo \
--model models/best.pt \
--conf 0.30 \
--max-box-area 0.20 \
--box-thickness 1Process a video and save an annotated MP4:
python main.py \
--video path/to/input.mp4 \
--mode yolo \
--model models/best.pt \
--save-video outputs/annotated_input.mp4Process and save without opening a preview window:
python main.py \
--video path/to/input.mp4 \
--mode yolo \
--model models/best.pt \
--save-video outputs/annotated_input.mp4 \
--no-displayVideo fallback mode without a trained model:
python main.py --video path/to/input.mp4 --mode circle --save-video outputs/circle_output.mp4When a coin is detected and then disappears for several consecutive frames, the app emits:
{
"type": "coin_out_of_frame"
}Events are always appended to:
outputs/events.jsonl
You can watch them in another terminal:
tail -f outputs/events.jsonlIf you start the app with --event-server, query recent events over HTTP:
curl "http://127.0.0.1:8765/events?type=coin_out_of_frame"Poll only events after a known event ID:
curl "http://127.0.0.1:8765/events?type=coin_out_of_frame&since_id=3"Tune how long the detector waits before emitting the event:
python main.py --webcam --mode circle --absence-frames 8 --event-serverThe same event system works for video files:
python main.py --video path/to/input.mp4 --mode yolo --model models/best.pt --event-serverPressing s saves both files:
outputs/frame_YYYYMMDD_HHMMSS.jpg
outputs/frame_YYYYMMDD_HHMMSS.json
The JSON file includes the timestamp, image path, and detections for that frame.
- YOLO mode needs a coin-trained model. Put it at
models/best.ptor pass--model path/to/model.pt. - Default YOLO weights usually do not include coin classes, so they may not detect coins reliably.
- Circle mode does not require training, but it detects circular objects, not coins specifically.
- The
modelsdirectory is included, butmodels/best.ptis not bundled because trained model weights are project-specific.
- Improve the dataset with varied coin angles, backgrounds, lighting, and distances.
- Train or fine-tune a custom YOLO coin detector.
- Add simple object tracking IDs if you need per-coin enter/exit events.
- Export a trained model to ONNX for later Rust usage.
from ultralytics import YOLO
model = YOLO("models/best.pt")
model.export(format="onnx")