Submission kelas Belajar Penerapan Machine Learning untuk Flutter (Dicoding).
Aplikasi mengenali jenis makanan dari sebuah gambar memakai model AIY Vision Classifier Food V1, lalu melengkapinya dengan informasi gizi dan resep referensi.
Aplikasi langsung bisa dijalankan tanpa konfigurasi (
flutter pub getlaluflutter run). Model sudah dibundel diassets/. Lihat SETUP.md untuk menambahkan Gemini API key yang bersifat opsional.
Home Page ──► pilih gambar (kamera / galeri)
│ │
│ └──► Cropper (opsional)
│
├──► Result Page ──► foto + nama makanan + confidence score
│ │ + Nutrition Facts (Gemini API)
│ │ + Reference (TheMealDB API)
│ │
│ └──► Detail Page ──► foto, bahan, langkah pembuatan
│
└──► Camera Page ──► deteksi real-time dari camera stream
| Ketentuan | Implementasi |
|---|---|
image_picker dari kamera & galeri |
lib/service/image_picker_service.dart |
| Gambar tampil di halaman | lib/ui/home_page.dart |
image_cropper untuk memotong gambar |
ImagePickerService.cropImage, tombol Crop & Analyze |
camera untuk camera stream |
lib/widget/camera_view.dart, lib/ui/camera_page.dart |
| Ketentuan | Implementasi |
|---|---|
| Model food classifier resmi | AIY Vision Classifier Food V1, 2024 kelas, di assets/aiy_food_V1.tflite |
LiteRT (flutter_litert) |
lib/service/image_classification_service.dart |
| Inferensi di Isolate | lib/service/isolate_inference.dart |
Interpreter dibuat sekali di main thread, lalu alamat memorinya
(interpreter.address) dikirim ke isolate. Dengan begitu preprocessing gambar
dan interpreter.run() berjalan di background thread sehingga UI tidak freeze.
| Ketentuan | Implementasi |
|---|---|
| Foto yang diambil pengguna | _UserImage di lib/ui/result_page.dart |
| Nama makanan hasil inferensi | ClassificationItem |
| Confidence score (persentase) | Classification.percentage |
| TheMealDB: nama, foto, bahan, instruksi | lib/service/meal_db_service.dart, lib/ui/detail_page.dart |
| Gemini API: kalori, karbo, lemak, serat, protein | lib/service/gemini_service.dart |
API key lewat --dart-define |
String.fromEnvironment di lib/env/env.dart |
lib/
├── controller/ ChangeNotifier untuk tiap layar
├── env/ pembacaan Gemini API key
├── model/ Classification, Meal, Nutrition, UiState
├── service/ LiteRT, Isolate, image picker, MealDB, Gemini
├── ui/ Home, Result, Detail, Camera
├── utils/ konversi CameraImage ke Image
└── widget/ komponen yang dipakai ulang
- Bentuk tensor dibaca dari model, bukan di-hardcode, sehingga tetap benar meskipun berkas modelnya suatu saat diganti.
- Output uint8 dinormalisasi dengan membaginya terhadap total skor, sehingga confidence score selalu berjumlah 100%.
- Kelas
__background__(indeks 0) tidak ditampilkan karena bukan nama makanan. - Orientasi EXIF foto kamera diluruskan dengan
bakeOrientationsebelum masuk ke model, agar foto potret tidak terbaca miring. - Frame kamera baru dilewati selama frame sebelumnya masih diproses, supaya antrean inferensi tidak menumpuk.