Flutter: aprendizaje automático en el dispositivo con el kit ML

El aprendizaje automático se está utilizando ampliamente en los proyectos de hoy. Requiere conocimiento de Machine Learning para crear modelos, para desarrolladores de aplicaciones que quieran usar Machine Learning en el proyecto pero no saben cómo crear un modelo. En Flutter, Google ha realizado ciertos desarrollos para ayudar a los desarrolladores a crear la aplicación que desean. Aunque hay un paquete google_ml_kit, sin embargo, solo está disponible para Android todavía. En este artículo, usaremos ML Kit.

Juego de aprendizaje automático:

Google ha creado ML Kit para que los desarrolladores creen fácilmente aplicaciones móviles que impliquen el aprendizaje automático. Se puede utilizar para reconocimiento de texto, detección de rostros y poses, escaneo de códigos de barras, etc. Vamos a crear una aplicación que detecte elementos en la imagen y los etiquete.

En primer lugar, veamos la aplicación que vamos a crear en este tutorial: 

Características:

  1. Captura la imagen
  2. Imagen de preprocesamiento
  3. Identifique elementos con etiqueta, índice y confianza.

Instala la dependencia:

Incluya el paquete google_ml_kit en el archivo pubspec.yaml de la aplicación para usar las funciones del kit ML de Google.

Dart

google_ml_kit: ^0.3.0

Para usar la función de cámara, primero debemos crear una pantalla que capture la imagen. Para incluir la función de cámara, necesitamos usar la biblioteca de cámaras de Flutter.

Dart

camera: ^0.8.1

Configure ambas bibliotecas ejecutando pub get.

Crear camera_screen.dart:

Importe la biblioteca de cámaras en camera_screen.dart e inicialice CameraController. También estamos encontrando la cantidad de cámaras disponibles y seleccionando la primera cámara de la opción para tomar fotografías.

Dart

late final CameraController _controller;
  
void _initializeCamera() async {
    final CameraController cameraController = CameraController(
      cameras[0],
      ResolutionPreset.high,
    );
    _controller = cameraController;
  
    _controller.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    });
  }

Llame al método dentro de initState(), para iniciar la cámara cuando se inicia la aplicación:

Dart

@override
void initState() {
  _initializeCamera();
  super.initState();
}

Antes de pasar a la siguiente pantalla, debemos deshacernos del controlador _ para evitar cualquier pérdida de memoria:

Dart

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}

Ahora, para tomar fotografías, estamos creando otra función _takePicture(), cuando se haga clic en el botón para capturar una imagen, se invocará esta función. Comprobará si CameraController está inicializado o no. Devolverá ImagePath donde se almacenará la imagen en el dispositivo después de la captura. Si ocurre algún error, lanzará una excepción. Tras capturar la imagen, nos redirigirá a otra pantalla, detail_screen.dart. Por lo tanto, cree otro archivo detail_screen.dart para mostrar los resultados.

Dart

Future<String?> _takePicture() async {
    if (!_controller.value.isInitialized) {
      print("Controller is not initialized");
      return null;
    }
  
    String? imagePath;
  
    if (_controller.value.isTakingPicture) {
      print("Processing is progress ...");
      return null;
    }
  
    try {
        
      // Turning off the camera flash
      _controller.setFlashMode(FlashMode.off);
        
      // Returns the image in cross-platform file abstraction
      final XFile file = await _controller.takePicture();
        
      // Retrieving the path
      imagePath = file.path;
    } on CameraException catch (e) {
      print("Camera Exception: $e");
      return null;
    }
  
    return imagePath;
  }

Código completo para camera_screen.dart

Dart

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mlkit_vision/main.dart';
  
import 'detail_screen.dart';
  
class CameraScreen extends StatefulWidget {
  @override
  _CameraScreenState createState() => _CameraScreenState();
}
  
class _CameraScreenState extends State<CameraScreen> {
  late final CameraController _controller;
  
  // Initializes camera controller to preview on screen
  void _initializeCamera() async {
    final CameraController cameraController = CameraController(
      cameras[0],
      ResolutionPreset.high,
    );
    _controller = cameraController;
  
    _controller.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    });
  }
  
  // Takes picture with the selected device camera, and
  // returns the image path
  Future<String?> _takePicture() async {
    if (!_controller.value.isInitialized) {
      print("Controller is not initialized");
      return null;
    }
  
    String? imagePath;
  
    if (_controller.value.isTakingPicture) {
      print("Processing is progress ...");
      return null;
    }
  
    try {
        
      // Turning off the camera flash
      _controller.setFlashMode(FlashMode.off);
        
      // Returns the image in cross-platform file abstraction
      final XFile file = await _controller.takePicture();
        
      // Retrieving the path
      imagePath = file.path;
    } on CameraException catch (e) {
      print("Camera Exception: $e");
      return null;
    }
  
    return imagePath;
  }
  
  @override
  void initState() {
    _initializeCamera();
    super.initState();
  }
  
  @override
  void dispose() {
      
    // dispose the camera controller when navigated
    // to a different page
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GeeksForGeeks'),
      ),
      body: _controller.value.isInitialized
          ? Stack(
              children: <Widget>[
                CameraPreview(_controller),
                Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: Container(
                    alignment: Alignment.bottomCenter,
                    child: ElevatedButton.icon(
                      icon: Icon(Icons.camera),
                      label: Text("Click"),
                      onPressed: () async {
                          
                        // If the returned path is not null navigate
                        // to the DetailScreen
                        await _takePicture().then((String? path) {
                          if (path != null) {
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                builder: (context) => DetailScreen(
                                  imagePath: path,
                                ),
                              ),
                            );
                          } else {
                            print('Image path not found!');
                          }
                        });
                      },
                    ),
                  ),
                )
              ],
            )
          : Container(
              color: Colors.black,
              child: Center(
                child: CircularProgressIndicator(),
              ),
            ),
    );
  }
}

Trabaja en detail_screen.dart:

Primero, necesitamos procesar la imagen, obtener imageSize para que se muestre en la pantalla.

Dart

Future<void> _getImageSize(File imageFile) async {
    final Completer<Size> completer = Completer<Size>();
  
    final Image image = Image.file(imageFile);
    image.image.resolve(const ImageConfiguration()).addListener(
      ImageStreamListener((ImageInfo info, bool _) {
        completer.complete(Size(
          info.image.width.toDouble(),
          info.image.height.toDouble(),
        ));
      }),
    );
  
    final Size imageSize = await completer.future;
    setState(() {
      _imageSize = imageSize;
    });
  }

Inicialice imageLabeler de GoogleMLKit en la clase.

Dart

final imageLabeler = GoogleMlKit.vision.imageLabeler();

Ahora, crearemos otra función _recognizeImage(), primero, obtendremos el tamaño de la imagen y luego el archivo de la imagen. Guardaremos todas las etiquetas de imagen en etiquetas de lista de tipo List<ImageLabel>. Luego, a través del ciclo for, recuperaremos la etiqueta, el índice y la confianza para cada etiqueta de imagen y los almacenaremos en sus respectivas listas: imagesData , indexData y trustData .

Dart

void _recognizeImage() async {
    _getImageSize(File(_imagePath));
    final inputImage = InputImage.fromFilePath(_imagePath);
    final List<ImageLabel> labels = await imageLabeler.processImage(inputImage);
  
    for (ImageLabel label in labels) {
        
      // retrieve label,index, and confidence from each label
      final String item = label.label;
      final int index = label.index;
      final double confidence = label.confidence;
      imagesData.add(item);
      indexData.add(index.toString());
      confidenceData.add(confidence.toString());
    }
  }

Ahora, es el momento de mostrar los resultados en la pantalla.

Código completo para detail_screen.dart:

Dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:google_ml_kit/google_ml_kit.dart';
  
