随着现代应用程序对高端客户需求的不断增长,越来越多的企业选择购买订阅服务来减轻管理、开发和运营成本。Azure认知服务正是这样一种服务,它提供了机器学习(ML)的最新解决方案,使开发者能够快速地将智能组件添加到他们的应用程序中。本文将展示如何在基于.NET Core的应用程序中集成认知服务SDK,并探索如何使用微软提供的ML服务解决现实世界的问题。
认知服务作为PaaS组件提供,可以在其上编写自己的应用程序。认知服务包括一个情绪API,可以用来检测图片中人物的情绪,并将其标记为一些已知的情绪,如快乐、悲伤、愤怒等。由于认知服务是由微软训练的一组ML/AI模型,Azure使用这些ML模型处理输入,然后返回一个包含情绪和对该情绪信心的响应。信心显示认知服务认为结果的准确性。因此,无需训练和发布自己的ML模型,而可以利用微软在Azure认知服务中训练和发布的模型。
假设已经拥有Azure订阅,并且已经安装并配置了.NET Core以及Xamarin(如果想探索Android示例)。在Azure门户中,将搜索"Face",并选择微软在AI类别下的"Face"解决方案。在"创建"选项卡中,输入名称,然后选择"订阅"和"定价层"。由于只是测试,可以选择任何位置(对于生产目的,请阅读"结论"部分)。对于资源组,将其命名为"Emotion-Detection-RG"。
也可以使用Docker容器来托管Azure认知服务,并自己托管这些实例。对于快速启动,建议使用Azure作为托管服务,而不是Docker替代方案。
首先,将演示如何在常见的.NET Core应用程序中使用Face 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(""), 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。
由于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.Forms应用程序中,刚刚创建了一个页面,允许用户捕获图片。Xam.Plugin.Media是一个开源中间件,支持跨平台相机捕获功能。可以按照这个GitHub指南将包集成到自己的Xamarin应用程序中。
一旦集成,所需要做的就是:
复制.NET Core应用程序中的Face API集成代码。编写代码捕获图像并将其转发给Face API对象以检测情绪。
为了保持简单,并保持某种单一责任,创建了一个单独的类来为做这件事。代码就像上面分享的那样,所以不会再添加那段代码。现在在主页面中,这是捕获图像然后将其转发给Azure进行分析的代码:
private async Task captureBtn_Clicked(object sender, EventArgs e)
{
if (await CrossMedia.Current.Initialize())
{
if (CrossMedia.Current.IsCameraAvailable)
{
// 50%压缩和唯一文件名。
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
{
// 加载视图中的图像
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认知服务的流媒体服务来分析图像流,这具有几乎零延迟的优势。
一旦完成了这个,通常最好的做法是清理Azure平台上的所有资源,这样就不会产生任何不必要的费用。如果按照文章的步骤,那么有一个名为"Emotion-Detection-RG"的单个资源组,可以找到并删除该资源,以快速删除本文中创建的所有内容。
在本文中,讨论了将Azure认知服务集成到应用程序中以添加最先进的机器学习情绪感知功能是多么快速和容易。讨论了如何利用Azure认知服务的Face API为Xamarin应用程序或更一般地说,为基于.NET Core的应用程序添加情绪检测功能。