博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用UWP人脸检测API在WPF中进行人脸检测
阅读量:3527 次
发布时间:2019-05-20

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

目录


介绍

通用Windows平台的Windows.Media.FaceAnalysis名称空间包含可用于检测图像文件和视频帧中的面部的API。人脸检测API是可用于桌面应用程序的UWP API使得这种可用性成为可能。本文将介绍如何在WPF应用程序中使用UWP人脸检测API,特别是在图像文件中检测人脸。

先决条件

接下来,需要熟悉MVVM模式。要运行示例项目,您应该安装以下软件:

  • .NET Core 3.1
  • Visual Studio 2019

背景

该示例应用程序是一个引用Microsoft.Windows.SDK.Contracts程序包(Windows 10 WinRT API包)的.NET Core WPF项目,该程序使桌面应用程序可以访问某些UWP API。用户可以选择一个图像文件,并点击检测面孔按钮来检测所选择的图像中的人脸。

人脸检测

要使用UWP人脸检测API,您必须导入Windows.Media.FaceAnalysis命名空间。在示例项目中,此操作在包含执行人脸检测过程的DetectFaces()方法的FaceDetectionService类中完成。

public async Task
> DetectFaces(Stream fileStream){ var stream = fileStream.AsRandomAccessStream(); var bitmapDecoder = await BitmapDecoder.CreateAsync(stream); using SoftwareBitmap bitmap = await bitmapDecoder.GetSoftwareBitmapAsync(); var bmp = FaceDetector.IsBitmapPixelFormatSupported(bitmap.BitmapPixelFormat) ? bitmap : SoftwareBitmap.Convert(bitmap, BitmapPixelFormat.Gray8); var faceDetector = await FaceDetector.CreateAsync(); var detectedFaces = await faceDetector.DetectFacesAsync(bmp); return detectedFaces;}

FaceDetector仅于SoftwareBitmap一起工作,因此目标图像被转换为使用BitmapDecoder。然后检查位图像素格式,如果不是当前设备FaceDetector支持的位图像素格式之一,则完成转换。DetectFacesAsync()检测SoftwareBitmap中的人脸并返回DetectedFace对象的集合。

标记人脸

为了使用边界框标记检测到的面部,我正在使用System.Drawing命名空间中的Graphics类。

public Bitmap DetectedFacesBitmap(Stream fileStream, IList
detectedFaces, Color boxColor, int strokeThickness = 2){ var bitmap = new Bitmap(fileStream); using (var graphics = Graphics.FromImage(bitmap)) { using var stroke = new Pen(boxColor, strokeThickness); foreach (var face in detectedFaces) { BitmapBounds faceBox = face.FaceBox; graphics.DrawRectangle(stroke, (int)faceBox.X, (int)faceBox.Y, (int)faceBox.Width, (int)faceBox.Height); } } return bitmap;}

DetectedFace包含一个名为FaceBox的属性,它提供检测到的脸部的边界。在检测到的脸所在的图像上绘制矩形时,将使用边界。

查看模型

该示例项目遵循MVVM模式,并且仅包含一个视图模型– MainWindowViewModel。该视图模型包含两个属性。一种用于指定所选图像的路径的string类型,另一种用于处理图像的Bitmap类型。视图模型还包含用于执行图像选择和面部检测的命令。

