November 2016

Band 31, Nummer 11

Dieser Artikel wurde maschinell übersetzt.

Cognitive Services: Die Welt mit Xamarin und Microsoft Maschinelles Sehen-APIs sehen

Durch Alessandro Del Del   VB

In meinem letzten Artikel wurde ich eine kurze Einführung zu Microsoft kognitive beschreiben die verfügbaren RESTful-APIs und zeigen die und "Emotion" APIs in einer plattformübergreifenden app mit Xamarin.Forms und c# geschrieben (msdn.microsoft.com/magazine/mt742868). In diesem Artikel werde ich eine andere wichtige Satz von APIs, als Computer Vision bezeichnet werden. Sie sollten den früheren Artikel zu lesen, bevor Sie mit dieser fortfahren, da ich werde wird davon ausgegangen, dass Sie mit einigen Konzepten zu kognitive Services, dass ich es erläutert vertraut sind, und da ich einige NuGet-Pakete und Codeausschnitte aus dem vorherigen Beispiel-app wieder verwendet werden. Allerdings beginnen wir mit der Beschreibung der Microsoft Computer Vision-APIs.

Erste Schritte mit dem Computer Vision-APIs

Die Computer Vision-APIs können Bilder, beschrieben und mit natürlicher Sprache analysiert. Sie können ein Bild in den Computer Vision-Dienst hochladen oder auf eine Bild-URL zeigen und erwarten, eine ganz natürliche Beschreibung zurückzubekommen, ohne selbst Beschreibungen erstellen und formatieren zu müssen. Aber das ist nicht alles. Computer Vision kann Optical Character Recognition (OCR) über ein Bild, das Text enthält, und ein Bild, um Gesichter Promis erkennen gescannt werden können. Wie bei anderen Diensten Computer Vision basiert auf maschinelles lernen und unterstützt REST, was bedeutet, dass Sie HTTP-Anforderungen durchgeführt, und erhalten eine JSON-Antwort. JSON in Abbildung 1 zeigt einen Auszug aus der Antwort der Computer Vision Analyse über ein Bild, stammt aus der offiziellen Dokumentation unter bit.ly/2a45kQI.

Abbildung 1 Ergebnis Computer Vision eines Bilds

{
  "description": {
    "tags": [
      "person",
      "man",
      "outdoor",
      "window",
    ],
    "captions": [
      {
        "text": "Satya Nadella sitting in front of a building",
        "confidence": 0.38035155997373377
      }
    ]
  },
  "requestId": "ed2de1c6-fb55-4686-b0da-4da6e05d283f",
  "metadata": {
    "width": 1500,
    "height": 1000,
    "format": "Jpeg"
  }
}

Wie Sie sehen, enthält die Antwort eine natürliche Sprache Beschreibung ein prominenter es auch in der Abbildung ist eine Liste mit zusätzlichen Informationen wie Tags, Größe und Format ausgeführten. Und dies sind nur einige der Informationen, die Sie vom Computer Vision-Dienst abrufen können.

Ausführen von HTTP-Anforderungen sicherlich funktioniert, aber als Entwickler .NET auch einen anderen Ansatz. Wie bei der Fläche und Emotion APIs, bietet Microsoft eine portable Clientbibliothek (PCL) für Computer Vision, mit denen Sie in C#-Anwendung, einschließlich .NET und Xamarin, die über einfache Methoden, die mit einem objektorientierten Ansatz des Diensts aufgerufen werden können. Ich werde in Kürze diese Bibliothek verwenden.

Abonnieren den Computer Vision-APIs

Wie bei anderen Diensten kognitive zur Verwendung der Computer Vision-APIs müssen den Dienst registrieren und erhalten einen geheimen Schlüssel für die Verwendung in Ihrem Code. Um dies zu erreichen, navigieren Sie zu der Seite Abonnements (bit.ly/2b2rKDO), und fordern Sie eine neue Testversion für die Computer Vision-APIs. Abbildung 2 zeigt, wie Ihr Abonnement nach der Registrierung angezeigt wird.

Registrieren für die Computer Vision-APIs
Abbildung 2: Registrieren für die Computer Vision-APIs

Wie Sie sehen können, erhalten Sie zwei geheimen Schlüssel. Sie müssen eine später benötigen, wenn C#-Code geschrieben werden.

Erstellen einer Xamarin.Forms-App und Installieren von NuGet-Pakete

Starten Sie Visual Studio 2015 und erstellen Sie ein neues Xamarin.Forms-Projekt mit der Projektvorlage leere XAML-App (Xamarin.Forms Portable). Rufen Sie das neue Projekt ComputerVisionSample, und klicken Sie auf OK. Wenn Sie bereit sind, installieren Sie die folgenden NuGet-Pakete:

Microsoft.ProjectOxford.Vision installiert die Clientbibliothek für die Computer Vision-APIs und muss installiert sein, um PCL-Projekt.

Xam.Plugin.Connectivity enthält die Plug-in-Konnektivität für Xamarin.Forms und muss für alle Projekte in der Projektmappe installiert werden. Es wird zum Überprüfen einer Verbindung, bevor Sie versuchen, über das Internet anzufordern.

Xam.Plugin.Mediacontains-Plug-In für Xamarin.Forms Medien für alle Projekte in der Projektmappe installiert werden muss. Es wird verwendet, und wählen Sie Bilder aus dem freigegebenen Code statt plattformspezifischen Code schreiben zu müssen.

Stellen Sie sicher, dass in diesem Fall die Projektmappe zu erstellen, damit alle Verweise aktualisiert werden. Nun los geht's Computer Vision-APIs, die drei wichtigsten Szenarien zu analysieren.

Beschreiben Sie die Bilder mit den Analyse-APIs

Die Computer Vision-Clientbibliothek stellt eine Klasse namens Microsoft.ProjectOxford.Vision.VisionServiceClient, das Objekt mit dem Anforderungen an den Dienst gesendet, und, die Eigenschaften, die das Analyseergebnis. Diese Klasse wird in allen Szenarien verwendet werden, die ich als Ziel. Im erste Szenario beschreibt Bildern, mit denen ich erhalten eine Beschreibung meine, wie das Bild darstellt, basierend auf natürliche, lesbare Sprache. Die Antwort des Diensts sendet enthält auch Informationen, z. B. bestimmende Farben, Flächen erkannt, Tags, Typ und Größe, und auch, ob ein Bild für Erwachsene oder schicken Inhalt enthält. Um ein Bild zu beschreiben, stellt die VisionServiceClient-Klasse zwei Methoden zur Verfügung: AnalyzeImageAsync und DescribeAsync. Der zweite Schritt bietet eine kleinere Gruppe von Informationen und wird in der Regel verwendet, um nur eine natürliche Sprache Beschreibung des Bildes abzurufen während AnalyzeImageAsync zurückgibt, ausführlichere Informationen. Beide Methoden speichern ihre Antwort in ein Objekt vom Typ Microsoft.ProjectOxford.Vision.Contract.AnalysisResult. Ich werde AnalyzeImageAsync in diesem Artikel verwenden. Diese Methode verfügt über zwei Überladungen, eine akzeptiert einen Datenstrom und einen akzeptiert eine URL zu einem Bild verweist; Beide Überladungen erfordern die Angabe von Informationen, die Sie aus dem Bild abrufen möchten. Dieser Satz von Informationen wird durch ein Array von Werten aus der Enumeration Microsoft.ProjectOxford.Vision.VisualFeature dargestellt. In der Seite "MainPage.xaml" Anwendung implementiere ich die Bild-Beschreibung. Abbildung 3 zeigt, wie eine detaillierte Analyse-Methode implementieren.

Abbildung 3 Analyse der Beschreibung eines Bildes

private async Task<AnalysisResult> AnalyzePictureAsync(Stream inputFile)
{
  // Use the connectivity plug-in to detect
  // if a network connection is available
  // Remember using Plugin.Connectivity directive
  if (!CrossConnectivity.Current.IsConnected)
  {
    await DisplayAlert("Network error",
      "Please check your network connection and retry.", "OK");
    return null;
  }
  VisualFeature[] visualFeatures = new VisualFeature[] { VisualFeature.Adult,
    VisualFeature.Categories, VisualFeature.Color, VisualFeature.Description,
    VisualFeature.Faces, VisualFeature.ImageType, VisualFeature.Tags };
  AnalysisResult analysisResult =
    await visionClient.AnalyzeImageAsync(inputFile,
    visualFeatures);
  return analysisResult;           
}

Beachten Sie, wie der Code die Konnektivität-Plug-in verwendet, um eine Netzwerkverbindung erkennen wie ich in meinem vorherigen Artikel erläutert. Es gibt drei wichtige Punkte im Abbildung 3. Der erste Punkt bezieht sich auf die Informationen, die Sie abrufen möchten. Das Array von Werten VisualFeature enthält die ausführliche Liste der möglichen Informationen und Werte aus der VisualFeature-Enumeration enthält. Diese bestehen aus selbsterklärend und Erkennung von Erwachsenen und schicken, eine Liste der Kategorien für das Bild, bestimmende Farben, eine Beschreibung für die natürliche Sprache, eine Liste von Schriftarten, Informationen und eine Liste der Tags enthalten. Ich habe die Flächen Wert der Vollständigkeit halber enthalten, aber ich nicht tatsächlich verwenden dieses Ergebnis, da Sie ausführlichere Informationen zu Flächen, die mit der API Face abrufen können. Zweite ist der Aufruf von AnalyzeImageAsync, sendet einen Datenstrom an den Dienst zusammen mit der Liste der Informationen abgerufen werden sollen, und speichert die Antwort in ein Objekt vom Typ AnalysisResult. Diese Klasse ist die dritte wichtige und ist definiert Abbildung 4.

