Perché il machine learning on-device
Integrare funzionalità di intelligenza artificiale nelle app mobile non richiede necessariamente chiamate a servizi cloud costosi o dipendenti dalla connessione. Google ML Kit offre modelli pre-addestrati che girano direttamente sul dispositivo, garantendo bassa latenza, privacy dei dati e funzionamento offline.
In Flutter possiamo sfruttare questi modelli grazie ai pacchetti della famiglia google_mlkit_*, che espongono API native in Dart per riconoscimento del testo (OCR), scansione di barcode, rilevamento e tracciamento dei volti, etichettatura di immagini e molto altro.
In questo articolo vediamo come integrare tre casi d'uso concreti: OCR, scansione barcode e rilevamento volti.
Configurazione del progetto
A differenza del vecchio pacchetto monolitico google_ml_kit, oggi è consigliato installare solo i moduli che servono, per ridurre la dimensione dell'app. Aggiungiamo le dipendenze necessarie:
dependencies:
google_mlkit_text_recognition: ^0.13.0
google_mlkit_barcode_scanning: ^0.12.0
google_mlkit_face_detection: ^0.11.0
image_picker: ^1.1.2
Configurazione iOS
Su iOS il minimo supportato è iOS 15.5. Nel file ios/Podfile assicurati di impostare la piattaforma:
platform :ios, '15.5'
Aggiungi inoltre in Info.plist i permessi per fotocamera e libreria foto:
<key>NSCameraUsageDescription</key>
<string>Serve per acquisire immagini da analizzare</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Serve per selezionare immagini da analizzare</string>
Configurazione Android
Su Android il minSdkVersion deve essere almeno 21. Se vuoi che i modelli vengano scaricati automaticamente dal Play Store, aggiungi nel AndroidManifest.xml:
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ocr,barcode,face" />
Riconoscimento del testo (OCR)
Il riconoscimento del testo estrae stringhe da un'immagine. Partiamo da un InputImage, che può derivare da un file, da un percorso o da un frame della fotocamera.
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
Future<String> riconosciTesto(String imagePath) async {
final inputImage = InputImage.fromFilePath(imagePath);
final recognizer = TextRecognizer(script: TextRecognitionScript.latin);
try {
final RecognizedText result = await recognizer.processImage(inputImage);
final buffer = StringBuffer();
for (final block in result.blocks) {
for (final line in block.lines) {
buffer.writeln(line.text);
}
}
return buffer.toString();
} finally {
await recognizer.close();
}
}
La gerarchia dei risultati è blocchi → righe → elementi, e ogni livello espone un boundingBox con le coordinate, utile se vuoi disegnare riquadri sopra l'immagine originale. Ricorda sempre di chiamare close() per liberare le risorse native.
Scansione di barcode e QR code
Il modulo barcode riconosce numerosi formati (QR, EAN, Code 128, ecc.) e restituisce sia il valore grezzo sia dati strutturati.
import 'package:google_mlkit_barcode_scanning/google_mlkit_barcode_scanning.dart';
Future<List<String>> scansionaBarcode(String imagePath) async {
final inputImage = InputImage.fromFilePath(imagePath);
final scanner = BarcodeScanner(formats: [BarcodeFormat.all]);
try {
final List<Barcode> barcodes = await scanner.processImage(inputImage);
return barcodes.map((b) {
// Dati tipizzati in base al tipo di contenuto
if (b.type == BarcodeType.url) {
final url = b.value as BarcodeUrl;
return 'URL: ${url.url}';
}
return b.displayValue ?? 'Sconosciuto';
}).toList();
} finally {
await scanner.close();
}
}
Oltre agli URL, ML Kit riconosce contatti (vCard), eventi calendario, coordinate geografiche, credenziali Wi-Fi e altro, esponendo tipi dedicati come BarcodeWifi o BarcodeContactInfo.
Rilevamento dei volti
Il rilevamento dei volti individua i visi in un'immagine e, con le opzioni adeguate, può classificare espressioni (probabilità di sorriso), stimare l'apertura degli occhi e tracciare i contorni.
import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart';
Future<void> rilevaVolti(String imagePath) async {
final options = FaceDetectorOptions(
enableClassification: true, // sorriso, occhi aperti
enableLandmarks: true, // occhi, naso, bocca
performanceMode: FaceDetectorMode.accurate,
);
final detector = FaceDetector(options: options);
try {
final faces = await detector.processImage(
InputImage.fromFilePath(imagePath),
);
for (final face in faces) {
final rect = face.boundingBox;
final smile = face.smilingProbability;
print('Volto in $rect, sorriso: ${smile?.toStringAsFixed(2)}');
}
} finally {
await detector.close();
}
}
Per applicazioni come filtri realtà aumentata puoi abilitare anche enableTracking, così ogni volto mantiene un trackingId stabile tra un frame e l'altro.
Elaborazione in tempo reale dalla fotocamera
Per analizzare lo stream della fotocamera, invece di partire da un file, costruisci l'InputImage a partire dai byte del frame usando InputImage.fromBytes, specificando InputImageMetadata con dimensioni, rotazione e formato. È fondamentale evitare di processare ogni frame: usa un flag booleano per saltare i frame mentre uno è ancora in elaborazione.
bool _isBusy = false;
Future<void> _processCameraImage(CameraImage image) async {
if (_isBusy) return;
_isBusy = true;
try {
// costruisci InputImage.fromBytes e passalo al detector...
} finally {
_isBusy = false;
}
}
Best practice
- Chiudi sempre i detector con
close(): sono risorse native e non rilasciarle causa memory leak. - Riutilizza l'istanza del detector invece di crearne una nuova a ogni analisi.
- Per lo streaming, esegui il throttling dei frame per non saturare la CPU.
- Su Android considera la modalità con download dei modelli da Play Store per ridurre la dimensione dell'APK iniziale.
- Gestisci i casi in cui il modello non è ancora scaricato, mostrando un feedback all'utente.
Conclusioni
Google ML Kit porta il machine learning on-device in Flutter con un'API pulita e tipizzata, senza costi di backend né dipendenza dalla rete. Che tu debba costruire uno scanner di documenti, un lettore di QR code o un'esperienza AR basata sul volto, i moduli google_mlkit_* offrono un punto di partenza solido e performante. Il consiglio è di installare solo i moduli necessari e di gestire con cura il ciclo di vita dei detector.