Pothole detection and road repair optimization system for the city of Cotonou.
- Citizen reporting (
/) — upload a road photo, run YOLOv8 pothole detection, click the map for GPS, save a report - Mayor dashboard (
/dashboard) — reports ranked by danger score, zone heatmap, optimized repair route - Danger score per report and zone:
number of potholes × average bounding-box area (px²) - Repair route — greedy priority algorithm (high danger ÷ distance to next stop)
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, React Router, Leaflet |
| Backend | Python 3, FastAPI, Uvicorn |
| AI | Ultralytics YOLOv8 + Hugging Face Hub |
| Model | keremberke/yolov8n-pothole-segmentation |
| Database | SQLite (backend/roadai.db) |
RoadAI/
├── backend/
│ ├── main.py # FastAPI app, HF model load, /api/detect
│ ├── detection.py # Box parsing, red annotations, danger score
│ ├── database.py # SQLite reports
│ ├── optimization.py # Greedy repair route
│ ├── zones.py # Cotonou 5×5 zone grid
│ ├── uploads/ # Original images (gitignored)
│ ├── annotated/ # Annotated images (gitignored)
│ └── models/ # Optional local weights (see models/README.md)
├── frontend/
│ └── src/
│ ├── pages/ # ReportPage, DashboardPage
│ ├── components/ # CotonouMap, Layout
│ └── api.ts # API client (port 8001)
├── start-backend.ps1
├── start-frontend.ps1
└── README.md
At startup, main.py downloads and loads the pothole model from Hugging Face:
from huggingface_hub import hf_hub_download
from ultralytics import YOLO
model_path = hf_hub_download(
repo_id="keremberke/yolov8n-pothole-segmentation",
filename="best.pt",
)
model = YOLO(model_path)Weights are cached by huggingface_hub after the first download. Internet access is required on first backend start.
Configured in main.py:
| Parameter | Value | Description |
|---|---|---|
conf |
0.25 |
Confidence threshold |
iou |
0.3 |
NMS IoU threshold |
Flow:
- Image saved under
backend/uploads/ model.predict(...)runs inmain.pyprint(results[0].boxes)logs detections to the server console (debug)detection.pybuilds the JSON response and draws red bounding boxes tobackend/annotated/
- Python 3.10+ (3.13 supported)
- Node.js 18+ and npm
- Network access for Hugging Face model download (first run)
See backend/requirements.txt: FastAPI, Ultralytics, OpenCV, huggingface_hub, aiosqlite, etc.
cd backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn main:app --reload --host 127.0.0.1 --port 8001From project root:
.\start-backend.ps1API docs: http://127.0.0.1:8001/docs
cd frontend
npm install
npm run devFrom project root:
.\start-frontend.ps1The frontend uses http://127.0.0.1:8001 (frontend/src/api.ts). Vite proxies /api to the same port during development (frontend/vite.config.ts).
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health |
Health check |
| GET | /api/bounds |
Cotonou map bounds |
| GET | /api/zones/grid |
Zone cell definitions |
| POST | /api/detect |
Detect potholes in an image |
| POST | /api/reports |
Save a report (JSON body) |
| POST | /api/reports/submit |
Detect + save (multipart) |
| GET | /api/reports |
List reports (sorted by danger) |
| GET | /api/zones |
Per-zone danger aggregates |
| GET | /api/route |
Greedy repair itinerary |
| GET | /api/files/annotated/{filename} |
Annotated image file |
| GET | /api/files/uploads/{filename} |
Original upload file |
- UI language: French
- Colors: red
#c41e3aand white - Map: OpenStreetMap tiles centered on Cotonou
| Issue | What to try |
|---|---|
| Model download fails | Check internet; retry backend start; verify Hugging Face is reachable |
| Frontend cannot reach API | Ensure backend runs on 8001; check frontend/src/api.ts and Vite proxy |
| No detections | Lower conf in main.py; use a clear road/pothole photo |
| Empty dashboard | Submit at least one report from the Signaler page |
MIT — See LICENSE
Hackathon project — educational and demonstration use.