using System.Drawing;using System.IO;using System.Threading.Tasks;using FaceDetection.Commands;using FaceDetection.Services.Interfaces;namespace FaceDetection.ViewModels{    public class MainWindowViewModel : ViewModelBase    {        private readonly IDialogService dialogService;        private readonly IFaceDetectionService faceDetectionService;        public MainWindowViewModel(IDialogService dialogSvc,                                   IFaceDetectionService faceDetectionSvc)        {            dialogService = dialogSvc;            faceDetectionService = faceDetectionSvc;        }        private string _selectedImage;        public string SelectedImage        {            get => _selectedImage;            set            {                _selectedImage = value;                OnPropertyChanged();            }        }        #region Select Image Command        private RelayCommand _selectImageCommand;        public RelayCommand SelectImageCommand =>            _selectImageCommand ??= new RelayCommand(_ => SelectImage());        private void SelectImage()        {            var image = dialogService.PickFile("Select Image",                "Image (*.jpg; *.jpeg; *.png)|*.jpg; *.jpeg; *.png");            if (string.IsNullOrWhiteSpace(image)) return;            SelectedImage = image;        }        #endregion        private Bitmap _facesBitmap;        public Bitmap FacesBitmap        {            get => _facesBitmap;            set            {                _facesBitmap = value;                OnPropertyChanged();            }        }        #region Detect faces Command        private RelayCommandAsync _detectFacesCommand;        public RelayCommandAsync DetectFacesCommand =>            _detectFacesCommand ??= new RelayCommandAsync                                    (DetectFaces, _ => CanDetectFaces());        private async Task DetectFaces()        {            await using FileStream fileStream = File.OpenRead(_selectedImage);            var faces = await faceDetectionService.DetectFaces(fileStream);            FacesBitmap = faceDetectionService.DetectedFacesBitmap                          (fileStream, faces, Color.GreenYellow);            SelectedImage = null;        }        private bool CanDetectFaces() => !string.IsNullOrWhiteSpace(SelectedImage);        #endregion    }}

视图

使用MainWindow.xamlImage控件的数据触发器在所选图像和已处理图像之间进行切换:

    

由于FacesBitmap类型为Bitmap,因此必须将其转换为BitmapSource。这是使用转换器完成的。

public class BitmapToBitmapSourceConverter : IValueConverter{    public object Convert(object value, Type targetType,           object parameter, CultureInfo culture)    {        if (value is null) return null;        using var bitmap = (Bitmap)value;        using var stream = new MemoryStream();        bitmap.Save(stream, ImageFormat.Bmp);        stream.Position = 0;        var bmpImg = new BitmapImage();        bmpImg.BeginInit();        bmpImg.CacheOption = BitmapCacheOption.OnLoad;        bmpImg.StreamSource = stream;        bmpImg.EndInit();        bmpImg.Freeze();        return bmpImg;    }    public object ConvertBack(object value, Type targetType,                              object parameter, CultureInfo culture)    {        return Binding.DoNothing;    }}

结论

如您所见,使用UWP人脸检测API是一个非常简单的过程。重要的是要注意,尽管该API确实非常擅长检测人脸,但由于像素可能不足以使人脸检测器正常工作,因此它可能无法检测到部分可见的人脸。

就是这样!如果您需要查看示例项目的其余代码,请使用本文顶部的下载链接来克隆或下载存储库。

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

你可能感兴趣的文章
数据结构之栈
查看>>
Elastic Stack简介
查看>>
关于deepin系统安装design compiler的问题解答
查看>>
Java Agent简介及使用Byte Buddy和AspectJ LTW监控方法执行耗时
查看>>
记录一下最近的学习经历
查看>>
hadoop3.0+spark2.0两台云服务器集群环境配置。
查看>>
记第一次面试经历
查看>>
网站实现qq登录(springboot后台)
查看>>
简单的用户头像修改功能(springboot后台)
查看>>
springboot+mybatis实现分页
查看>>
leetcode332. 重新安排行程
查看>>
为什么局域网网段不同不能通信?
查看>>
itchat微信助手,kaggle 电影数据集分析,基于内容的电影推荐
查看>>
认识和使用JWT
查看>>
通过springboot框架,自己动手实现oauth2.0授权码模式认证
查看>>
条件表达式于运算符的点点滴滴的积累
查看>>
最短路径最基本的三种算法【此后无良辰】
查看>>
class的点点滴滴的总结
查看>>
vector 的点点滴滴的总结
查看>>
测试用例
查看>>