Flutter google_ml_kit_flutter: Обнаружение лиц для сценариев класса не работает

Вопрос или проблема

Я сталкиваюсь с проблемой в функции распознавания лиц в моем проекте. Когда я пытаюсь распознать лица на изображении, содержащем несколько человек (например, этом: https://drive.google.com/file/d/17IerjcqeFMVlNLn0qBdrBDSAyZBOvsd7/view?usp=sharing), плагин не может идентифицировать ни одно лицо, хотя они явно видны.

Код для воспроизведения.

   import 'package:flutter/material.dart';
   import 'dart:io';
   import 'dart:ui' as ui;
   
   import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart';
   import 'package:image_picker/image_picker.dart';
   
   void main() {
     runApp(
       const MaterialApp(
         debugShowCheckedModeBanner: false,
         home: HomePage(), //TakePicture(),
       ),
     );
   }
   
   class HomePage extends StatefulWidget {
     const HomePage({super.key});
   
     @override
     State<HomePage> createState() => _HomePageState();
   }
   
   class _HomePageState extends State<HomePage> {
     late final ImagePicker _imagePicker;
     late final FaceDetector _faceDetector;
     late final ValueNotifier<ui.Image?> _image;
     late final ValueNotifier<File?> _imageFile;
     late final ValueNotifier<List<Face>?> _detectedFaces;
   
     @override
     void initState() {
       super.initState();
       _imagePicker = ImagePicker();
       _image = ValueNotifier(null);
       _imageFile = ValueNotifier(null);
       _detectedFaces = ValueNotifier(null);
       _faceDetector = FaceDetector(
         options: FaceDetectorOptions(
           enableContours: true,
           enableLandmarks: true,
         ),
       );
     }

     @override
     Widget build(BuildContext context) {
       return Scaffold(
         appBar: AppBar(),
         body: Column(
           mainAxisAlignment: MainAxisAlignment.center,
           crossAxisAlignment: CrossAxisAlignment.center,
           children: [
             Expanded(
               child: Padding(
                 padding: const EdgeInsets.fromLTRB(12, 0, 12, 12),
                 child: AnimatedBuilder(
                   animation: Listenable.merge([
                     _image,
                     _detectedFaces,
                     _imageFile,
                   ]),
                   builder: (context, _) {
                     if (_image.value == null ||
                         _detectedFaces.value == null ||
                         _imageFile.value == null) {
                       return Container(
                           height: 400,
                           // width: 300,
                           decoration: BoxDecoration(
                             border: Border.all(
                               color: Colors.lightBlueAccent.withOpacity(0.6),
                             ),
                             borderRadius: BorderRadius.circular(15),
                           ),
                           child: const Center(child: Text("Лицо не найдено")));
                     }
                     return FittedBox(
                       child: SizedBox(
                         width: _image.value?.width.toDouble() ?? 300,
                         height: _image.value?.height.toDouble() ?? 400,
                         child: CustomPaint(
                           painter: FacePainter(
                             _image.value!,
                             _detectedFaces.value!,
                           ),
                         ),
                       ),
                     );
                   },
                 ),
               ),
             ),
             Padding(
               padding: const EdgeInsets.all(18.0),
               child: Row(
                 mainAxisAlignment: MainAxisAlignment.spaceAround,
                 children: [
                   IconButton(
                       onPressed: onCameraPress,
                       icon: const Icon(Icons.camera_alt,
                           size: 35, color: Colors.blue)),
                   IconButton(
                     onPressed: onGalleryPress,
                     icon: const Icon(Icons.add_photo_alternate,
                         size: 35, color: Colors.blue),
                   ),
                 ],
               ),
             ),
           ],
         ),
       );
     }

     void onCameraPress() async {
       try {
         final file = await _imagePicker.pickImage(
           source: ImageSource.camera,
           maxWidth: null,
           maxHeight: null,
           imageQuality: null,
         );
         final InputImage inputImage = InputImage.fromFile(File(file!.path));
         final List<Face> faces = await _faceDetector.processImage(inputImage);
           _imageFile.value = File(file.path);
           _detectedFaces.value = faces;
           _loadImage(File(file.path));
       } catch (e) {
         print(e.toString());
       }
     }

     void onGalleryPress() async {
       try {
         final file = await _imagePicker.pickImage(
           source: ImageSource.gallery,
           maxWidth: null,
           maxHeight: null,
           imageQuality: null,
         );
         final InputImage inputImage = InputImage.fromFile(File(file!.path));
         final List<Face> faces = await _faceDetector.processImage(inputImage);
         print('СМОТРИТЕ: ${faces.length}');
           _imageFile.value = File(file.path);
           _detectedFaces.value = faces;
           _loadImage(File(file.path));
       } catch (e) {
         print(e.toString());
       }
     }
   
     _loadImage(File file) async {
       final data = await file.readAsBytes();
       await decodeImageFromList(data).then((value) {_image.value = value;});
     }
   
     @override
     void dispose() {
       _image.dispose();
       _imageFile.dispose();
       _detectedFaces.dispose();
       super.dispose();
     }
   }
   
   class FacePainter extends CustomPainter {
     final ui.Image image;
     final List<Face> faces;
     final List<Rect> rects = [];
   
     FacePainter(this.image, this.faces) {
       for (var i = 0; i < faces.length; i++) {
         rects.add(faces[i].boundingBox);
       }
     }
   
     @override
     void paint(ui.Canvas canvas, ui.Size size) {
       final Paint paint = Paint()
         ..style = PaintingStyle.stroke
         ..strokeWidth = 3.0
         ..color = Colors.red;
   
       canvas.drawImage(image, Offset.zero, Paint());
       for (var i = 0; i < faces.length; i++) {
         canvas.drawRect(rects[i], paint);
       }
     }

     @override
     bool shouldRepaint(FacePainter oldDelegate) {
       return image != oldDelegate.image || faces != oldDelegate.faces;
     }
   }

Ответ или решение

Решение проблемы с обнаружением лиц в Flutter с использованием google_ml_kit_flutter в классе

Если вы сталкиваетесь с проблемой, когда функциональность обнаружения лиц в вашем проекте не работает должным образом, и не удается идентифицировать явно видимые лица на изображении, вам следует принять во внимание несколько ключевых аспектов. Давайте разберем вашу проблему и основные шаги для ее решения.

1. Проверка подготовки среды

Первоначально убедитесь, что вы правильно настроили окружение. Ваша версия google_ml_kit_flutter должна быть актуальной. Проверьте файл pubspec.yaml и убедитесь, что вы используете последнюю стабильную версию пакета:

dependencies:
  google_mlkit_face_detection: ^x.x.x # Убедитесь, что версия актуальна

После внесения изменений выполните команду:

flutter pub get

2. Проверка качества изображения

Качество изображений, используемых для распознавания лиц, может существенно влиять на результаты. Рассмотрите следующие рекомендации:

  • Размер изображения: Убедитесь, что изображения, которые вы используете для обнаружения лиц, имеют достаточное разрешение. Слишком мелкие или с низким качеством изображения могут препятствовать точному распознаванию.
  • Условия освещения: Убедитесь, что изображения хорошо освещены. Сложные условия (например, слишком яркий свет или тень) могут затруднять процесс обнаружения лиц.
  • Изменение ориентации: Если изображения находятся в альбомной ориентации, попробуйте изменить их на портретную.

3. Логика работы с изображением

В вашем коде есть несколько мест, которые стоит проверить на предмет возможных улучшений:

  • Проверка ошибок: Вы выводите ошибки в консоль, но не обрабатываете их особым образом. Вы можете добавить более подробное логирование, чтобы отслеживать, какую именно ошибку возвращает функция. Например, добавьте вывод faces после обработки изображения:

    print("Найдено лиц: ${faces.length}");
  • Обработка выборки изображений: Убедитесь, что все изображения, получаемые через ImagePicker, правильно загружаются и обрабатываются. Добавьте проверку на наличие файлов и обработайте возможные ошибки, связанные с доступом к файловой системе.

4. Проверка функциональности FaceDetector

Проверьте параметры настройки FaceDetector:

_faceDetector = FaceDetector(
  options: FaceDetectorOptions(
    enableContours: true,
    enableLandmarks: true,
  ),
);

Попробуйте временно отключить enableContours и enableLandmarks, чтобы проверить, влияет ли это на обнаружение:

_faceDetector = FaceDetector(
  options: FaceDetectorOptions(
    enableContours: false,
    enableLandmarks: false,
  ),
);

5. Проверка совместимости устройства

Исследуйте, возможно ли, что проблема связана с конкретным физическим устройством. Попробуйте протестировать приложение на нескольких устройствах. Некоторые старые устройства могут не поддерживать необходимые функции распознавания лиц.

6. Сравнение с тестовыми изображениями

Если ваши тестовые изображения имеют особые условия или параметры, рассмотрите возможность использования стандартных изображений из документации google_ml_kit. Это поможет исключить вероятность проблем с изображениями в вашем проекте.

Заключение

Если ни один из предложенных шагов не помог, рассмотрите возможность поиска аналогичных проблем в сообществе разработчиков или на форумах, таких как Stack Overflow. Порой другие разработчики сталкиваются с аналогичными проблемами и могут предложить уникальные решения. Следуя этим рекомендациям, вы сможете более эффективно использовать библиотеку для обнаружения лиц в вашем приложении Flutter.

Оцените материал
Добавить комментарий

Капча загружается...