2016 年 11 月

第 31 卷,第 11 期

此文章由机器翻译。

认知服务 - 通过 Xamarin 和 Microsoft 计算机视觉 API 观察世界

通过 Alessandro Del Del

在我的上一篇文章,我提供了简要介绍了 Microsoft 认知服务,用于描述可用的 RESTful Api,并将展示使用 Xamarin.Forms 和 C# 编写的跨平台应用程序中的字体和情感 Api (msdn.microsoft.com/magazine/mt742868)。在本文中,我将讨论另一组重要的 Api,称为计算机视觉。您需要用于读取上一篇文章中,您在继续此我将假定您熟悉认知服务有关的一些概念,我介绍了,因为之前,因为我将重新使用的某些 NuGet 包和代码段从上一个示例应用程序。也就是说,让我们首先介绍 Microsoft 计算机构想 Api。

计算机构想 Api 入门

计算机构想 Api 允许图像要描述和分析使用自然语言。你可以将图片上载至计算机视觉服务或指向图像 URL,然后便可期待返回完全自然的描述,无需自己构造和格式化描述。还远不止这些。计算机视觉可以对包含文本、 图像执行光学字符识别 (OCR),并且它可以扫描图像来检测正面的名人。与其他服务,如计算机视觉基于机器学习,并且支持其他部分,这意味着您执行 HTTP 请求并返回 JSON 响应。中的 JSON 图 1 显示了在一张图片,来自在正式的文档的响应的计算机视觉分析一段摘录 bit.ly/2a45kQI

图 1 的映像的计算机构想分析结果

{
  "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"
  }
}

如您所见,响应将包含一位名人在该图片,如标记和图片的大小和格式的其他信息的列表中执行的操作的自然语言说明。而这正是只是一些你可以从计算机视觉服务获取的信息。

执行 HTTP 请求肯定工作原理,但作为.NET 开发人员,您可能宁愿使用不同的方法。与面临和情感 Api 中,Microsoft 还提供了可以使用 C# 应用程序,包括.NET 和 Xamarin,这样就可以通过使用面向对象的方法的便利方法调用该服务中的计算机视觉便携式客户端库 (PCL)。我将稍后使用此库。

璹綷计算机构想 Api

与其他认知服务要使用计算机构想 Api 必须注册该服务,并获取要使用在代码中的机密密钥。要实现此目的,只需转到订阅页 (bit.ly/2b2rKDO) 和计算机构想 api 请求新的试用版。图 2 显示你的订阅注册后的显示方式。

正在注册的计算机构想 Api
图 2 正在注册的计算机构想 Api

如您所见,您将获得两个密钥。您需要一个更高版本时就可以编写 C# 代码。

创建 Xamarin.Forms 应用程序并安装 NuGet 包

启动 Visual Studio 2015,并创建新的 Xamarin.Forms 项目使用空白 XAML 应用 (Xamarin.Forms Portable) 项目模板。调用新的项目 ComputerVisionSample 并单击确定。就绪时,请安装以下 NuGet 程序包︰

Microsoft.ProjectOxford.Vision 安装客户端库计算机构想 Api 应用程序,必须向 PCL 项目只安装。

Xam.Plugin.Connectivity Xamarin.Forms 包含插件的连接,而且必须安装到解决方案中的所有项目。它将用于检查网络连接,然后再尝试通过 Internet 发出请求。

Xam.Plugin.Mediacontains 媒体用于 Xamarin.Forms 的插件,并且必须安装到解决方案中的所有项目。它将用来执行和共享代码,而无需编写特定于平台的代码中选择图片。

确保在此情况下,生成解决方案,以便将刷新所有的引用。现在我们来深入讨论计算机构想 Api,分析三个关键方案。

描述分析 Api 使用的图片

计算机视觉客户端库公开一个名为 Microsoft.ProjectOxford.Vision.VisionServiceClient,即对象类可用于将请求发送到该服务,并且公开包含分析结果的属性。在我的目标的所有情况下,将使用此类。第一个方案描述的图片,依据我的意思是获取说明的图片所表示的内容,基于自然,用户可读的语言。服务发回的响应也包含信息,如主导色、 检测到的面、 标记、 图像类型和大小,并且还包含是否图片成人或对象的犯罪的内容。目的是描述图片,VisionServiceClient 类公开两个方法︰ AnalyzeImageAsync 和 DescribeAsync。后者提供了一组较小的信息,并通常用来检索该图片的自然语言说明而 AnalyzeImageAsync 返回更多详细信息。这两种方法将其响应存储到 Microsoft.ProjectOxford.Vision.Contract.AnalysisResult 类型的对象。我将使用 AnalyzeImageAsync 在本文中。此方法具有两个重载,一个接受流和一个接受使 URL 指向图像;这两种重载都需要指定您希望从图片中检索的信息集。此组的信息均由一个值数组表示 Microsoft.ProjectOxford.Vision.VisualFeature 枚举中。在示例应用程序 MainPage.xaml 页中,我将实现的图片说明。图 3 演示如何实现一个详细的分析方法。

图 3 分析的说明的图片

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;           
}

请注意代码如何使用插件的连接以检测网络连接,如我在上一篇文章所述。有三个要点 图 3。第一个点涉及您想要检索的信息。VisualFeature 值的数组包含的信息有可能的最详细的列表,并包括来自 VisualFeature 枚举的值。这些具有很容易理解的名称,包括检测成人和偷内容,图片、 主导色、 自然语言说明、 面、 图像信息和标记的列表的列表类别的列表。我提供了为完整起见,表面值,但我实际用不到此结果因为您可以检索使用面临 API 表面的更多详细的信息。第二个关键之处是调用到 AnalyzeImageAsync,将流发送到该服务与您想要检索的信息的列表,并将响应存储到 AnalysisResult 类型的对象。此类是第三个关键点,在中定义 图 4

图 4 AnalysisResult 类定义

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; }
  }
}

若要查看此定义,用鼠标右键单击代码编辑器中的 AnalysisResult 类型并选择转到定义 (或如果不想保留活动窗口中查看定义)。如您所见,该定义将显示包含所需的信息通过专用的对象的属性。通过使用每个属性类型上的转到定义,您可以了解如何定义每个专用的对象,因此,如何在 (使用数据绑定,例如) 对应用程序中使用它。例如,说明类型的定义如下︰

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

在这里,最重要属性是标题,标题对象的数组。每个标题包含通过其 Text 属性提供对图片的检索到的服务的用户可读说明。成人类定义,如下所示︰

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; }
 }

这是一个更简单的类并公开两个返回如果图片中包含内容成人或对象的犯罪,则为 true 的布尔值属性加上其他两个属性表示该结果的置信度。这在您想要限制内容可用性时特别有用。现在看看颜色类的定义︰

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; }
}

此类用于存储在该图片,如强调文字颜色、 占主导地位的前景色和背景色和主导颜色的数组中检测到的颜色的列表。它还公开一个名为 IsBWImg,bool 类型,它将返回 true,如果图片是黑色和白色的属性。如果想要通过数据绑定用户界面中显示的信息将帮助了解如何定义这些对象和它们公开的属性。我会将它留给您能够浏览 AnalysisResult 使用存储分析信息的其他类的定义。由于它是,AnalysisResult 实例可以是数据绑定到一些 UI 元素可以非常轻松地显示信息和我会谈到这很快。请考虑 图 5, ,其中显示 XAML 定义的示例应用程序的 UI 所需的完整清单。

图 5 图像的描述将 UI 定义

<?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>

用户界面定义两个按钮,一个用于选择从设备和一个用于从照像机上,加上显示的操作正在进行 ActivityIndicator 拍照的图片。Image 控件中显示所选的图片。(我使用这些控件在上一篇文章中,过。) 请注意数据绑定标签控件中的表达方式。例如,可以从 AnalysisResult 实例而不是执行复杂的绑定,Text 属性绑定到 Adult.IsAdultContent 和 Adult.IsRacyContent 直接。同样,您可以检索图片通过直接绑定到由 AnalysisResult.Description 属性公开的标题的集合中的第一个标题对象的 Text 属性的自然语言说明。当然,这是正常如果只有一个标题或只是想要看到的第一个结果。但是,标题可能包含多个标题对象,并且在这种情况下,您可能想要选择一个不同的数据绑定。根据 Color.AccentColor 属性由同一个直接绑定。对于标记,用户界面显示的标记使用 ListView 控件,显示每个标记名称的标签的数据模板的列表。在代码隐藏中,您必须首先实现两个按钮事件处理程序,如中所示 图 6。该代码使用我已经介绍在上一篇文章,因此我不会在此处介绍的媒体插件。

图 6 的按钮单击事件处理程序

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;
}

此处的关键一点是调用 AnalyzePictureAsync 方法,其结果 (AnalysisResult 实例) 分配给作为其数据源页上。这可实现所示的 UI 元素的数据绑定 图 6。然后,您需要声明和实例化 VisionServiceClient 类,如下所示︰

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

请注意,您需要提供一个密钥正在注册的计算机构想 Api 后,您得到的结果。最后,请记住在应用程序的清单中添加适当的权限。例如,通用 Windows 平台 (UWP) 项目所需的 Internet、 网络摄像头和图片库的功能;和 Android 的项目所需的 INTERNET、 相机、 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 权限。现在,您可以在您最喜欢的设备或仿真器上开始应用程序。图 7 显示桌面模式下运行,与所需的信息并将该映像的 UWP 版本。

描述与计算机构想 Api 的图片
图 7 描述与计算机的图片意向 Api

在所有可用的信息,您将可能很最少受 AnalysisResult 类,该类提供的自动生成的、 用户可读说明不费吹灰之力的 Description 属性的内容。

从具有 OCR 图片中检索文本

OCR 是图像的文本的电子转换为可编辑的文本。大多数扫描仪附带 OCR 软件,它们允许您制作从包含文本,如杂志的页面的图像的可编辑文档。组的计算机构想 Api 提供了 OCR 服务,可以检索图像,无论文本的语言中的文本。OCR 基本上可导致字符串对象。若要了解 OCR Api 的工作原理,让我们向 PCL 项目中添加新的 XAML 页面。在解决方案资源管理器中右击 ComputerVisionSample (可移植) 项目,选择添加 |新的项,然后在添加新项对话框中,选择窗体 Xaml 页面项可用于跨平台节点。调用新窗口中 OcrRecognitionPage。VisionServiceClient 类会公开一个名为 RecognizeTextAsync,后者将在图像上执行 OCR 方法。此方法接受指向图像的 URL 或流,并可以选择指定语言。如果未指定一种语言,RecognizeTextAsync 将尝试自动检测语言。它返回类型 Microsoft.ProjectOxford.Vision.Contract.OcrResults,这是有点复杂,并且需要进行详细说明的对象。现在,请考虑下面的代码,也不能通过流调用 OCR 服务自动检测的语言︰

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;
}

请注意如何您始终检查网络连接第一次。如果您想要指定一种语言,您将传递给 RecognizeTextAsync RecognizeLanguage 类的实例,如下所示︰

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

在 WPF 的正式示例应用程序 bit.ly/2ahHum3 显示支持的语言和代码的完整列表。OcrResults 类定义,如下所示︰

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; }
}

语言、 方向和 TextAngle 属性表示检测到的语言、 方向和已识别文本的角度。区域是区域对象的数组。每个区域表示包含文本,在图像上的区域,区域类型具有名行,行对象的数组为每个代表单个区域中的文本行的属性。每个行对象具有名的单词,Word 对象的数组为每个代表单个单词在行中的属性。这是一个稍微复杂的层次结构,但它提供了非常准确的结果,因为您可以使用该 API 检测到每个单词。不要忘记将转到定义用于调查每个类的定义。由于这种复杂性,将在运行时生成用户界面中的某些部分。现在,在新页上,为 XAML 中添加的代码中所示 图 8, ,它声明了某些熟悉控制 (两个按钮,图像、 ActivityIndicator),并将收到的线路和单词列表 StackLayout 检测到。请注意该代码如何还将添加一个标签控件来显示检测到的语言。

图 8 准备光学字符识别的用户界面

<?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>

正如我提到,将在运行时构造用户界面中的某些部分。更具体地说,我需要迭代区域数组,则其嵌套行的数组,以检测每个单词的单词数组中。说明了这一点 图 9, ,其中的每一行生成 StackLayout。

图 9 循环文本区域和行

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);
    }
  }
}

其余代码就非常简单。首先,声明并实例化 VisionServiceClient 类,如下所示︰

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

当然可以使用以前使用的同一个密钥。接下来,您可以重复使用中所示这两个事件处理程序 图 6, ,您需要将以下行︰

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

具有以下新行︰

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

这样做之后,可以将 OcrResults 实例绑定到 UI,然后 PopulateUIWithRegions 方法将生成检测到的文本将以新行。为简单起见,而不是实现页面导航,您可以只需更改在 App.xaml.cs 构造函数中的启动页,如下所示︰

MainPage = new OcrRecognitionPage();

现在重新启动应用程序,通过选择您最喜欢的仿真程序或设备。如果您选择或拍摄一张照片,您将能够读取它,打印的文本中所示 图 10

对图像执行光学字符识别
图 10 对图像执行光学字符识别

在这种情况下,在 Android 仿真器上运行示例应用程序。请注意如何语言已被正确地检测出英语 (en)。它是非常重要,请注意 OCR 服务适用于高质量的图像。如果图像分辨率较差、 模糊的图像,或它包含手写或自然手写体文本,该服务可能返回不准确的结果。它还是值得一提的 OCR 服务能够检测甚至多彩色背景,而不仅仅是一种纯色的图像的单词。例如,您可以通过停用的图片分析文本。

查找与特定于域的模型的名人

在文章的第一部分,我介绍了计算机构想 Api 提供用于描述图像。说明是指发生在非常高的级别,并且从映像中返回的一般信息。Microsoft 还致力于提供专门的识别通过所谓的特定于域的模型。这些行为允许从映像,它可以与图像说明结合返回非常具体的信息。在撰写本文时,可仅特定于域模型是名人识别。通过使用此模型,您可以利用计算机构想 Api 来检测中图片的名人。通常情况下,使用模型可以通过特定类别的图像执行专用的分析。因此我的下一步和最后一个示例就明确名人图片内。我不能让名人图片的版权原因,但不会产生测试代码的任何问题。让我们首先将新的 XAML 页面添加到名为 CelebrityRecognitionPage 的 PCL 项目。请参阅上一节添加页所需的步骤。此页的 UI 是非常简单︰ 它只需在标签中显示的名人名称,当然,它将提供的常用的 UI 元素,如中所示 图 11

图 11 准备名人识别的用户界面

<?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>

使用一种方法从名为 AnalyzeImageInDomainAsync VisionServiceClient 类执行名人识别。此方法要求使用的图像流或 URL 以及特定于域的模型进行检测。您可以通过调用 VisionServiceClient.ListModelsAsync; 检索可用模型列表尽管我已经提到,只有名人识别模型是此时中。下面的代码演示如何检索模型和一个特定模型的列表︰

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();
}

下一步是执行识别,如下面的自定义方法调用 AnalyzePictureAsync 中所示的代码︰

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;
}

图像分析的结果是类型 AnalysisInDomainResult 替换为以下定义的对象︰

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

Result 属性包含识别的实际结果。如您所见,它属于类型 System.Object,这意味着它包含原始数据。更具体地说,结果将存储通过计算机视觉服务返回的 JSON 响应。根据检测到的名人的数量,此 JSON 可能会非常复杂,并且这是它是而不是更特殊类型的对象的原因。它基本上是定义一组项,每个包含名人名称、 面临矩形大小和一个值,表示结果的准确性。例如,如果结果包含一个名人,JSON 将类似于以下 (其中 CelebrityName 代表真实名人名称)︰

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

如果 JSON 包含多个名人,您可以想象多么复杂它可以是。因此要此处解决重要问题从一种对象类型中检索名人名称。这可以通过使用常用的 Newtonsoft.Json 库,也不能是 Microsoft.ProjectOxford.Vision 库的依赖项,因此,已在 PCL 项目中可用。库提供了一个称为 JObject,Netwonsoft.Json.Linq 命名空间,它允许分析 JSON 标记存储到 System.Object 内部具有一个名为分析方法中的对象。然后可以将结果视为一个 JSON 字符串,并检索其索引所需的元素。下面的方法演示如何从分析结果检索名人名称︰

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();
}

在这种情况下,我假定图片包含只能有一个名人,因此该代码调用 FirstOrDefault LINQ 查询的结果,但您可以使用要看到多少名人已检测到的查询结果。下一步是声明和使用的机密密钥再次实例 VisionServiceClient 类︰

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

此时,您可以添加的两个事件处理程序按钮 Clicked 事件。您仍可以重用中的代码 图 6, ,只需替换以下行︰

this.BindingContext = analysisResult;

替换为以下行︰

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

您现在可以通过选择您最喜欢的名人图形时,测试应用程序并查看如何计算机构想 Api 返回的具体结果。

总结

计算机构想 Api 打开许多令人难以置信的新的机会,并提供一种描述世界中,使用您的应用程序,在任何平台上和在任何设备上非常简单方法。在生成 2016年大会上,Microsoft 提供基于多个认知服务,包括短视频,使您可以执行哪些操作的现实认知中展示的计算机视觉看到 AI 项目。观看在 bit.ly/1qk5ZkJ


Alessandro Del Sole自 2008 年起被评为 Microsoft MVP。他已经 5 次获得年度 MVP 这一殊荣,发表过很多关于 Visual Studio .NET 开发的书籍、电子书、指导视频和文章。Visual Studio 专家、 Windows Presentation Foundation 和 Visual Basic 颁发机构,国际上被视为 Del Sole 加上他现任大脑 Sys 的解决方案开发人员专家 (www.brain-sys.it)、 聚焦对.NET 开发、 培训和咨询服务。你可以关注他的 Twitter @progalex

衷心感谢以下 Microsoft 技术专家对本文的审阅: James McCaffrey
ScriptoJames McCaffrey 供职于华盛顿地区雷蒙德市沃什湾的 Microsoft Research。他参与过多个 Microsoft 产品的工作,包括 Internet Explorer 和 Bing。Scripto可通过 jammc@microsoft.com 与 McCaffrey 取得联系。