使用Azure人脸API对图片进行人脸识别

前端之家收集整理的这篇文章主要介绍了使用Azure人脸API对图片进行人脸识别前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

人脸识别是人工智能机器学习比较成熟的一个领域。人脸识别已经应用到了很多生产场景。比如生物认证,人脸考勤,人流监控等场景。对于很多中小功能由于技术门槛问题很难自己实现人脸识别的算法。Azure人脸API对人脸识别机器学习算法进行封装提供REST API跟SDK方便用户进行自定义开发。

Azure人脸API可以对图像中的人脸进行识别,返回面部的坐标、性别、年龄、情感、愤怒还是高兴、是否微笑,是否带眼镜等等非常有意思的信息。
Azure人脸API也是一个免费服务,每个月30000次事务的免费额度。

创建人脸服务

a0K5lt.png


填写实例名,选择一个区域,同样选离你近的。

获取秘钥跟终结点

a0KH0S.png


选中侧边菜单“秘钥于终结点”,获取信息,这2个信息后面再sdk调用中需要用到。

新建WPF应用

新建一个WPF应用实现以下功能

  1. 选择图片后把原图显示出来
  2. 选中后马上进行识别
  3. 识别成功后把脸部用红框描述出来
  4. 当鼠标移动到红框内的时候显示详细脸部信息

安装SDK

使用nuget安装对于的sdk包:

  1. Install-Package Microsoft.Azure.CognitiveServices.Vision.Face -Version 2.5.0-preview.2

实现界面

编辑MainWindow.xml放置图像显示区域、文件选中、描述显示区域

  1. <Window x:Class="FaceWpf.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:FaceWpf"
  7. mc:Ignorable="d"
  8. Title="MainWindow" Height="600" Width="800">
  9. <Grid x:Name="BackPanel">
  10. <Image x:Name="FacePhoto" Stretch="Uniform" Margin="0,50" MouseMove="FacePhoto_MouseMove" />
  11. <DockPanel DockPanel.Dock="Bottom">
  12. <Button x:Name="BrowseButton" Width="72" Height="80" VerticalAlignment="Bottom" HorizontalAlignment="Left"
  13. Content="选择图片..."
  14. Click="BrowseButton_Click" />
  15. <StatusBar VerticalAlignment="Bottom">
  16. <StatusBarItem>
  17. <TextBlock Name="faceDescriptionStatusBar" Height="80" FontSize="20" Text="" Width="500" TextWrapping="Wrap"/>
  18. </StatusBarItem>
  19. </StatusBar>
  20. </DockPanel>
  21. </Grid>
  22. </Window>

构造函数

在编辑MainWindow类的构造函数初始化FaceClient等数据

  1. private IFaceClient _faceClient;
  2. //检测到的人脸
  3. private IList<DetectedFace> _faceList;
  4. //人脸描述信息
  5. private string[] _faceDescriptions;
  6. private double _resizeFactor;
  7. private const string _defaultStatusBarText =
  8. "鼠标移动到面部显示描述信息.";
  9. public MainWindow()
  10. {
  11. InitializeComponent();
  12. //faceid的订阅key
  13. string subscriptionKey = "";
  14. // faceid的终结的配置
  15. string faceEndpoint = "";
  16. _faceClient = new FaceClient(
  17. new ApiKeyServiceClientCredentials(subscriptionKey),new System.Net.Http.DelegatingHandler[] { });
  18. if (Uri.IsWellFormedUriString(faceEndpoint,UriKind.Absolute))
  19. {
  20. _faceClient.Endpoint = faceEndpoint;
  21. }
  22. else
  23. {
  24. MessageBox.Show(faceEndpoint,"Invalid URI",MessageBoxButton.OK,MessageBoxImage.Error);
  25. Environment.Exit(0);
  26. }
  27. }

