Stellen Sie das Python-Gesichtserkennungsmodell für Heroku bereit und verwenden Sie es von Flutter ②

Im vorherigen Artikel habe ich beschrieben, wie das Gesichtserkennungsmodell von Python für Heroku bereitgestellt wird.

Stellen Sie das Python-Gesichtserkennungsmodell für Heroku bereit und verwenden Sie es von Flutter ①

Dieses Mal möchte ich vorstellen, wie man dieses Modell von einer mobilen App aus aufruft und tatsächlich einen Gesichtsvergleich realisiert. Mit Flutter wurde ein Beispiel für die mobile App erstellt.

Über das Poster dieses Artikels

Wir twittern über die Entwicklung von Apps, die die Gesichtserkennung auf Twitter nutzen. https://twitter.com/studiothere2

Das Tagebuch der Anwendungsentwicklung ist in Notiz serialisiert. https://note.com/there2

App Übersicht

Screenshot_resize.png

Es ist eine einfache Anwendung, die beurteilt, ob zwei Bilder dieselbe Person sind, indem zwei Bilder aus der Galerie ausgewählt und die Vergleichstaste unten rechts gedrückt werden. Holen Sie sich die Einbettung jedes Bildes aus dem im vorherigen Artikel erstellten WEB-Dienst und berechnen Sie die L2-Norm zwischen den Einbettungen. Wenn die L2-Norm 0,6 oder weniger beträgt, wird sie als dieselbe Person beurteilt, und wenn sie höher ist, wird sie als eine andere Person beurteilt.

Wenn Sie beispielsweise eine andere Person auswählen, wie unten gezeigt, beträgt die L2-Norm 0,6 oder mehr und wird als eine andere Person beurteilt.

Screenshot_1590077756.png

Wenn die L2-Norm 0,5 oder weniger beträgt, besteht eine hohe Wahrscheinlichkeit, dass es sich um dieselbe Person handelt, und der Schwellenwert für die Beurteilung, ob es sich um dieselbe Person handelt, mit einer Genauigkeit von etwa 99% beträgt 0,6.

Codekommentar

Nutzungspaket

pubsec.yaml


dependencies:
  flutter:
    sdk: flutter
  image_picker: ^0.6.6+1
  ml_linalg: ^12.7.1
  http: ^0.12.1
  http_parser: ^3.1.4

Flatter-Quellcode

Erstens ist der Importteil. Importieren der erforderlichen Bibliotheken.

main.dart


import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:ml_linalg/linalg.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import './secret.dart';

secret.dart enthält Informationen für den Zugriff auf WEB-Dienste. Dies ist nicht in git enthalten, lesen Sie daher bitte entsprechend.

main.dart