class DetailScreen extends StatefulWidget {
  final String imagePath;
  
  const DetailScreen({required this.imagePath});
  
  @override
  _DetailScreenState createState() => _DetailScreenState();
}
  
class _DetailScreenState extends State<DetailScreen> {
  late final String _imagePath;
  final imageLabeler = GoogleMlKit.vision.imageLabeler();
  Size? _imageSize;
  List<String> imagesData = [];
  List<String> indexData = [];
  List<String> confidenceData = [];
  
  // Fetching the image size from the image file
  Future<void> _getImageSize(File imageFile) async {
    final Completer<Size> completer = Completer<Size>();
  
    final Image image = Image.file(imageFile);
    image.image.resolve(const ImageConfiguration()).addListener(
      ImageStreamListener((ImageInfo info, bool _) {
        completer.complete(Size(
          info.image.width.toDouble(),
          info.image.height.toDouble(),
        ));
      }),
    );
  
    final Size imageSize = await completer.future;
    setState(() {
      _imageSize = imageSize;
    });
  }
  
  void _recognizeImage() async {
    _getImageSize(File(_imagePath));
    final inputImage = InputImage.fromFilePath(_imagePath);
    final List<ImageLabel> labels = await imageLabeler.processImage(inputImage);
  
    for (ImageLabel label in labels) {
      final String item = label.label;
      final int index = label.index;
      final double confidence = label.confidence;
      imagesData.add(item);
      indexData.add(index.toString());
      confidenceData.add(confidence.toString());
    }
  }
  
  @override
  void initState() {
    _imagePath = widget.imagePath;
      
    // Initializing the Image Labeler
    final imageLabeler = GoogleMlKit.vision.imageLabeler();
    _recognizeImage();
    super.initState();
  }
  
  @override
  void dispose() {
      
    // Disposing the imageLabeler when not used anymore
    imageLabeler.close();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Image Details"),
      ),
      body: _imageSize != null
          ? Stack(
              children: [
                Container(
                  width: double.maxFinite,
                  color: Colors.black,
                  child: AspectRatio(
                    aspectRatio: _imageSize!.aspectRatio,
                    child: Image.file(
                      File(_imagePath),
                    ),
                  ),
                ),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: Card(
                    elevation: 8,
                    color: Colors.white,
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Padding(
                            padding: const EdgeInsets.only(bottom: 8.0),
                            child: Text(
                              "IdentifiedItems  Index   Confidence",
                              style: TextStyle(
                                fontSize: 20,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                          Container(
                            height: 120,
                            child: SingleChildScrollView(
                              child: imagesData != null
                                  ? ListView.builder(
                                      shrinkWrap: true,
                                      physics: BouncingScrollPhysics(),
                                      itemCount: imagesData.length,
                                      itemBuilder: (context, index) {
                                        return Row(
                                          mainAxisAlignment:
                                              MainAxisAlignment.spaceBetween,
                                          children: [
                                            Text(imagesData[index]),
                                            Text(indexData[index]),
                                            Text(confidenceData[index])
                                          ],
                                        );
                                      })
                                  : Container(),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            )
          : Container(
              color: Colors.blue,
              child: Center(
                child: CircularProgressIndicator(),
              ),
            ),
    );
  }
}

Ahora, llama a CameraScreen en main.dart.

Dart

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
  
import 'camera_screen.dart';
  
// Global variable for storing the list of cameras available
List<CameraDescription> cameras = [];
  
Future<void> main() async {
    
  // Fetch the available cameras before initializing the app.
  try {
    WidgetsFlutterBinding.ensureInitialized();
    cameras = await availableCameras();
  } on CameraException catch (e) {
    debugPrint('CameraError: ${e.description}');
  }
  runApp(MyApp());
}
  
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter MLKit Vision',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: CameraScreen(),
    );
  }
}

Producción:

Publicación traducida automáticamente

Artículo escrito por rn540 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *