博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Azure人脸API对图片进行人脸识别
阅读量:4032 次
发布时间:2019-05-24

本文共 9409 字,大约阅读时间需要 31 分钟。

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

Azure人脸API可以对图像中的人脸进行识别,返回面部的坐标、性别、年龄、情感、愤怒还是高兴、是否微笑,是否带眼镜等等非常有意思的信息。

Azure人脸API也是一个免费服务,每个月30000次事务的免费额度。

创建人脸服务

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

获取秘钥跟终结点

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

新建WPF应用

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

  1. 选择图片后把原图显示出来

  2. 选中后马上进行识别

  3. 识别成功后把脸部用红框描述出来

  4. 当鼠标移动到红框内的时候显示详细脸部信息

安装SDK

使用nuget安装对于的sdk包:

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

实现界面

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

构造函数

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

private IFaceClient _faceClient;        //检测到的人脸        private IList
_faceList; //人脸描述信息 private string[] _faceDescriptions; private double _resizeFactor; private const string _defaultStatusBarText = "鼠标移动到面部显示描述信息."; public MainWindow() { InitializeComponent(); //faceid的订阅key string subscriptionKey = ""; // faceid的终结的配置 string faceEndpoint = ""; _faceClient = new FaceClient( new ApiKeyServiceClientCredentials(subscriptionKey), new System.Net.Http.DelegatingHandler[] { }); if (Uri.IsWellFormedUriString(faceEndpoint, UriKind.Absolute)) { _faceClient.Endpoint = faceEndpoint; } else { MessageBox.Show(faceEndpoint, "Invalid URI", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(0); } }

图片选择并显示

// 选择图片并上传        private async void BrowseButton_Click(object sender, RoutedEventArgs e)        {            var openDlg = new Microsoft.Win32.OpenFileDialog();            openDlg.Filter = "JPEG Image(*.jpg)|*.jpg";            bool? result = openDlg.ShowDialog(this);            if (!(bool)result)            {                return;            }            // Display the image file.            string filePath = openDlg.FileName;            Uri fileUri = new Uri(filePath);            BitmapImage bitmapSource = new BitmapImage();            bitmapSource.BeginInit();            bitmapSource.CacheOption = BitmapCacheOption.None;            bitmapSource.UriSource = fileUri;            bitmapSource.EndInit();            FacePhoto.Source = bitmapSource;            // Detect any faces in the image.            Title = "识别中...";            _faceList = await UploadAndDetectFaces(filePath);            Title = String.Format(                "识别完成. {0}个人脸", _faceList.Count);            if (_faceList.Count > 0)            {                // Prepare to draw rectangles around the faces.                DrawingVisual visual = new DrawingVisual();                DrawingContext drawingContext = visual.RenderOpen();                drawingContext.DrawImage(bitmapSource,                    new Rect(0, 0, bitmapSource.Width, bitmapSource.Height));                double dpi = bitmapSource.DpiX;                // Some images don't contain dpi info.                _resizeFactor = (dpi == 0) ? 1 : 96 / dpi;                _faceDescriptions = new String[_faceList.Count];                for (int i = 0; i < _faceList.Count; ++i)                {                    DetectedFace face = _faceList[i];                    //画方框                    drawingContext.DrawRectangle(                        Brushes.Transparent,                        new Pen(Brushes.Red, 2),                        new Rect(                            face.FaceRectangle.Left * _resizeFactor,                            face.FaceRectangle.Top * _resizeFactor,                            face.FaceRectangle.Width * _resizeFactor,                            face.FaceRectangle.Height * _resizeFactor                            )                    );                    _faceDescriptions[i] = FaceDescription(face);                }                drawingContext.Close();                RenderTargetBitmap faceWithRectBitmap = new RenderTargetBitmap(                    (int)(bitmapSource.PixelWidth * _resizeFactor),                    (int)(bitmapSource.PixelHeight * _resizeFactor),                    96,                    96,                    PixelFormats.Pbgra32);                faceWithRectBitmap.Render(visual);                FacePhoto.Source = faceWithRectBitmap;                faceDescriptionStatusBar.Text = _defaultStatusBarText;            }        }

调用SDK进行识别

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

// 上传图片使用faceclient识别        private async Task
> UploadAndDetectFaces(string imageFilePath) { IList
faceAttributes = new FaceAttributeType[] { FaceAttributeType.Gender, FaceAttributeType.Age, FaceAttributeType.Smile, FaceAttributeType.Emotion, FaceAttributeType.Glasses, FaceAttributeType.Hair }; using (Stream imageFileStream = File.OpenRead(imageFilePath)) { IList
faceList = await _faceClient.Face.DetectWithStreamAsync( imageFileStream, true, false, faceAttributes); return faceList; } }

显示脸部的描述

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

///         /// 鼠标移动显示脸部描述        ///         ///         ///         private void FacePhoto_MouseMove(object sender, MouseEventArgs e)        {            if (_faceList == null)                return;            Point mouseXY = e.GetPosition(FacePhoto);            ImageSource imageSource = FacePhoto.Source;            BitmapSource bitmapSource = (BitmapSource)imageSource;            var scale = FacePhoto.ActualWidth / (bitmapSource.PixelWidth / _resizeFactor);            bool mouseOverFace = false;            for (int i = 0; i < _faceList.Count; ++i)            {                FaceRectangle fr = _faceList[i].FaceRectangle;                double left = fr.Left * scale;                double top = fr.Top * scale;                double width = fr.Width * scale;                double height = fr.Height * scale;                if (mouseXY.X >= left && mouseXY.X <= left + width &&                    mouseXY.Y >= top && mouseXY.Y <= top + height)                {                    faceDescriptionStatusBar.Text = _faceDescriptions[i];                    mouseOverFace = true;                    break;                }            }            if (!mouseOverFace) faceDescriptionStatusBar.Text = _defaultStatusBarText;        }
///         /// 脸部描述        ///         ///         /// 
private string FaceDescription(DetectedFace face) { StringBuilder sb = new StringBuilder(); sb.Append("人脸: "); // 性别年龄 sb.Append(face.FaceAttributes.Gender.Value == Gender.Female ? "女性" : "男性"); sb.Append(", "); sb.Append(face.FaceAttributes.Age.ToString() + "岁"); sb.Append(", "); sb.Append(String.Format("微笑 {0:F1}%, ", face.FaceAttributes.Smile * 100)); // 显示超过0.1的表情 sb.Append("表情: "); Emotion emotionScores = face.FaceAttributes.Emotion; if (emotionScores.Anger >= 0.1f) sb.Append( String.Format("生气 {0:F1}%, ", emotionScores.Anger * 100)); if (emotionScores.Contempt >= 0.1f) sb.Append( String.Format("蔑视 {0:F1}%, ", emotionScores.Contempt * 100)); if (emotionScores.Disgust >= 0.1f) sb.Append( String.Format("厌恶 {0:F1}%, ", emotionScores.Disgust * 100)); if (emotionScores.Fear >= 0.1f) sb.Append( String.Format("恐惧 {0:F1}%, ", emotionScores.Fear * 100)); if (emotionScores.Happiness >= 0.1f) sb.Append( String.Format("高兴 {0:F1}%, ", emotionScores.Happiness * 100)); if (emotionScores.Neutral >= 0.1f) sb.Append( String.Format("自然 {0:F1}%, ", emotionScores.Neutral * 100)); if (emotionScores.Sadness >= 0.1f) sb.Append( String.Format("悲伤 {0:F1}%, ", emotionScores.Sadness * 100)); if (emotionScores.Surprise >= 0.1f) sb.Append( String.Format("惊喜 {0:F1}%, ", emotionScores.Surprise * 100)); sb.Append(face.FaceAttributes.Glasses); sb.Append(", "); sb.Append("头发: "); if (face.FaceAttributes.Hair.Bald >= 0.01f) sb.Append(String.Format("秃头 {0:F1}% ", face.FaceAttributes.Hair.Bald * 100)); IList
hairColors = face.FaceAttributes.Hair.HairColor; foreach (HairColor hairColor in hairColors) { if (hairColor.Confidence >= 0.1f) { sb.Append(hairColor.Color.ToString()); sb.Append(String.Format(" {0:F1}% ", hairColor.Confidence * 100)); } } return sb.ToString(); }

运行

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

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

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

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

总结

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

关注我的公众号一起玩转技术  

转载地址:http://yozdi.baihongyu.com/

你可能感兴趣的文章
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
昨夜今晨最大八卦终于坐实——人类首次直接探测到了引力波
查看>>
如何优雅、机智地和新公司谈薪水?
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
第一性原理:戳中问题本质的人是怎么思考的?
查看>>
No.147 - LeetCode1108
查看>>
No.148 - LeetCode771
查看>>
No.174 - LeetCode1305 - 合并两个搜索树
查看>>
No.175 - LeetCode1306
查看>>
No.176 - LeetCode1309
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
mac:移动python包路径
查看>>
mysql:sql create database新建utf8mb4 数据库
查看>>
mysql:sql alter database修改数据库字符集
查看>>
mysql:sql drop table (删除表)
查看>>
mysql:sql truncate (清除表数据)
查看>>