人脸识别是人工智能机器学习比较成熟的一个领域。人脸识别已经应用到了很多生产场景。比如生物认证,人脸考勤,人流监控等场景。对于很多中小功能由于技术门槛问题很难自己实现人脸识别的算法。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放置图像显示区域、文件选中、描述显示区域

<Window x:Class="FaceWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FaceWpf"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800">
<Grid x:Name="BackPanel">
<Image x:Name="FacePhoto" Stretch="Uniform" Margin="0,0,0,50" MouseMove="FacePhoto_MouseMove" />
<DockPanel DockPanel.Dock="Bottom">
<Button x:Name="BrowseButton" Width="72" Height="80" VerticalAlignment="Bottom" HorizontalAlignment="Left"
Content="选择图片..."
Click="BrowseButton_Click" />
<StatusBar VerticalAlignment="Bottom">
<StatusBarItem>
<TextBlock Name="faceDescriptionStatusBar" Height="80" FontSize="20" Text="" Width="500" TextWrapping="Wrap"/>
</StatusBarItem>
</StatusBar>
</DockPanel>
</Grid>
</Window>

图片选择并显示

  // 选择图片并上传
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<IList<DetectedFace>> UploadAndDetectFaces(string imageFilePath)
{
IList<FaceAttributeType> faceAttributes =
new FaceAttributeType[]
{
FaceAttributeType.Gender, FaceAttributeType.Age,
FaceAttributeType.Smile, FaceAttributeType.Emotion,
FaceAttributeType.Glasses, FaceAttributeType.Hair
}; using (Stream imageFileStream = File.OpenRead(imageFilePath))
{
IList<DetectedFace> faceList =
await _faceClient.Face.DetectWithStreamAsync(
imageFileStream, true, false, faceAttributes);
return faceList;
}
}

显示脸部的描述

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

 /// <summary>
/// 鼠标移动显示脸部描述
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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;
}
 /// <summary>
/// 脸部描述
/// </summary>
/// <param name="face"></param>
/// <returns></returns>
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<HairColor> 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除了能对图片中的人脸进行检测,还可以对多个人脸进行比对,检测是否是同一个人,这样就可以实现人脸考勤等功能了,这个下次再说吧。

使用Azure人脸API对图片进行人脸识别的更多相关文章

  1. 借助百度云API进行人脸识别

    前言:本篇博客是笔者第一次使用百度云api进行人脸检测,主要内容包括两部分,一是获取接口,二是借助接口进行人脸检测.笔者也是初步了解这方面的内容,也是参考了杂七杂八的博文,内容可能存在错误及其他毛病, ...

  2. 树莓派+百度api实现人脸识别

    title: 树莓派+百度api实现人脸识别 tags: 树莓派 date: 2018-5-31 20:06:00 --- 树莓派对接百度api 我以前玩安卓的时候一直用的讯飞的平台和api,对于百度 ...

  3. 转:基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴等)【模式识别中的翘楚】

    文章来自于:http://blog.renren.com/share/246648717/8171467499 基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴 ...

  4. keras系列︱人脸表情分类与识别:opencv人脸检测+Keras情绪分类(四)

    引自:http://blog.csdn.net/sinat_26917383/article/details/72885715 人脸识别热门,表情识别更加.但是表情识别很难,因为人脸的微表情很多,本节 ...

  5. 基于OpenCV读取摄像头进行人脸检测和人脸识别

    前段时间使用OpenCV的库函数实现了人脸检测和人脸识别,笔者的实验环境为VS2010+OpenCV2.4.4,opencv的环境配置网上有很多,不再赘述.检测的代码网上很多,记不清楚从哪儿copy的 ...

  6. Opencv与dlib联合进行人脸关键点检测与识别

    前言 依赖库:opencv 2.4.9 /dlib 19.0/libfacedetection 本篇不记录如何配置,重点在实现上.使用libfacedetection实现人脸区域检测,联合dlib标记 ...

  7. facenet 人脸识别(二)——创建人脸库搭建人脸识别系统

    搭建人脸库 选择的方式是从百度下载明星照片 照片下载,downloadImageByBaidu.py # coding=utf-8 """ 爬取百度图片的高清原图 &qu ...

  8. 人脸真伪验证与识别:ICCV2019论文解析

    人脸真伪验证与识别:ICCV2019论文解析 Face Forensics++: Learning to Detect Manipulated Facial Images 论文链接: http://o ...

  9. Tensorflow object detection API 搭建物体识别模型(二)

    二.数据准备 1)下载图片 图片来源于ImageNet中的鲤鱼分类,下载地址:https://pan.baidu.com/s/1Ry0ywIXVInGxeHi3uu608g 提取码: wib3 在桌面 ...

随机推荐

  1. tensorflow实现lstm中遇到的函数记录

    函数一:initializer=tf.random_uniform_initializer(-0.1, 0.1, seed=123) tf.random_uniform_initializer 参数: ...

  2. 数据源管理 | 搜索引擎框架,ElasticSearch集群模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.集群环境搭建 1.环境概览 ES版本6.3.2,集群名称esmaster,虚拟机centos7. 服务群 角色划分 说明 en-maste ...

  3. 【面试题资源共享】一文总结最高频软件测试|sq|语句|思维发散|计算机基础|Linux|测试用例|接口测试|等技术面试题

    思维发散 1.一个球, -把尺子长度是球直径的2/3,怎样测出半径?2.四枚硬币,花面朝上,每次翻转三个,几次可以将四枚硬币变为字面朝上?3. U2合唱团在1 7分钟内赶到演唱会现场问题?4.小明一家 ...

  4. map数据按照list排序

    简介 (Introduction): 背景 需要对字段进行排序,但是,一个字段的结果存在一个map中,一个存在list中,需要让map的数组,按照list的顺序进行排序 结构图 list顺序 [ { ...

  5. 当小程序遇见物联网IoT,几行代码搞定智能插座控制

    在 5G 热潮的推动下,与其紧密结合的物联网(IoT)正日益成为个人和企业工作生活中的重要组成部分,它为企业和个人带来了操作流程的改进和更好的生活体验,随着人工智能(AI)技术的日趋成熟,IoT 与 ...

  6. NIO入门之缓冲区Buffer

    缓存区 Buffer 是数据容器 ByteBuffer 可以存储除了 boolean 以外的其他 7 种Java基本数据类型,如 getInt.putInt Buffer 是抽象类,它有除了 Bool ...

  7. 2n皇后问题-------递归 暴力求解题与分布讨论题

    问题描述 给定一个n*n的棋盘,棋盘中有一些位置不能放皇后.现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行.同一列或同一条对角线上,任意的两个白皇后都不在同一行.同一列或同一 ...

  8. 初识Http

     HTTP是一个用在计算机世界里的协议,它确立了一种计算机之间交流通信的规范,以及相关的各种控制 和错误处理方式.  HTTP专门用来在两点之间传输数据,不能用于广播.寻址或路由. HTTP传输的是文 ...

  9. 简单理解:数据库的一致性与四种隔离级别(+MySQL实现)

    并行数据库存在着几种常见不一致问题: 1.更新丢失:两个并发的写进程同时修改某内容,一个没修改完提交之后另一个又提交,导致其覆盖了第一个提交的写进程内容. 2.脏读:一个操作读到了另外一个操作没有提交 ...

  10. C语言学习笔记一---C语言概述

    一.编程语言与解释语言 1.程序的执行 a.解释:借助一个能试图理解程序的程序,使计算机按要求执行你自己写的程序 b.编译:将所写程序翻译为机器语言写的程序,使计算机按要求执行你自己写的程序 2.两者 ...