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.
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
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.
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.
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
image_picker
. Dies ist eine großartige Möglichkeit, um Bilder aus der Galerie oder von der Kamera zu erhalten.ml_linalg
berechnet. Dies ist eine Dart-Bibliothek, die Vektoroperationen ausführen kann.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.
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.
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.
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.
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.
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