Eine kleine Hilfestellung zur Verwendung der Face-API.
Die Microsoft Face-API ist ein neuer Microsoft Dienst für die Gesichtserkennung. Dank der Software bzw. der API ist es möglich, die Funktionalität der sogenannten Face Perception in eigene Applikationen und Anwendungen einzubauen. Damit eröffnen sich dem Programmierer/Entwickler eine Vielzahl an neuen Möglichkeiten und Techniken im Bereich der Entwicklung.
Die Grundlagen der Face-API
Ziel dieses Tutorials ist es, eine App bzw. ein Programm zu entwickeln, das auf die Webcam zugreifen kann, um ein Foto von einer Person zu erhalten. Anschließend soll die App unter Nutzung der Gesichtserkennung, das Bild bzw. das Gesicht identifizieren. Anschließend soll in der Applikation der Name der Person angezeigt werden, die auf dem Foto identifiziert wurde.
Die API Keys erhalten
Bevor Du aber loslegen kannst, brauchst Du zunächst einige gültige API Keys, die du mit der Face-API von Microsoft nutzen kannst. Diese bekommst Du auf der Microsoft Homepage. Dort hast Du – nach der Anmeldung – die Möglichkeit, Trial Keys für Testzwecke zu erhalten. Diese sind kostenlos und auf 30000 Transaktionen im Monat beziehungsweise auf 20 Transaktionen pro Minute beschränkt. VORSICHT: Microsoft bietet Dir hier auch die Möglichkeit an, den Face-API Key bei Azure kostenpflichtig zu kaufen. Hier beginnt der Preis bei ca. 1,50 USD für 1000 Transaktionen. Wie Du siehst, ist das Trial Angebot also deutlich besser. Darüber hinaus ist die Trial API für die Gesichtserkennung im Rahmen dieses Tutorials mehr als ausreichend und sollte auch im Alltag mehr als genug sein, sofern es nicht darum geht, extrem viel Traffic zu verarbeiten.
Programmierung der Gesichtserkennung – welche Programmiersprache lohnt sich?
Generell ist es möglich, in fast allen Programmiersprachen eine App zur Gesichtserkennung zu erstellen. Besonders beliebt sind jedoch C++ sowie C#. In diesem Tutorial werden wir der Einfachheit halber mit C# arbeiten. Die Arbeitsschritte und Codebeispiele lassen sich jedoch mit wenig Mühe auch auf die anderen Sprachen anwenden bzw. in diese migrieren. Auf die Funktionalität und Performance hat die Wahl der Sprache nur eine geringe Auswirkung.
Der nächste Schritt: ein Gesicht erstellen
In unserem C# Beispiel erstellen wir zunächst eine neue UWP Applikation. Außerdem benötigen wir zwei zusätzliche NuGet pakete. Bei diesen handelt es sich um Newtonsoft.JSO sowie um Microsoft.ProjectOxford.Face. Diese kannst Du dir im Internet herunterladen. Für dieses Beispiel erzeugen wir alles, was wir für die Gesichtserkenung brauchen, direkt in der MainPage.xaml Datei. Der Hintergrundcode hingegen kommt in die Datei MainPage.xaml.cs. Später, wenn Du Deine eigenen Anwendungen zur Gesichtserkennung mit der Face-API entwickelst, musst Du Dir selbst Gedanken darüber machen, wie Du Deine Dateien einbindest und aufteilst.
Soweit so gut. Das Prinzip hinter dem Code ist denkbar einfach: der Browse Button dient dazu, nach einem bestimmten Bild zu suchen und dieses im Sichtfenster anzuzeigen. Die Option Find Face… hingegen ruft die Face-API zwecks der Gesichtserkennung auf. Sobald das Ergebnis zurück kommt, wird ein grünes Quadrat über dem Gesicht angezeigt.
Nun beginnt die Arbeit am Code, der im Hintergrund läuft. Hier benötigen wir als erstes ein Objekt für den Face Service. Dieses fügen wir wie folgt ein:
private readonly IFaceServiceClient _faceServiceClient = new FaceServiceClient("YOUR_API_KEY");
Nun ist es besonders wichtig, dass Du sowohl Microsoft.ProjectOxford.Face als auch Microsoft.ProjectOxford.Face.Contract einbindest. Ansonsten kann die Gesichtserkennung nicht funktionieren. Der Code für den Browse Button, sieht wie folgt aus:
private StorageFile _imageFile; private async void BrowseButton_Click(object sender, RoutedEventArgs e) { // Thanks to Suresh-M at https://code.msdn.microsoft.com/File-Picker-in-Windows-10-846c2116 // for filepicker code. FileOpenPicker openPicker = new FileOpenPicker(); openPicker.ViewMode = PickerViewMode.Thumbnail; openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; openPicker.FileTypeFilter.Add(".jpg"); openPicker.FileTypeFilter.Add(".png"); _imageFile = await openPicker.PickSingleFileAsync(); if (_imageFile == null) { StatusField.Text = "Status: Image failed to load"; return; } FaceCanvas.Children.Clear(); var stream = await _imageFile.OpenAsync(FileAccessMode.Read); BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); BitmapTransform transform = new BitmapTransform(); const float sourceImageHeightLimit = 1280; if (decoder.PixelHeight > sourceImageHeightLimit) { float scalingFactor = (float)sourceImageHeightLimit / (float)decoder.PixelHeight; transform.ScaledWidth = (uint)Math.Floor(decoder.PixelWidth * scalingFactor); transform.ScaledHeight = (uint)Math.Floor(decoder.PixelHeight * scalingFactor); } _bitmapSource = await decoder.GetSoftwareBitmapAsync(decoder.BitmapPixelFormat, BitmapAlphaMode.Premultiplied, transform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage); ImageBrush brush = new ImageBrush(); SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource(); await bitmapSource.SetBitmapAsync(_bitmapSource); brush.ImageSource = bitmapSource; brush.Stretch = Stretch.Uniform; FaceCanvas.Background = brush; StatusField.Text = "Status: Image loaded"; }
Mit diesem Code funktioniert der Browse Button einwandfrei und Du kannst diesen nutzen, damit Dir ein Foto Deiner Wahl in das Sichtfenster zu laden. Damit das Ganze funktioniert, musst Du nun eine Anfrage direkt an die Face-API senden. Diese beinhaltet das ausgewählte Bild. Auf dem selben Weg erhältst Du von der API die Ergebnisse der Anfrage zurück – vorausgesetzt, es existieren welche. Der Code für die Anfrage und Kommunikation mit der API sieht wie folgt aus:
private async void FindFaceButton_Click(object sender, RoutedEventArgs e) { FaceRectangle[] faceRects = await UploadAndDetectFaces(); StatusField.Text = $"Detection Finished. {faceRects.Length} face(s) detected"; if (faceRects.Length > 0) { MarkFaces(faceRects); } } private async Task UploadAndDetectFaces() { try { StatusField.Text = "Status: Detecting..."; using (Stream imageFileStream = await _imageFile.OpenStreamForReadAsync()) { var faces = await _faceServiceClient.DetectAsync(imageFileStream); var faceRects = faces.Select(face => face.FaceRectangle); return faceRects.ToArray(); } } catch (Exception ex) { StatusField.Text = $"Status: {ex.Message}"; return new FaceRectangle[0]; } }
Wie Du siehst, ist die ganze Aufgabe relativ einfach. Es handelt sich im Prinzip um eine Methode, die durch einen Klick auf den Button ausgelöst wird. Diese ruft eine weitere Methode auf, die das ausgewählte Bild hoch lädt und über die Face API mit bekannten Fotos vergleicht. Die bekannten Fotos bzw. Gesichter werden mit dem neuen Foto verglichen. Anschließend wird das Ergebnis zurückgegeben. Das Endergebnis ist schließlich einfach ein quadratisches Fenster, das als Display für das ausgewählte Bild dient. Außerdem gibt es die beiden Buttons, jeweils um ein Foto auszuwählen und um die Abfrage über die Face-API mit den Daten zu vergleichen. Das Ergebnis wird anschließend in einem kleinen Fenster im unteren Bereich angezeigt.