Overview
Smart Leaf helps gardeners, smallholders, and extension workers identify crop leaf diseases from a photo — without internet. Users scan with the in-app camera (pinch-to-zoom via a custom native module) or pick from the gallery; a quantized Float16 TFLite model returns a disease label and confidence in seconds. A built-in library explains symptoms, treatment, and prevention, with content tailored for Ugandan smallholder contexts.
The problem
Field diagnosis is slow and error-prone when connectivity is poor and expert help is scarce. Many “plant ID” apps depend on cloud APIs, upload user photos, and fail offline. Generic image classifiers also tend to force a label on non-leaf images instead of saying “I don’t know.”
The solution
An end-to-end offline-first pipeline:
Camera / Gallery → 224×224 RGB preprocess → smartleaf_fp16.tflite (EfficientNetB0)→ temperature calibration → confidence + entropy gate → verdict or “Not a leaf”
- 38 disease/healthy classes across Apple, Blueberry, Cherry, Corn, Grape, Orange, Peach, Pepper, Potato, Raspberry, Soybean, Squash, Strawberry, Tomato
- 39th class:
Not_A_Leaf plus rejection logic so random photos are not misclassified - Disease library with Markdown-rendered guides (symptoms, management, Uganda-specific notes)
- Local scan history via Zustand + SQLite/AsyncStorage — nothing leaves the device
My role
- Trained and exported the EfficientNetB0 model on Kaggle (PlantVillage + negative datasets)
- Ported notebook inference (preprocess, temperature scaling, decision gate) to TypeScript for parity with training
- Built the Expo/React Native app: camera flow, results UI, library, history, settings
- Shipped to Google Play with EAS Build; authored privacy/support docs site
Tech stack
- Layer
- Tools
- Mobile
- Expo SDK 56, React Native 0.85, TypeScript, expo-router
- ML
- TensorFlow Lite (Float16), react-native-fast-tflite, EfficientNetB0
- Capture
- expo-camera, expo-image-picker, custom
camera-zoom native module - State & storage
- Zustand, expo-sqlite, AsyncStorage
- Build & release
- EAS, Google Play (
com.yasinwalum.smartleaf)
Technical highlights
- Training ↔ app parity — Same preprocessing, temperature calibration, and confidence/entropy thresholds in the Kaggle notebook and
src/ml/inference.ts, driven by assets/models/infer_config.json. - Out-of-distribution handling — Negatives from Intel Image Classification and Caltech-256 train a reject class; runtime gates catch low-confidence or high-entropy predictions.
- Native where it matters — Custom Expo module for camera zoom; Nitro Modules for fast TFLite inference.
- Privacy by design — No network calls for diagnosis; camera and photos permissions only for capture/selection.
Results / impact
- Published on Google Play
- >95% validation accuracy target during training
- ~8 MB on-device model (
smartleaf_fp16.tflite) - Fully offline inference suitable for rural/low-connectivity use
Challenges & learnings
- Expo Go is not enough — TFLite and custom native modules require a dev client / EAS build.
- Mobile ML is more than export — Calibration and rejection logic matter as much as raw accuracy.
- Product content is part of the ML app — Structured disease guides turn a classifier into something people can act on in the field.
Links
- Try it: Google Play
- Source: github.com/wyasyn/smart-leaf
- Training notebook:
assets/models/train_smartleaf.ipynb