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:
- Captura la imagen
- Imagen de preprocesamiento
- 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: