65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Azure Cognitive Services 进行实时情感检测

2019 年 4 月 15 日

CPOL

6分钟阅读

viewsIcon

6374

在基于 .NET Core 的应用程序中集成 Cognitive Services SDK

随着云托管解决方案作为服务(as-a-service)模式的兴起,组织倾向于为他们的现代应用程序购买订阅,以支持客户和用户的核心需求。这样做的目的是,他们可以忽略与这些服务相关的管理、开发和运营成本。Azure Cognitive Services 就是这样一项服务,它提供了最先进的机器学习(ML)解决方案,并使开发人员能够快速地在其应用程序中添加智能组件。在本文中,我将演示如何将 Cognitive Services SDK 集成到基于 .NET Core 的应用程序中,并探讨如何使用 Microsoft 提供的 ML 服务来解决现实世界中的场景。

Cognitive Services 以 PaaS 组件的形式提供,您可以在其之上编写自己的应用程序。Cognitive Services 包括一个情感 API (Emotion API),可用于检测图像中人物的情感,并将其标记为已知的几种情感,如快乐、悲伤、愤怒等。由于 Cognitive Services 是由 Microsoft 训练的一系列 ML/AI 模型。Azure 使用这些 ML 模型来处理您的输入,然后返回一个包含情感和情感置信度的响应。置信度表明 Cognitive Services 认为结果有多准确。因此,您无需训练和发布自己的 ML 模型,就可以利用 Azure Cognitive Services 中 Microsoft 训练和发布的模型。

目前,这项服务已被整合到人脸 API (Face API) 中,并且 SDK 将会更新以支持人脸 API 的情感检测。我将使用人脸 API 来检测照片中的情感,并演示如何扩展 SDK 本身来编写自己的帮助函数来解析响应并生成 UI。

环境设置

我假设您已经拥有 Azure 订阅,并且已经安装和配置了 .NET Core 以及 Xamarin(如果您也想探索 Android 示例)。在 Azure 门户中,搜索“Face”,然后在“AI”类别下选择 Microsoft 的“Face”解决方案。在“创建”选项卡中,输入名称,然后选择订阅和定价层。由于我们只是测试,您可以选择任何位置(生产用途,请阅读“结论”部分)。此外,对于“资源组”,请命名为“Emotion-Detection-RG”。

您还可以使用 Docker 容器来部署 Azure Cognitive Services,并自行托管这些实例。为了快速上手,我建议使用 Azure 作为托管服务,而不是 Docker 替代方案。

与 .NET Core 集成

首先,我将演示如何在常见的 .NET Core 应用程序中使用人脸 API SDK。这将帮助您继续在 Xamarin 应用程序中集成 SDK。

通过终端或您喜欢的 IDE 创建一个新的 .NET Core 应用程序。

接下来,将 NuGet 包“Microsoft.Azure.CognitiveServices.Vision.Face”安装到项目中。例如,您可以在 NuGet 包管理器控制台中执行以下命令:

PM> Install-Package Microsoft.Azure.CognitiveServices.Vision.Face
-Version 2.2.0-preview

在此部分,我将使用离线图像文件并检测该图片中的情感。使用的代码非常简单:

static async Task detectEmotion(string filepath)
{
    using (var client = new FaceClient(
        new ApiKeyServiceClientCredentials("<your-face-api-key-here>"),
        new System.Net.Http.DelegatingHandler[] { }))
    {
        client.Endpoint = faceEndpoint;

        using (var filestream = File.OpenRead(filepath))
        {
            var detectionResult = await client.Face.DetectWithStreamAsync
                                  (filestream, returnFaceId: true, 
                                  returnFaceAttributes: emotionAttribute, 
                                  returnFaceLandmarks: true);
            foreach (var face in detectionResult)
            {
                Console.WriteLine(JsonConvert.SerializeObject
                                 (face.FaceAttributes.Emotion));
                var highestEmotion = getEmotion(face.FaceAttributes.Emotion);
                Console.WriteLine($"This face has emotional traits of 
                {highestEmotion.Emotion} ({highestEmotion.Value} confidence).");
            }
        }
    }
}

在此代码中,我传入文件路径,程序读取文件并将文件作为流发送到 Azure,在那里进行处理和分析。请注意,其中大多数对象都是 .NET Core 的原生类型,并支持原生的 .NET Framework 功能,如 async/await。

我省略了 faceEndpoint 和 emotionAttribute 变量,因为它们在代码中是可访问的并且相当自明。

由于 SDK 不提供内置方法来了解哪个情感最高,我编写了一个帮助函数来检测最高情感的值。

static (string Emotion, double Value) getEmotion(Emotion emotion)
{
    var emotionProperties = emotion.GetType().GetProperties();
    (string Emotion, double Value) highestEmotion = ("Anger", emotion.Anger);
    foreach (var e in emotionProperties)
    {
        if (((double)e.GetValue(emotion, null)) > highestEmotion.Value)
        {
            highestEmotion.Emotion = e.Name;
            highestEmotion.Value = (double)e.GetValue(emotion, null);
        }
    }
    return highestEmotion;
}

在此代码中,我使用 C# 元组来返回最高情感以及与之关联的置信度值。利用反射(因为 JSON 响应现在是以运行时对象的形式出现的),我正在读取情感值列表并捕获这些值的最大值。然后使用此最大值来呈现输出。稍后我也会在 Xamarin 应用中使用此函数。

main 函数中的代码仅调用此函数并等待按键输入以继续,如下所示:

现在,让我们将此模块添加到 Xamarin 应用程序中,以检测所拍照片的情感。

为原生 Xamarin 应用添加情感功能

在 Xamarin.Forms 应用程序中,我创建了一个允许用户拍照的页面。Xam.Plugin.Media 是一个开源的中间件,支持跨平台相机捕获功能。您可以按照此 GitHub 指南,将该包集成到您自己的 Xamarin 应用中。

集成后,您只需:

  • 从 .NET Core 应用程序复制用于人脸 API 集成的代码。
  • 编写代码来捕获图像并将其转发给人脸 API 对象以检测情感。

为了简单起见,并保持一定的单一职责,我创建了一个单独的类来完成这项工作。代码与上面共享的代码类似,所以我们不再重复添加该代码。现在在主页面,这是捕获图像然后将其转发给 Azure 进行分析的代码:

private async Task captureBtn_Clicked(object sender, EventArgs e)
{
    if (await CrossMedia.Current.Initialize())
    {
        if (CrossMedia.Current.IsCameraAvailable)
        {
            // 50% compression and a unique file name.
            var file = await CrossMedia.Current.TakePhotoAsync
                       (new Plugin.Media.Abstractions.StoreCameraMediaOptions 
                       { Name = Guid.NewGuid().ToString(), CompressionQuality = 50 });
            if (file == null)
            {
                await DisplayAlert("Cannot capture", 
                "We cannot store the file in the system, 
                 possibly permission issues.", "Okay");
            }
            else
            {
                // Load the image in view
                emotionResults.Text = "Processing the image...";
                imageView.Source = ImageSource.FromStream(() =>
                {
                    return file.GetStream();
                });

                await processImage(file);
            }
        }
        else
        {
            await DisplayAlert("Cannot select picture", 
            "Your device needs to have a camera, 
            or needs to support photo selection.", "Okay");
        }
    }
    else
    {
        await DisplayAlert("Problem", 
                           "Cannot initialize the low-level APIs.", "Okay");
    }
}

成功生成并运行在 Android 设备上后,获得了以下结果:

您可以捕获图像并将其发送到服务器进行分析和检测图像流中用户的表情 — 或者您可以选择更高级的路径,使用 Azure Cognitive Services 的流式服务来分析图像流,这几乎可以实现零延迟。

清理资源

完成后,通常最好清理 Azure 平台上的所有资源,以免产生不必要的费用。如果您按照本文的指示操作,那么您将有一个名为“Emotion-Detection-RG”的单个资源组,您可以找到并删除该资源,以快速删除本文中创建的所有内容。

结论

在本文中,我们讨论了将 Azure Cognitive Services 整合到应用程序中以添加最先进的机器学习情感感应功能的快速和简便性。我讨论了如何利用 Azure Cognitive Services 的人脸 API 来为我们的 Xamarin 应用程序或更普遍的 .NET Core 应用程序添加情感检测功能。

在开发基于 Cognitive Services 的生产软件时,您应该考虑一些最佳实践:

  • 您的终结点密钥不得向外部用户公开。您应该考虑始终将其保存在安全的地方,例如 Azure Key Vault,或使用代理应用程序作为中间件。
  • 您的 Cognitive Service 可能有配额限制,因此请将代码放在 try…catch 或类似块中,以处理 Azure 因配额违规而拒绝您请求的情况。
  • 由于 Azure Cognitive Services 在全球不同区域都有提供,请考虑使用离用户最近的实例,以减少延迟。

在 Microsoft Azure 上,您拥有自己的数据,并遵守欧洲的 GDPR 法规,您可以要求 Microsoft 删除用户在使用服务时生成的数据。

历史

  • 2019 年 4 月 15 日:初始版本
© . All rights reserved.