使用UWP人脸检测API在WPF中进行人脸检测(译文)
By S.F.
本文链接 https://www.kyfws.com/news/face-detection-in-wpf-using-uwp-face-detection-api/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 4 分钟阅读 - 1954 个词 阅读量 0使用UWP人脸检测API在WPF中进行人脸检测(译文)
原文地址:https://www.codeproject.com/Articles/5282165/Face-Detection-in-WPF-using-UWP-Face-Detection-API
原文作者:Meshack Musundi
译文由本站翻译
前言
Detecting faces in an image in WPF using the UWP face detection API 使用UWP人脸检测API在WPF中检测图像中的人脸 Learn how to use the UWP face detection API to detect faces in an image in a WPF application 了解如何使用UWP人脸检测API在WPF应用程序中检测图像中的人脸
(Introduction) 介绍
(The Universal Windows Platform’s) 通用Windows平台 Windows.Media.FaceAnalysis
(namespace contains APIs that can be used to detect faces in image files and video frames. The face detection API is) 名称空间包含可用于检测图像文件和视频帧中的面部的API.人脸检测API是 (one) 一 (of the UWP APIs available to desktop applications, with this availability being made possible by the) 桌面应用程序可以使用的UWP API的数量, (Windows 10 WinRT API Pack) Windows 10 WinRT API包 (. This article will take a look at how to go about using the UWP face detection API in a WPF application, specifically to detect faces in an image file.) .本文将介绍如何在WPF应用程序中使用UWP人脸检测API,特别是在图像文件中检测人脸.
(Prerequisites) 先决条件
(To follow along, some familiarity with the MVVM pattern is required. To run the sample project, you should have the following installed:) 接下来,需要熟悉MVVM模式.要运行示例项目,您应该安装以下软件:
-
(.NET Core 3.1) .NET Core 3.1
-
(Visual Studio 2019) Visual Studio 2019
(Background) 背景
(The sample application is a .NET Core WPF project that references the) 该示例应用程序是一个.NET Core WPF项目,该项目引用了 Microsoft.Windows.SDK.Contracts
(package (Windows 10 WinRT API pack), which enables desktop applications to access certain UWP APIs. The user can select an image file and click on the) 软件包(Windows 10 WinRT API软件包),使桌面应用程序可以访问某些UWP API.用户可以选择一个图像文件,然后单击(Detect Faces) 检测人脸(button to detect faces in the selected image.) 按钮以检测所选图像中的脸部.
(Face Detection) 人脸检测
(To use the UWP face detection API, you have to import the) 要使用UWP人脸检测API,您必须导入 Windows.Media.FaceAnalysis
(namespace. In the sample project, this is done in the) 命名空间.在示例项目中,这是通过 FaceDetectionService
(class which contains a) 包含 DetectFaces()
(method where the face detection process is executed.) 执行面部检测处理的方法.
public async Task<IList<DetectedFace>> 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
(only works with a) 仅适用于 SoftwareBitmap
(so the target image is converted to one using a) 因此目标图片会使用 BitmapDecoder
(. A check of the bitmap pixel format is then done and if it’s not one of those supported by the) .然后检查位图像素格式,如果不是位图像素支持的格式之一, FaceDetector
(on the current device, a conversion is done.) 在当前设备上,已完成转换. DetectFacesAsync()
(detects the faces in the) 检测到人脸 SoftwareBitmap
(and returns a collection of) 并返回一个集合 DetectedFace
(objects.) 对象.
(Marking Faces) 标记面
(To mark the detected faces using bounding boxes, I’m making use of the) 为了使用边界框标记检测到的面部,我正在使用 Graphics
(class from the) 来自的班级 System.Drawing
(namespace.) 命名空间.
public Bitmap DetectedFacesBitmap(Stream fileStream, IList<DetectedFace> 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
(contains a property named) 包含一个名为 FaceBox
(that provides the bounds of a detected face. The bounds are used when drawing rectangles on the image where the detected faces are located.) 提供检测到的脸部的边界.在检测到的脸所在的图像上绘制矩形时,将使用边界.
(View Model) 查看模型
(The sample project follows the MVVM pattern and contains only one view model –) 该示例项目遵循MVVM模式,仅包含一个视图模型– MainWindowViewModel
(. This view model contains two properties; one of type) .该视图模型包含两个属性.一种类型 string
(that specifies the path of the selected image and the other of type) 指定所选图像的路径,另一种类型 Bitmap
(for the processed image. The view model also contains commands for executing image selection and face detection.) 用于处理的图像.视图模型还包含用于执行图像选择和面部检测的命令.
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
}
}
(View) 视图
(Switching between the selected image and the processed image is done using a data trigger for the) 所选图像和已处理图像之间的切换是通过使用 Image
(control in) 控制在**(*MainWindow.xaml*) MainWindow.xaml**(*:*) :
<Image Margin="10">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding SelectedImage, Mode=OneWay}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedImage}" Value="{x:Null}">
<Setter Property="Source"
Value="{Binding FacesBitmap,
Converter={StaticResource BitmapConverter}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
(Since) 以来 FacesBitmap
(is of type) 是类型 Bitmap
(, it has to be converted to a) ,则必须将其转换为 BitmapSource
(. This is done using a converter.) .这是使用转换器完成的.
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;
}
}
(Conclusion) 结论
(As you’ve seen, using the UWP face detection API is a very simple process. It’s important to note that while the API is really good at detecting faces, it may not detect faces that are partially visible since the pixels may not be sufficient for the face detector to work with.) 如您所见,使用UWP人脸检测API是一个非常简单的过程.重要的是要注意,尽管该API确实非常擅长检测人脸,但由于像素可能不足以使人脸检测器正常工作,因此它可能无法检测部分可见的人脸.
(That’s it! If you need to have a look at the rest of the code for the sample project, clone or download the repository using the download link at the top of this article.) 而已!如果您需要查看示例项目的其余代码,请使用本文顶部的下载链接来克隆或下载存储库.
(History) 历史
- (7) 7(th) 日(October, 2020: Initial post) 2020年10月:初始提交
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# WPF Intermediate 新闻 翻译