Abbildung 4 Definition der AnalysisResult-Klasse

namespace Microsoft.ProjectOxford.Vision.Contract
{
  public class AnalysisResult
  {
    public AnalysisResult();
    public Adult Adult { get; set; }
    public Category[] Categories { get; set; }
    public Color Color { get; set; }
    public Description Description { get; set; }
    public Face[] Faces { get; set; }
    public ImageType ImageType { get; set; }
    public Metadata Metadata { get; set; }
    public Guid RequestId { get; set; }
    public Tag[] Tags { get; set; }
  }
}

Um diese Definition anzuzeigen, mit der rechten Maustaste in des AnalysisResult-Typs im Code-Editor, und wählen Sie Gehe zu Definition (oder Definition einsehen, wenn Sie das aktive Fenster lassen möchten). Wie Sie sehen können, stellt die Definition Eigenschaften, die die erforderliche Informationen über spezielle Objekte enthalten. Gehe zu Definition in jeden Eigenschaftentyp verwenden, können Sie verstehen, wie jede spezielles Objekt definiert ist und daher, wie Sie es in Ihrer app (mit Daten binden, z. B.) verwenden können. Der Typ der Beschreibung ist z. B. wie folgt definiert:

public class Description
{
  public Description();
  public Caption[] Captions { get; set; }
  public string[] Tags { get; set; }
}

Hier ist die wichtigste Eigenschaft Beschriftungen, ein Array von Objekten der Beschriftung. Jede Beschriftung enthält eine lesbare Beschreibung des Diensts aus dem Bild abgerufen, das durch die Text-Eigenschaft bereitgestellt wird. Nicht jugendfreie Klasse wird wie folgt definiert:

public class Adult
 {
   public Adult();
   public double AdultScore { get; set; }
   public bool IsAdultContent { get; set; }
   public bool IsRacyContent { get; set; }
   public double RacyScore { get; set; }
 }

Dies ist ein einfacher Klasse und stellt zwei boolesche Eigenschaften, die die Rückgabe von true, wenn das Bild nicht jugendfreie oder schicken Inhalt enthält, sowie zwei weitere Eigenschaften, die das Vertrauen für dieses Ergebnis darstellen. Dies ist besonders nützlich, wenn Sie die Verfügbarkeit Inhalts einschränken möchten. Betrachten Sie nun die Definition der Color-Klasse:

public class Color
{
  public Color();
  public string AccentColor { get; set; }
  public string DominantColorBackground { get; set; }
  public string DominantColorForeground { get; set; }
  public string[] DominantColors { get; set; }
  public bool IsBWImg { get; set; }
}

Diese Klasse dient zum Speichern einer Liste von Farben, die Abbildung zeigt, wie z. B. die Akzentfarbe, bestimmende Vordergrund- und Hintergrundfarben und ein Array von bestimmende Farben erkannt. Macht auch eine Eigenschaft namens IsBWImg, vom Typ Bool true zurückgibt, wenn das Bild Schwarz und weiß ist. Verstehen, wie diese Objekte definiert werden und die Eigenschaften, die sie verfügbar machen helfen, wenn Sie Informationen in der Benutzeroberfläche über die Datenbindung darstellen möchten. Ich lasse sie Ihnen die Definition von anderen Klassen zu untersuchen, die AnalysisResult verwendet, um die Informationen für die Analyse zu speichern. Ist die Instanz AnalysisResult kann Daten-gebunden werden einige Elemente der Benutzeroberfläche ganz einfach Informationen anzuzeigen und werde ich dies in Kürze. Berücksichtigen Sie Abbildung 5, die zeigt, die vollständige Liste der XAML-CODE zur Definition der Benutzeroberfläche für die Beispiel-app erforderlich.

Abbildung 5: die Definition der Benutzeroberfläche für die Image-Beschreibung

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ComputerVisionSample"
             x:Class="ComputerVisionSample.MainPage">
  <StackLayout Orientation="Vertical">
    <Button x:Name="TakePictureButton" Clicked="TakePictureButton_Clicked"
      Text="Take from camera"/>
    <Button x:Name="UploadPictureButton" Clicked="UploadPictureButton_Clicked"
      Text="Pick a photo"/>
    <ActivityIndicator x:Name="Indicator1" IsVisible="False" IsRunning="False" />
    <Image x:Name="Image1" HeightRequest="240" />
  <ScrollView Padding="10">
    <StackLayout>
      <StackLayout Orientation="Horizontal">
        <Label Text="Adult content: "/>
        <Label Text="{Binding Adult.IsAdultContent}"/>
      </StackLayout>
      <StackLayout Orientation="Horizontal">
        <Label Text="Racy content: "/>
        <Label Text="{Binding Adult.IsRacyContent}"/>
      </StackLayout>
      <StackLayout Orientation="Horizontal">
        <Label Text="Description: "/>
        <Label Text="{Binding Description.Captions[0].Text}"/>
      </StackLayout>
      <StackLayout Orientation="Horizontal">
        <Label Text="Accent color: "/>
        <Label Text="{Binding Color.AccentColor}"/>
      </StackLayout>
      <StackLayout Orientation="Horizontal">
        <Label Text="Tags: "/>
        <ListView ItemsSource="{Binding Tags}">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell>
                <Label Text="{Binding Name}"/>
              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>
      </StackLayout>      
    </StackLayout>
  </ScrollView>
</ContentPage>

Benutzeroberfläche definiert zwei Schaltflächen, eine für ein Bild auswählen, von dem Gerät und eine für die Aufnahme von der Kamera, sowie eine ActivityIndicator, die anzeigt, dass ein Vorgang ausgeführt wird. Das ausgewählte Bild wird in einem Bild-Steuerelement angezeigt. (Ich verwendet diese Steuerelemente im vorherigen Artikel zu.) Beachten Sie, wie die Datenbindung innerhalb der Label-Steuerelemente ausgedrückt werden. Sie können z. B. die Text-Eigenschaft direkt auf Adult.IsAdultContent und Adult.IsRacyContent aus der AnalysisResult-Instanz anstatt komplexe Bindungen binden. Auf ähnliche Weise können Sie die natürlicher Sprache Beschreibung eines Bildes durch direkte Bindung an die Text-Eigenschaft des ersten Caption-Objekts in der Auflistung der Beschriftungen verfügbar gemacht, von der AnalysisResult.Description-Eigenschaft abrufen. Natürlich ist dies in Ordnung, wenn nur eine Beschriftung oder wenn Sie nur das erste Ergebnis anzeigen möchten. Allerdings Beschriftungen enthält möglicherweise mehrere Beschriftung Objekte und, in diesem Fall möchten Sie eine andere Bindung auswählen. Die direkte Bindung erfolgt anhand der Color.AccentColor-Eigenschaft. Für Tags zeigt die Benutzeroberfläche die Liste der Tags mit einem ListView-Steuerelement mit einer Datenvorlage, die eine Bezeichnung für jeden Tagnamen darstellt. Im Codebehind, müssen Sie zunächst zwei Ereignishandler für die Schaltflächen implementieren, siehe Abbildung 6. Der Code verwendet die Plug-in-Medien ich bereits in meinem vorherigen Artikel beschrieben, damit ich hier verdeckt wird.

Abbildung 6-Ereignishandler für die Schaltflächen geklickt

private async void TakePictureButton_Clicked(object sender, EventArgs e)
{
  await CrossMedia.Current.Initialize();
  if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
  {
    await DisplayAlert("No Camera", "No camera available.", "OK");
    return;
  }
  var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
  {
    SaveToAlbum = true,
    Name = "test.jpg"
  });
  if (file == null)
      return;
  this.Indicator1.IsVisible = true;
  this.Indicator1.IsRunning = true;
  Image1.Source = ImageSource.FromStream(() => file.GetStream());
  var analysisResult = await AnalyzePictureAsync(file.GetStream());
  this.BindingContext = analysisResult;
  this.Indicator1.IsRunning = false;
  this.Indicator1.IsVisible = false;
}
private async void UploadPictureButton_Clicked(object sender, EventArgs e)
{
  if (!CrossMedia.Current.IsPickPhotoSupported)
  {
    await DisplayAlert("No upload", "Picking a photo is not supported.", "OK");
    return;
  }
  var file = await CrossMedia.Current.PickPhotoAsync();
  if (file == null)
      return;
  this.Indicator1.IsVisible = true;
  this.Indicator1.IsRunning = true;
  Image1.Source = ImageSource.FromStream(() => file.GetStream());
  var analysisResult = await AnalyzePictureAsync(file.GetStream());
  this.BindingContext = analysisResult;
  this.Indicator1.IsRunning = false;
  this.Indicator1.IsVisible = false;
}

Hier wird der Aufruf der Methode AnalyzePictureAsync, dessen Ergebnis (eine Instanz von AnalysisResult) wird auf der Seite als Datenquelle zugewiesen. Dies ermöglicht die Datenbindung angezeigt, Elemente der Benutzeroberfläche Abbildung 6. Dann müssen Sie zum Deklarieren und instanziieren die VisionServiceClient-Klasse wie folgt:

private readonly VisionServiceClient visionClient;
public MainPage()
{
  InitializeComponent();
  this.visionClient =
    new VisionServiceClient("YOUR-KEY-GOES-HERE");
}

Beachten Sie, dass müssen Sie eines der geheimen Schlüssel angeben, die Sie erhalten haben, bei der Registrierung für die Computer Vision-APIs. Schließlich müssen Sie die richtigen Berechtigungen in der app-Manifest hinzu. Die universelle Windows-Plattform (UWP)-Projekt benötigt z. B. die Internet, Webcam und Bildbibliothek Funktionen; und das Android-Projekt die INTERNET, KAMERA, READ_EXTERNAL_STORAGE und WRITE_EXTERNAL_STORAGE-Berechtigungen erforderlich. Jetzt können Sie die Anwendung auf Ihrem bevorzugten Gerät oder Emulator starten. Abbildung 7 zeigt die Ausführung im Modus mit einem Bild und die angeforderten Informationen UWP-Version.

Beschreiben Sie ein Bild mit den Computer Vision-APIs
Abbildung 7 beschreiben ein Bild mit dem Computer Vision APIs

Für alle verfügbaren Informationen werden Sie wahrscheinlich am häufigsten anhand des Inhalts der Description-Eigenschaft der Klasse AnalysisResult beeindruckt sein bietet eine automatisch generierte, lesbare Beschreibung ohne Aufwand.

Abrufen von Text aus Bildern mit OCR

OCR ist die elektronische Konvertierung eines Bilds von Text in Text bearbeitet werden. Die meisten Scanner Lieferumfang OCR-Software, die bearbeitet werden Dokumente von Bildern, die Text enthält, z. B. magazine Seiten ermöglicht. Der Satz von APIs für Computer Vision bietet einen OCR-Dienst, der Text aus Bildern, unabhängig von der Sprache des Texts abrufen kann. OCR führt im Grunde String-Objekten. Um zu verstehen, wie die OCR-APIs arbeiten, fügen Sie eine neue XAML-Seite, PCL-Projekt. Im Projektmappen-Explorer mit der ComputerVisionSample (portabel) rechten Maustaste, wählen Sie hinzufügen | Neues Element, und wählen Sie dann im Dialogfeld Neues Element hinzufügen die plattformübergreifende Knoten Xaml Page-Element. Rufen Sie das neue Fenster OcrRecognitionPage. Die VisionServiceClient-Klasse macht eine Methode namens RecognizeTextAsync, die OCR in einem Bild ausführt. Diese Methode akzeptiert einen Stream oder eine URL zu einem Bild verweist, und geben Sie optional die Sprache. Wenn Sie eine Sprache angeben, versucht RecognizeTextAsync, automatische Spracherkennung. Es gibt ein Objekt vom Typ Microsoft.ProjectOxford.Vision.Contract.OcrResults, ist ein wenig komplexer und weitere Erläuterung verdient. Jetzt sollten Sie den folgenden Code, der OCR-Dienst über einen Stream aufruft und automatische Erkennung die Sprache:

private async Task<OcrResults> AnalyzePictureAsync(Stream inputFile)
{
  if (!CrossConnectivity.Current.IsConnected)
  {
    await DisplayAlert("Network error",
      "Please check your network connection and retry.", "OK");
    return null;
  }
  OcrResults ocrResult = await visionClient.RecognizeTextAsync(inputFile);
  return ocrResult;
}

Beachten Sie, wie Sie immer für die Netzwerkkonnektivität zuerst überprüfen. Wenn Sie eine Sprache angeben möchten, übergeben Sie an RecognizeTextAsync eine Instanz der Klasse RecognizeLanguage wie folgt:

OcrResults ocrResult =
  await visionClient.RecognizeTextAsync(inputFile,
  new RecognizeLanguage(){ ShortCode = "it", LongName = "Italian"  }

Die offizielle beispielanwendung für WPF an bit.ly/2ahHum3 zeigt die vollständige Liste der unterstützten Sprachen und Fehlercodes. Die Klasse OcrResults ist wie folgt definiert:

public class OcrResults
{
  public OcrResults();
  public string Language { get; set; }
  public string Orientation { get; set; }
  public Region[] Regions { get; set; }
  public double? TextAngle { get; set; }
}

Die Sprache, Ausrichtung und TextAngle Eigenschaften darstellen, die erkannte Sprache, die Ausrichtung und Winkel mit dem erkannten Text. Regionen ist ein Array von Objekten der Region. Jede Region stellt Bereiche auf das Bild, die Text enthalten, und die Region besitzt einer Eigenschaft namens Linien, ein Array von Line-Objekten, von denen jedes eine einzelne Textzeile in der Region darstellt. Jede Zeile besitzt eine Eigenschaft namens ausgedrückt, ein Array von Word-Objekte, von denen jedes ein einzelnes Wort in der Zeile darstellt. Dies ist eine etwas komplexe Hierarchie, aber es bietet äußerst genaue Ergebnisse, dass Sie jedes einzelne Wort, die erkennt, die API verwenden können. Vergessen Sie nicht, Gehe zu Definition zu verwenden, um die Definition jeder Klasse untersuchen. Aufgrund dieser Komplexität werden einige Teile der Benutzeroberfläche zur Laufzeit generiert werden. Fügen Sie jetzt in der XAML für die neue Seite, den Code in Abbildung 8, die deklariert wird, einige vertraute steuert (zwei Schaltflächen, ein Bild, ein ActivityIndicator) und einem StackLayout, die die Liste der Zeilen und Wörter erhalten erkannt. Beachten Sie, wie Code auch ein Bezeichnungsfeld-Steuerelement, um die erkannte Sprache angezeigt wird.

Abbildung 8 Optical Character Recognition Vorbereitung der Benutzeroberfläche

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ComputerVisionSample.OcrRecognitionPage">
  <StackLayout Orientation="Vertical">
    <Button x:Name="TakePictureButton" Clicked="TakePictureButton_Clicked"
      Text="Take from camera"/>
    <Button x:Name="UploadPictureButton" Clicked="UploadPictureButton_Clicked"
      Text="Pick a photo"/>
    <ActivityIndicator x:Name="Indicator1" IsVisible="False" IsRunning="False" />
    <Image x:Name="Image1" HeightRequest="240" />
    <StackLayout Orientation="Horizontal">
      <Label Text="Language: "/>
      <Label Text="{Binding Language}"/>
    </StackLayout>
    <ScrollView>
      <StackLayout x:Name="DetectedText">
      </StackLayout>
    </ScrollView>
  </StackLayout>
</ContentPage>

Wie bereits erwähnt, werden einige Teile der Benutzeroberfläche zur Laufzeit erstellt werden. Genauer gesagt muss das Regionen Array, dann die geschachtelten Zeilen, jedes einzelnes Wort in das Array Wörter erkennen durchlaufen werden. Dies wird im dargestellt Abbildung 9, in einem StackLayout für jede Zeile generiert wird.

Abbildung 9 durchlaufen Textbereiche und Linien

private void PopulateUIWithRegions(OcrResults ocrResult)
{
  // Iterate the regions
  foreach (var region in ocrResult.Regions)
  {
    // Iterate lines per region
    foreach (var line in region.Lines)
    {
      // For each line, add a panel
      // to present words horizontally
      var lineStack = new StackLayout
      { Orientation = StackOrientation.Horizontal };
      // Iterate words per line and add the word
      // to the StackLayout
      foreach (var word in line.Words)
      {
        var textLabel = new Label { Text = word.Text };
        lineStack.Children.Add(textLabel);
      }
      // Add the StackLayout to the UI
      this.DetectedText.Children.Add(lineStack);
    }
  }
}

Der restliche Code ist sehr einfach. Zunächst deklarieren Sie und instanziieren Sie die VisionServiceClient-Klasse wie folgt:

private readonly VisionServiceClient visionClient;
public OcrRecognitionPage()
{
  InitializeComponent();
  this.visionClient =
    new VisionServiceClient("YOUR-KEY-GOES-HERE");
}

Natürlich können Sie den gleichen Schlüssel, den Sie zuvor verwendet. Als Nächstes können Sie beide in gezeigten Ereignishandler wiederverwenden Abbildung 6, müssen Sie die folgenden Zeilen zu ersetzen:

var analysisResult = await AnalyzePictureAsync(
  file.GetStream());
this.BindingContext = analysisResult;

mit den folgenden neuen Zeilen:

var ocrResult = await AnalyzePictureAsync(
  file.GetStream());
this.BindingContext = ocrResult;
PopulateUIWithRegions(ocrResult);

Auf diese Weise können Sie die OcrResults-Instanz an die Benutzeroberfläche binden, und klicken Sie dann generiert die Methode PopulateUIWithRegions neue Zeilen mit dem erkannten Text. Der Einfachheit halber statt implementieren Seitennavigation können Sie einfach die Startseite in der Datei "App.Xaml.cs"-Konstruktor wie folgt ändern:

MainPage = new OcrRecognitionPage();

Nun die Anwendung erneut aus, wählen Sie Ihre bevorzugten Emulator oder Gerät. Wenn Sie ein Bild oder auswählen, Sie werden, lesen den Text, der es gedruckt wird, siehe Abbildung 10.

Ausführen von Optical Character Recognition in einem Bild
Abbildung 10 Optical Character Recognition in einem Bild ausführen

In diesem Fall wird die Beispiel-app auf Android-Emulator ausgeführt. Beachten Sie, wie die Sprache ordnungsgemäß als Englisch (En) erkannt wurde. Es ist sehr wichtig zu beachten, dass der Dienst OCR mit qualitativ hochwertige Bilder. Wenn Auflösung schlecht ist, das Bild verschwommen ist oder sie handschriftlichen oder kursive Text enthält, könnte der Dienst eine falsche Ergebnis zurückgeben. Es ist auch erwähnenswert, dass der OCR-Dienst auch Bilder bei mehreren Hintergrundfarben, nicht nur eine Volltonfarbe Wörter erkennen kann. Beispielsweise können Sie Text über dem Bild mit einem Sonnenuntergang analysieren.

Suchen von Promis mit einer Domain-Specific-Modell

Im ersten Teil des Artikels erläutert ich, was der Computer Vision-APIs bieten, um ein Bild zu beschreiben. Beschreibung ist etwas, das auf einer sehr hohen Ebene geschieht und gibt allgemeine Informationen aus einem Bild. Microsoft arbeitet auch spezielle Erkennung über die so genannte domänenspezifische Modelle anzubieten. Diese ermöglichen die Rückgabe von Informationen aus einem Bild, die mit einer Beschreibung des Abbilds kombiniert werden können. Zum Zeitpunkt dieses Artikels ist das nur domänenspezifische verfügbar Promi ggf Anerkennung. Mithilfe dieses Modells können Sie die Nutzen der Computer Vision APIs Promis in einem Bild zu erkennen. Im Allgemeinen können Sie mit einem Modell spezielle Analyse über bestimmte Kategorien von Images ausführen. So wird mein Beispiel nächsten und letzten Promis innerhalb Bilder erkennen. Copyright Gründen können nicht prominenter es auch Bilder angezeigt, aber Sie haben ein Problem mit dem Testen des Codes. Beginnen wir mit der PCL-Projekt namens CelebrityRecognitionPage eine neue XAML-Seite hinzugefügt. Finden Sie im vorherigen Abschnitt für die erforderlichen Schritte zum Hinzufügen einer Seite. Die Benutzeroberfläche für diese Seite ist sehr einfach: Es muss lediglich den Namen prominenter es auch in eine Bezeichnung anzuzeigen und, natürlich haben sie die Möglichkeit der üblichen Elemente der Benutzeroberfläche, siehe Abbildung 11.

Abbildung 11: Vorbereiten der Benutzeroberfläche für die Erkennung von Promi ggf

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ComputerVisionSample.CelebrityRecognitionPage">
  <StackLayout Orientation="Vertical">
    <Button x:Name="TakePictureButton" Clicked="TakePictureButton_Clicked"
      Text="Take from camera"/>
    <Button x:Name="UploadPictureButton" Clicked="UploadPictureButton_Clicked"
      Text="Pick a photo"/>
    <ActivityIndicator x:Name="Indicator1" IsVisible="False" IsRunning="False" />
    <Image x:Name="Image1" HeightRequest="240" />
    <Label x:Name="CelebrityName"/>
  </StackLayout>
</ContentPage>

Prominenter es auch Anerkennung erfolgt mithilfe einer Methode aus der VisionServiceClient-Klasse, die als AnalyzeImageInDomainAsync bezeichnet. Diese Methode muss mithilfe der Bild-Stream oder URL und die domänenspezifische Modell für die Erkennung. Sie können die Liste der verfügbaren Modelle durch Aufrufen der VisionServiceClient.ListModelsAsync abrufen. Wie bereits erwähnt, ist nur das Promi ggf anerkennungsmodell verfügbar im Moment. Der folgende Code zeigt, wie beim Abrufen der Liste der Modelle und ein bestimmtes Modell:

private async Task<Model> GetDomainModel()
{
  ModelResult modelResult = await visionClient.ListModelsAsync();
  // At this writing, only celebrity recognition
  // is available. It is the first model in the list
  return modelResult.Models.First();
}

Im nächste Schritt wird der Code, der Erkennung, wie die folgende benutzerdefinierte Methode namens AnalyzePictureAsync durchführt:

private async Task<AnalysisInDomainResult> AnalyzePictureAsync(Stream inputFile)
{
  if (!CrossConnectivity.Current.IsConnected)
  {
    await DisplayAlert("Network error",
      "Please check your network connection and retry.", "OK");
    return null;
  }
  AnalysisInDomainResult analysisResult =
    await visionClient.AnalyzeImageInDomainAsync(inputFile, await GetDomainModel());
  return analysisResult;
}

Das Ergebnis der Image-Analyse ist ein Objekt vom Typ AnalysisInDomainResult mit der folgenden Definition:

public class AnalysisInDomainResult
{
  public AnalysisInDomainResult();
  public Metadata Metadata { get; set; }
  public Guid RequestId { get; set; }
  public object Result { get; set; }
}

Die Result-Eigenschaft enthält, das tatsächliche Ergebnis der Erkennung. Wie Sie sehen können, ist es vom Typ System.Object, d. h. es die unformatierte Daten enthält. Genauer gesagt, speichert Ergebnis die JSON-Antwort von dem Computer Vision-Dienst zurückgegeben. Abhängig von der Anzahl der Promis erkannt JSON-OBJEKT kann sehr komplex sein, und dies ist der Grund, dass es sich um ein Objekt anstelle eines spezifischen Typs ist. Es definiert im Wesentlichen ein Array von Elementen, mit dem Namen prominenter es auch, die Größe des Rechtecks Gesicht und ein Wert, der die Genauigkeit des Ergebnisses darstellt. Beispielsweise enthält das Ergebnis ein prominenter es auch, die JSON sieht etwa wie im folgenden (CelebrityName, in dem für den Namen der tatsächlichen prominenter es auch steht):

{"celebrities": [
  {
    "name": "CelebrityName",
    "faceRectangle": {
      "left": 169,
      "top": 148,
      "width": 186,
      "height": 186
    },
    "confidence": 0.9064959
  }
]}

JSON mehrere Promis enthält, können Sie sich vorstellen, wie komplex es sein kann. Daher ist ein wichtiges Problem hier lösen den Namen prominenter es auch vom Objekttyp abgerufen. Dies kann erfolgen, mithilfe der beliebten Newtonsoft.Json-Bibliothek, die eine Abhängigkeit von der Bibliothek Microsoft.ProjectOxford.Vision und, daher ist bereits in der PCL-Projekt verfügbar. Die Bibliothek stellt ein Objekt namens "jobject", aus der Netwonsoft.Json.Linq-Namespace ermöglicht die Analyse von JSON-Markup in einem System.Object geschachtelt mit einer Methode namens Analyse gespeichert werden. Sie können das Ergebnis als eine JSON-Zeichenfolge behandelt und das gewünschte Element mit einem Index abgerufen. Die folgende Methode zeigt, wie ein prominenter es auch aus dem Ergebnis abrufen:

private string ParseCelebrityName(object analysisResult)
{
  JObject parsedJSONresult = JObject.Parse(analysisResult.ToString());
  var celebrities = from celebrity in parsedJSONresult["celebrities"]
                    select (string)celebrity["name"];
  return celebrities.FirstOrDefault();
}

In diesem Fall gehe ich davon aus, dass ein Bild enthält nur ein prominenter es auch, damit der Code "FirstOrDefault" über das Ergebnis der LINQ-Abfrage ruft, aber Sie können mit dem Abfrageergebnis an, wie viele Promis erkannt wurden. Der nächste Schritt ist deklarieren und instanziieren die Klasse VisionServiceClient erneut mit dem geheimen Schlüssel:

private readonly VisionServiceClient visionClient;
public CelebrityRecognitionPage()
{
  InitializeComponent();
  this.visionClient = new VisionServiceClient("YOUR-KEY-GOES-HERE");
}

An diesem Punkt können Sie die beiden-Ereignishandler für die Schaltflächen Clicked Ereignis hinzufügen. Sie können immer noch den Code in wiederverwenden Abbildung 6, ersetzen die folgende Zeile direkt:

this.BindingContext = analysisResult;

mit der folgenden Zeile:

this.CelebrityName.Text = ParseCelebrityName(analysisResult.Result);

Sie können nun die Anwendung testen, indem Sie ein Bild von Ihrer bevorzugten prominenter es auch auswählen, wie die Computer Vision-APIs für das genaue Ergebnis zurückgeben.

Zusammenfassung

Die Computer Vision APIs öffnen Sie eine unglaubliche Anzahl an neue Chancen, und sie bieten eine ganz einfache Möglichkeit zum Beschreiben der Welt mit Ihrer app auf einer beliebigen Plattform und auf jedem Gerät. Auf der Konferenz Build 2016 präsentiert Microsoft die sehen AI-Projekt basierend auf mehreren kognitiven-Dienste, einschließlich Computer Vision, die in einem kurzen Video präsentiert wird, die Sie erhalten eine realistische Vorstellung was Sie tun können. Sehen Sie sich unter bit.ly/1qk5ZkJ.


Alessandro Del Sole ist seit 2008 ein Microsoft MVP. Er wurde bereits fünf Mal als MVP des Jahres ausgezeichnet und ist der Autor zahlreicher Bücher, eBooks, Videoanleitungen und Artikel zur .NET-Entwicklung mit Visual Studio. Del Sole gilt International ein Experte für Visual Studio, Windows Presentation Foundation und Visual Basic-Autorität sowie arbeitet er als eine Lösung Developer Experten für Gehirn Sys (www.brain-sys.it), auf die .NET-Entwicklung, training und Beratung fokussierende. Sie können ihm auf Twitter folgen: @progalex..

Unser Dank gilt dem folgenden technischen Experten bei Microsoft für die Durchsicht dieses Artikels: James McCaffrey
Dr. James McCaffrey ist in Redmond (Washington) für Microsoft Research tätig. Er hat an verschiedenen Microsoft-Produkten mitgearbeitet, unter anderem an Internet Explorer und Bing. Dr. McCaffrey erreichen Sie unter jammc@microsoft.com.