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.