
Android app (internship) using computer vision and generative AI to flag road condition, with on-device storage. Rebuilt as a public demo: FastAPI + scikit-learn classifier on accelerometer features, map view, history and reports.
- My role
- Android intern (original app); sole engineer (public rebuild)
- Links
- GitHub ↗
- Stack
- AndroidAndroid StudioPythonFastAPIscikit-learn
- Android · Kotlin/Java · Room · GenAI · FastAPI · scikit-learn · SQLite
- Microsoft-ecosystem fit
▸ Model portable to ONNX Runtime (planned)
5/5
API tests passing
0.956
Macro-F1 — synthetic sample, not real roads
[REPLACE]
Real-world accuracy / test drives

Source · Generated by the real API: reports logged via POST /reports (synthetic sensor features), its live /docs, and the classifier's hold-out confusion matrix. [REPLACE] add emulator screenshots of the app
01 — Problem
Road damage reporting was manual and slow, although smartphones already capture the sensor data needed to detect it.
02 — Approach
- 01
2-second accelerometer/gyro windows → features (vertical RMS, peak, variance, speed).
- 02
Random-forest classifier: good / fair / poor, with confidence.
- 03
Reports stored locally first, synced later; map + history + summary report screens.
03 — Architecture
System architecture
S01
Phone sensors
S02
Feature window
S03
Classifier
S04
SQLite / Room
S05
Map · History · Report
04 — Engineering notes
From a vibration window to a label
The public rebuild classifies a 2-second sensor window. The features are cheap enough to compute on the phone, so the app can label roads offline and sync later.
# services/road-health-api/app/model.py
FEATURES = ["z_rms", "z_peak", "z_std", "gyro_var", "speed_kmh"]
LABELS = ["good", "fair", "poor"]
def predict(features: dict) -> tuple[str, float]:
x = np.array([[features[f] for f in FEATURES]])
proba = load().predict_proba(x)[0]
i = int(proba.argmax())
return LABELS[i], float(proba[i])Honest numbers
The classifier scores 0.956 macro-F1 on a held-out split of a synthetic dataset, generated with physically plausible vibration ranges. That proves the pipeline, not real-world accuracy; real labelled drives replace make_dataset().


Outcome
A field tool that records and classifies road condition offline and syncs when connectivity returns.
Next project
Document Q&A (RAG)