图片选择并显示

  1. // 选择图片上传
  2. private async void BrowseButton_Click(object sender,RoutedEventArgs e)
  3. {
  4. var openDlg = new Microsoft.Win32.OpenFileDialog();
  5. openDlg.Filter = "JPEG Image(*.jpg)|*.jpg";
  6. bool? result = openDlg.ShowDialog(this);
  7. if (!(bool)result)
  8. {
  9. return;
  10. }
  11. // Display the image file.
  12. string filePath = openDlg.FileName;
  13. Uri fileUri = new Uri(filePath);
  14. BitmapImage bitmapSource = new BitmapImage();
  15. bitmapSource.BeginInit();
  16. bitmapSource.CacheOption = BitmapCacheOption.None;
  17. bitmapSource.UriSource = fileUri;
  18. bitmapSource.EndInit();
  19. FacePhoto.Source = bitmapSource;
  20. // Detect any faces in the image.
  21. Title = "识别中...";
  22. _faceList = await UploadAndDetectFaces(filePath);
  23. Title = String.Format(
  24. "识别完成. {0}个人脸",_faceList.Count);
  25. if (_faceList.Count > 0)
  26. {
  27. // Prepare to draw rectangles around the faces.
  28. DrawingVisual visual = new DrawingVisual();
  29. DrawingContext drawingContext = visual.RenderOpen();
  30. drawingContext.DrawImage(bitmapSource,new Rect(0,bitmapSource.Width,bitmapSource.Height));
  31. double dpi = bitmapSource.DpiX;
  32. // Some images don't contain dpi info.
  33. _resizeFactor = (dpi == 0) ? 1 : 96 / dpi;
  34. _faceDescriptions = new String[_faceList.Count];
  35. for (int i = 0; i < _faceList.Count; ++i)
  36. {
  37. DetectedFace face = _faceList[i];
  38. //画方框
  39. drawingContext.DrawRectangle(
  40. Brushes.Transparent,new Pen(Brushes.Red,2),new Rect(
  41. face.FaceRectangle.Left * _resizeFactor,face.FaceRectangle.Top * _resizeFactor,face.FaceRectangle.Width * _resizeFactor,face.FaceRectangle.Height * _resizeFactor
  42. )
  43. );
  44. _faceDescriptions[i] = FaceDescription(face);
  45. }
  46. drawingContext.Close();
  47. RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(
  48. (int)(bitmapSource.PixelWidth * _resizeFactor),(int)(bitmapSource.PixelHeight * _resizeFactor),96,PixelFormats.Pbgra32);
  49. faceWithRectBitmap.Render(visual);
  50. FacePhoto.Source = faceWithRectBitmap;
  51. faceDescriptionStatusBar.Text = _defaultStatusBarText;
  52. }
  53. }

调用SDK进行识别

指定需要识别的要素,调用sdk进行图像识别

  1. // 上传图片使用faceclient识别
  2. private async Task<IList<DetectedFace>> UploadAndDetectFaces(string imageFilePath)
  3. {
  4. IList<FaceAttributeType> faceAttributes =
  5. new FaceAttributeType[]
  6. {
  7. FaceAttributeType.Gender,FaceAttributeType.Age,FaceAttributeType.Smile,FaceAttributeType.Emotion,FaceAttributeType.Glasses,FaceAttributeType.Hair
  8. };
  9. using (Stream imageFileStream = File.OpenRead(imageFilePath))
  10. {
  11. IList<DetectedFace> faceList =
  12. await _faceClient.Face.DetectWithStreamAsync(
  13. imageFileStream,true,false,faceAttributes);
  14. return faceList;
  15. }
  16. }

显示脸部的描述