void main() => runApp(MyApp());`

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

Bisher wurde an den für das neue Projekt erstellten Standardeinstellungen nichts geändert. Das Folgende sind die Hauptklassen.

main.dart


class _MyHomePageState extends State<MyHomePage> {
  ///Bild zum Vergleich 1
  Uint8List _cmpImage1;

  ///Bild zum Vergleich 2
  Uint8List _cmpImage2;

  //Euklidischer Abstand zwischen zwei Flächen.
  double _distance = 0;

  void initState() {
    super.initState();
  }

Es deklariert ein Element, das die Byte-Daten ("Uint8List") der beiden zu vergleichenden Bilder als Elementvariablen enthält, und eine "_distance" -Variable, die die L2-Norm (euklidischer Abstand) der Einbettung der beiden Bilder enthält.

Bilder laden

main.dart


  Future<Uint8List> _readImage() async {
    var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
    return imageFile.readAsBytesSync();
  }

Verwenden Sie die ImagePicker-Bibliothek, um Bilder aus der Galerie abzurufen. Der Rückgabewert ist vom Typ "Datei". Verwenden Sie daher die Methode "readAsBytesSync ()", um ihn in das Format "Uint8List" zu konvertieren. Uint8List ist ein Array vom Typ int und kann als Byte-Daten behandelt werden.

Eine Funktion, die das Vergleichsergebnis aus dem Abstand der L2-Norm zurückgibt

main.dart


  ///Gibt Ähnlichkeit in Abhängigkeit vom euklidischen Abstand zwischen den beiden Bildern zurück
  String _getCompareResultString() {
    if (_distance == 0) {
      return "";
    } else if (_distance < 0) {
      return "wird bearbeitet....";
    } else if (_distance < 0.6) {
      return "Gleiche Person";
    } else {
      return "Eine andere Person";
    }
  }

Diese Funktion gibt das Ergebnis des Bildvergleichs im Text gemäß dem Wert von "_distance" in der L2-Norm zurück. -1 verarbeitet, wenn es 0,6 oder weniger ist, gibt es den Text als dieselbe Person zurück, wenn es mehr als 0,6 ist, gibt es den Text als eine andere Person zurück. Rufen Sie dies über das Widget auf und zeigen Sie es auf dem Bildschirm an.

WEB Service Caller

Es ist ein bisschen lang, also werde ich es teilen und es der Reihe nach betrachten.

main.dart


  void uploadFile() async {
    setState(() {
      _distance = -1;
    });
    var response;
    var postUri = Uri.parse(yourRemoteUrl);
    var request1 = http.MultipartRequest("POST", postUri);

Setzen Sie zuerst "_distance" auf -1, damit der Bildschirm anzeigt, dass es verarbeitet wird. Bitte lesen Sie postUri separat. Wir bereiten hier eine http-Anfrage vor.

main.dart


    //Erste Datei
    debugPrint("start: " + DateTime.now().toIso8601String());
    request1.files.add(http.MultipartFile.fromBytes('file', _cmpImage1.toList(),
        filename: "upload.jpeg ", contentType: MediaType('image', 'jpeg')));
    response = await request1.send();
    if (response.statusCode == 200) print("Uploaded1!");

Das aus der Galerie erhaltene Bild wird in der http-Anfrage festgelegt und die Anfrage wird gesendet. Wenn der Rückgabewert "200" ist, ist er erfolgreich.

main.dart


    var featureString1 = await response.stream.bytesToString();
    List<double> embeddings1 =
        (jsonDecode(featureString1) as List<dynamic>).cast<double>();
    debugPrint("end: " + DateTime.now().toIso8601String());

Der Rückgabewert des Webdienstes wird von einem Byte-Array in eine Zeichenfolge konvertiert und erhalten (featureString1), jsonDecode wird in double umgewandelt und als Ergebnis als Array vom Typ double erfasst. .. Dies ist die Einbettung des Bildes, und Sie können beurteilen, ob es sich um dieselbe Person handelt, indem Sie sie vergleichen.

main.dart


    //Zweite Datei
    var request2 = http.MultipartRequest("POST", postUri);
    request2.files.add(http.MultipartFile.fromBytes('file', _cmpImage2.toList(),
        filename: "upload.jpeg ", contentType: MediaType('image', 'jpeg')));
    response = await request2.send();
    if (response.statusCode == 200) print("Uploaded2!");
    var featureString2 = await response.stream.bytesToString();
    List<double> embeddings2 =
        (jsonDecode(featureString2) as List<dynamic>).cast<double>();

Bisher habe ich das gleiche für das zweite Bild getan. Als nächstes folgt der Berechnungsteil der L2-Norm.

main.dart


    var distance = Vector.fromList(embeddings1)
        .distanceTo(Vector.fromList(embeddings2), distance: Distance.euclidean);

    setState(() {
      _distance = distance;
    });
  }

Es ist sehr einfach, weil es die ml_linalg Bibliothek verwendet. Alles, was Sie tun müssen, ist, die Einbettung jedes Arrays vom Typ "double" mit "Vector.fromList" in "Vector" zu konvertieren und die Entfernung mit "distanceTo" zu ermitteln. Der euklidische Abstand (L2-Norm) wird als Berechnungsmethode für den Abstand angegeben.

Stellen Sie abschließend den Abstand zur Mitgliedsvariablen "_distance" ein und fertig.

Bildschirmzeichnungsteil

main.dart


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Expanded(
                flex: 1,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    RaisedButton(
                      onPressed: () async {
                        var cmpImage = await _readImage();
                        setState(() {
                          _cmpImage1 = cmpImage;
                        });
                      },
                      child: Text("Laden des ersten Bildes"),
                    ),
                    Text("Erstes Bild"),
                    Container(
                      child:
                          _cmpImage1 == null ? null : Image.memory(_cmpImage1),
                    ),
                  ],
                ),
              ),
              Expanded(
                flex: 1,
                child: Column(
                  children: <Widget>[
                    RaisedButton(
                      onPressed: () async {
                        var cmpImage = await _readImage();
                        setState(() {
                          _cmpImage2 = cmpImage;
                        });
                      },
                      child: Text("Laden des zweiten Bildes"),
                    ),
                    Text("Zweites Bild"),
                    Container(
                      child:
                          _cmpImage2 == null ? null : Image.memory(_cmpImage2),
                    ),
                  ],
                ),
              )
            ],
          ),
          SizedBox(height: 10),
          Text("Ergebnisse des Gesichtsähnlichkeitsvergleichs"),
          Text(_getCompareResultString()),
          Text("L2 Norm$_Entfernung"),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: uploadFile,
        tooltip: 'Bildvergleich',
        child: Icon(Icons.compare),
      ),
    );
  }

Es ist etwas lang, aber einfach. Laden Sie das Bild mit der Ladetaste jedes der beiden Bilder. Die "Uint8List" -Daten des geladenen Bildes können mit "Image.memory" auf dem Bildschirm angezeigt werden. Das Vergleichsergebnis des Bildes wird auf Japanisch mit _getCompareResultString () angezeigt. Das "onPressed" des "FloatingActionButton" ruft den WEB-Dienst auf, um den Prozess der Berechnung der Bildabdruckentfernung aufzurufen.

Schließlich

Wenn es sich um ein Gesichtsbild handelt, das richtig reflektiert wird, wird beurteilt, ob es sich um dieselbe Person handelt. Es ist also ziemlich beeindruckend. In letzter Zeit scheint es ein Modell zu geben, das das Gesicht auch dann erkennen kann, wenn es maskiert ist. Die Verwendung der Gesichtserkennung hat das Problem, in die Privatsphäre einzudringen. Sie müssen daher vorsichtig sein, wie Sie sie verwenden. Es würde jedoch Spaß machen, wenn Sie einen Dienst entwickeln könnten, der sie gut nutzt.

Recommended Posts

Stellen Sie das Python-Gesichtserkennungsmodell für Heroku bereit und verwenden Sie es von Flutter ②
Stellen Sie das Python-Gesichtserkennungsmodell für Heroku bereit und verwenden Sie es von Flutter ①
Stellen Sie das in Python unter SQL Server erstellte Vorhersagemodell bereit und verwenden Sie es
Lesen und verwenden Sie Python-Dateien aus Python
Verwenden Sie das von fastText trainierte Modell von Python
Installieren Sie mecab auf dem gemeinsam genutzten Sakura-Server und rufen Sie es von Python aus auf
Firebase: Verwenden Sie Cloud Firestore und Cloud Storage von Python
Verknüpfung von PHP und Python von Grund auf auf Laravel
Bis zur Verwendung von PhantomJS mit Python auf Heroku
Verwenden Sie Python auf Raspberry Pi 3, um die LED zu beleuchten, wenn es dunkel wird!
Installieren Sie Selenium auf Ihrem Mac und probieren Sie es mit Python aus
Ich habe versucht, regelmäßig E-Mails von sendgrid mit Heroku und Python zu senden
Erhalten Sie E-Mails von Google Mail und beschriften Sie sie mit Python3
Ubuntu 20.04 auf Himbeer-Pi 4 mit OpenCV und mit Python verwenden
Verwenden Sie thingspeak aus Python
Verwenden Sie fließend Python
Verwenden Sie MySQL aus Python
Verwenden Sie MySQL aus Python
Verwenden Sie BigQuery aus Python.
Verwenden Sie mecab-ipadic-neologd von Python
Installieren Sie Mecab und CaboCha auf ubuntu16.04LTS, damit es aus der Python3-Serie verwendet werden kann
Setzen Sie Ubuntu in Raspi ein, setzen Sie Docker darauf und steuern Sie GPIO mit Python aus dem Container
So stellen Sie Pybot, das einfachste Python-Lehrbuch, auf Heroku bereit
Ein Hinweis beim Berühren der Gesichtserkennungs-API von Microsoft mit Python
Installieren Sie pyenv auf MacBookAir und wechseln Sie Python zur Verwendung
Ich habe versucht, das Gesicht aus dem Video zu erkennen (OpenCV: Python-Version)
[Python] Ich habe das Spiel von pip installiert und versucht zu spielen
Verwenden Sie matplotlib unter Ubuntu 12 und Python
Python auf Ruby und wütend Ruby auf Python
Verwenden Sie MySQL von Anaconda (Python)
Stellen Sie die Masonite-App auf Heroku 2020 bereit
Verwenden Sie das Django-Modell vom Interpreter
Versuchen Sie die Gesichtserkennung mit Python
Verwenden Sie Python unter Windows (PyCharm)
Verwenden Sie die e-Stat-API von Python
Verarbeitung zur Verwendung von notMNIST-Daten in Python (und versucht, sie zu klassifizieren)
So installieren Sie OpenCV in Cloud9 und führen es in Python aus
Holen Sie sich Daten von VPS MySQL mit Python 3 und SQL Alchemy
Installieren Sie lp_solve unter Mac OSX und rufen Sie es mit Python auf.
[Python + Heroku] Vom Zustand ohne Python zur Anzeige von etwas mit Heroku (Teil 2)
Alles vom Erstellen einer Python-Umgebung bis zur Ausführung unter Windows