对人脸识别后的结果信息组装成字符串,当鼠标移动到人脸上的时候显示这些信息。

  1. /// <summary>
  2. /// 鼠标移动显示脸部描述
  3. /// </summary>
  4. /// <param name="sender"></param>
  5. /// <param name="e"></param>
  6. private void FacePhoto_MouseMove(object sender,MouseEventArgs e)
  7. {
  8. if (_faceList == null)
  9. return;
  10. Point mouseXY = e.GetPosition(FacePhoto);
  11. ImageSource imageSource = FacePhoto.Source;
  12. BitmapSource bitmapSource = (BitmapSource)imageSource;
  13. var scale = FacePhoto.ActualWidth / (bitmapSource.PixelWidth / _resizeFactor);
  14. bool mouSEOverFace = false;
  15. for (int i = 0; i < _faceList.Count; ++i)
  16. {
  17. FaceRectangle fr = _faceList[i].FaceRectangle;
  18. double left = fr.Left * scale;
  19. double top = fr.Top * scale;
  20. double width = fr.Width * scale;
  21. double height = fr.Height * scale;
  22. if (mouseXY.X >= left && mouseXY.X <= left + width &&
  23. mouseXY.Y >= top && mouseXY.Y <= top + height)
  24. {
  25. faceDescriptionStatusBar.Text = _faceDescriptions[i];
  26. mouSEOverFace = true;
  27. break;
  28. }
  29. }
  30. if (!mouSEOverFace) faceDescriptionStatusBar.Text = _defaultStatusBarText;
  31. }
  1. /// <summary>
  2. /// 脸部描述
  3. /// </summary>
  4. /// <param name="face"></param>
  5. /// <returns></returns>
  6. private string FaceDescription(DetectedFace face)
  7. {
  8. StringBuilder sb = new StringBuilder();
  9. sb.Append("人脸: ");
  10. // 性别年龄
  11. sb.Append(face.FaceAttributes.Gender.Value == Gender.Female ? "女性" : "男性");
  12. sb.Append(",");
  13. sb.Append(face.FaceAttributes.Age.ToString() + "岁");
  14. sb.Append(",");
  15. sb.Append(String.Format("微笑 {0:F1}%,",face.FaceAttributes.Smile * 100));
  16. // 显示超过0.1的表情
  17. sb.Append("表情: ");
  18. Emotion emotionscores = face.FaceAttributes.Emotion;
  19. if (emotionscores.Anger >= 0.1f) sb.Append(
  20. String.Format("生气 {0:F1}%,emotionscores.Anger * 100));
  21. if (emotionscores.Contempt >= 0.1f) sb.Append(
  22. String.Format("蔑视 {0:F1}%,emotionscores.Contempt * 100));
  23. if (emotionscores.Disgust >= 0.1f) sb.Append(
  24. String.Format("厌恶 {0:F1}%,emotionscores.Disgust * 100));
  25. if (emotionscores.Fear >= 0.1f) sb.Append(
  26. String.Format("恐惧 {0:F1}%,emotionscores.Fear * 100));
  27. if (emotionscores.Happiness >= 0.1f) sb.Append(
  28. String.Format("高兴 {0:F1}%,emotionscores.Happiness * 100));
  29. if (emotionscores.Neutral >= 0.1f) sb.Append(
  30. String.Format("自然 {0:F1}%,emotionscores.Neutral * 100));
  31. if (emotionscores.Sadness >= 0.1f) sb.Append(
  32. String.Format("悲伤 {0:F1}%,emotionscores.Sadness * 100));
  33. if (emotionscores.Surprise >= 0.1f) sb.Append(
  34. String.Format("惊喜 {0:F1}%,emotionscores.Surprise * 100));
  35. sb.Append(face.FaceAttributes.Glasses);
  36. sb.Append(",");
  37. sb.Append("头发: ");
  38. if (face.FaceAttributes.Hair.Bald >= 0.01f)
  39. sb.Append(String.Format("秃头 {0:F1}% ",face.FaceAttributes.Hair.Bald * 100));
  40. IList<HairColor> hairColors = face.FaceAttributes.Hair.HairColor;
  41. foreach (HairColor hairColor in hairColors)
  42. {
  43. if (hairColor.Confidence >= 0.1f)
  44. {
  45. sb.Append(hairColor.Color.ToString());
  46. sb.Append(String.Format(" {0:F1}% ",hairColor.Confidence * 100));
  47. }
  48. }
  49. return sb.ToString();
  50. }

运行

到此我们的应用打造完成了。先让我们选择一张结衣的图片试试:

a0lnoD.png


看看我们的结衣微笑率97.9%。

再选一张杰伦的图片试试:

a0l1SA.png


嗨,杰伦就是不喜欢笑,微笑率0% 。。。

总结

通过简单的一个wpf的应用我们演示了如果使用Azure人脸API进行图片中的人脸检测,真的非常方便,识别代码只有1行而已。如果不用C# sdk还可以使用更加通用的rest api来调用,这样可以适配任何开发语言。Azure人脸API除了能对图片中的人脸进行检测,还可以对多个人脸进行比对,检测是否是同一个人,这样就可以实现人脸考勤等功能了,这个下次再说吧。

猜你在找的Azure相关文章