分析相机帧的效果

本文介绍了如何使用 SceneAnalysisEffectFaceDetectionEffect 分析媒体捕获预览流的内容。

场景分析效果

SceneAnalysisEffect 将分析媒体捕获预览流中的视频帧,并建议处理选项以改进捕获结果。 当前,效果支持检测是否通过使用高动态范围 (HDR) 处理改进捕获。

如果该效果建议使用 HDR,可以采用以下方式执行此操作:

场景分析命名空间

若要使用场景分析,你的应用必须包含以下命名空间以及基本媒体捕获所需的命名空间。

using Windows.Media.Core;
using Windows.Media.Devices;

初始化场景分析效果并将其添加到预览流

使用两个 API、一个效果定义(可提供捕获设备初始化效果所需的设置)和一个效果实例(可用于控制效果)实现视频效果。 因为你可能想要从代码内的多个位置访问效果实例,因此你通常应声明成员变量以保留对象。

private SceneAnalysisEffect _sceneAnalysisEffect;

在你的应用中,在初始化 MediaCapture 对象后,创建 SceneAnalysisEffectDefinition 的新实例。

通过在你的 MediaCapture 对象上调用 AddVideoEffectAsync、提供 SceneAnalysisEffectDefinition 并指定 MediaStreamType.VideoPreview,指示该效果应应用于视频预览流(而不是捕获流),从而使用捕获设备注册效果。 AddVideoEffectAsync 返回已添加效果的实例。 因为此方法可以与多个效果类型结合使用,因此你必须将返回的实例转换为 SceneAnalysisEffect 对象。

若要接收场景分析的结果,你必须为 SceneAnalyzed 事件注册处理程序。

当前,场景分析效果仅包含高动态范围分析器。 通过将效果的 HighDynamicRangeControl.Enabled 设置为 true 启用 HDR 分析。

// Create the definition
var definition = new SceneAnalysisEffectDefinition();

// Add the effect to the video record stream
_sceneAnalysisEffect = (SceneAnalysisEffect)await _mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);

// Subscribe to notifications about scene information
_sceneAnalysisEffect.SceneAnalyzed += SceneAnalysisEffect_SceneAnalyzed;

// Enable HDR analysis
_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = true;

实现 SceneAnalyzed 事件处理程序

场景分析的结果在 SceneAnalyzed 事件处理程序中返回。 传入处理程序中的 SceneAnalyzedEventArgs 对象具有包含 HighDynamicRangeOutput 对象的 SceneAnalysisEffectFrame 对象。 高动态范围输出的 Certainty 属性提供了一个介于 0 到 1.0 的值,其中 0 指示 HDR 处理不会帮助改进捕获结果,1.0 指示 HDR 处理会帮助改进捕获结果。 你可以确定要使用 HDR 的阈值点,或向用户显示结果并让用户作出决定。

private void SceneAnalysisEffect_SceneAnalyzed(SceneAnalysisEffect sender, SceneAnalyzedEventArgs args)
{
    double hdrCertainty = args.ResultFrame.HighDynamicRange.Certainty;
    
    // Certainty value is between 0.0 and 1.0
    if(hdrCertainty > MyCertaintyCap)
    {
        ShowMessageToUser("Enabling HDR capture is recommended.");
    }
}

传入处理程序中的 HighDynamicRangeOutput 对象还具有 FrameControllers 属性,它包含用于捕获可变照片序列进行 HDR 处理的建议帧控制器。 有关详细信息,请参阅可变照片序列

清理场景分析效果

当你的应用完成捕获时,在处理 MediaCapture 对象之前,你应该通过将效果的 HighDynamicRangeAnalyzer.Enabled 属性设置为 false 来禁用场景分析效果,并取消注册 SceneAnalyzed 事件处理程序。 请调用 MediaCapture.ClearEffectsAsync,从而指定视频预览流,因为该流是已添加效果的流。 最后,将你的成员变量设置为 null。

// Disable detection
_sceneAnalysisEffect.HighDynamicRangeAnalyzer.Enabled = false;

_sceneAnalysisEffect.SceneAnalyzed -= SceneAnalysisEffect_SceneAnalyzed;

// Remove the effect from the preview stream
await _mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);

// Clear the member variable that held the effect instance
_sceneAnalysisEffect = null;

人脸检测效果

FaceDetectionEffect 可在媒体捕获预览流内标识人脸的位置。 该效果允许你在预览流中检测到人脸时接收通知,并为预览帧内每个检测到的人脸提供边界框。 在受支持的设备上,人脸检测效果还提供增强的曝光,并聚焦于场景中最重要的人脸。

人脸检测命名空间

若要使用人脸检测,你的应用必须包含以下命名空间,以及基本媒体捕获所需的命名空间。

using Windows.Media.Core;

初始化人脸检测效果并将其添加到预览流

使用两个 API、一个效果定义(可提供捕获设备初始化效果所需的设置)和一个效果实例(可用于控制效果)实现视频效果。 因为你可能想要从代码内的多个位置访问效果实例,因此你通常应声明成员变量以保留对象。

FaceDetectionEffect _faceDetectionEffect;

在你的应用中,在初始化 MediaCapture 对象后,创建 FaceDetectionEffectDefinition 的新实例。 设置 DetectionMode 属性以设置优先级:更快的人脸检测优先或更精确的人脸检测优先。 设置 SynchronousDetectionEnabled 以指定传入的帧不会延迟等待人脸检测完成,因为这可能导致不连贯的预览体验。

通过在你的 MediaCapture 对象上调用 AddVideoEffectAsync、提供 FaceDetectionEffectDefinition 并指定 MediaStreamType.VideoPreview,指示该效果应应用于视频预览流(而不是捕获流),从而使用捕获设备注册效果。 AddVideoEffectAsync 返回已添加效果的实例。 因为此方法可以与多个效果类型结合使用,因此你必须将返回的实例转换为 FaceDetectionEffect 对象。

通过设置 FaceDetectionEffect.Enabled 属性,启用或禁用效果。 通过设置 FaceDetectionEffect.DesiredDetectionInterval 属性调整效果分析帧的频率。 在正在运行媒体捕获时,可同时调整这两个属性。


// Create the definition, which will contain some initialization settings
var definition = new FaceDetectionEffectDefinition();

// To ensure preview smoothness, do not delay incoming samples
definition.SynchronousDetectionEnabled = false;

// In this scenario, choose detection speed over accuracy
definition.DetectionMode = FaceDetectionMode.HighPerformance;

// Add the effect to the preview stream
_faceDetectionEffect = (FaceDetectionEffect)await _mediaCapture.AddVideoEffectAsync(definition, MediaStreamType.VideoPreview);

// Choose the shortest interval between detection events
_faceDetectionEffect.DesiredDetectionInterval = TimeSpan.FromMilliseconds(33);

// Start detecting faces
_faceDetectionEffect.Enabled = true;

在检测到人脸时接收通知

如果你想要在检测到人脸时执行某些操作(例如,在视频预览中检测到的人脸周围绘制一个框),你可以注册 FaceDetected 事件。

// Register for face detection events
_faceDetectionEffect.FaceDetected += FaceDetectionEffect_FaceDetected;

在该事件的处理程序中,你可以通过访问 FaceDetectedEventArgsFaceDetectionEffectFrame.DetectedFaces 属性,获取帧中所有检测到的人脸列表。 FaceBox 属性是 BitmapBounds 结构,用于描述包含检测到的人脸的矩形,其单位相对于预览流尺寸。 若要查看将预览流坐标转换到屏幕坐标的示例代码,请参阅人脸检测 UWP 示例

private void FaceDetectionEffect_FaceDetected(FaceDetectionEffect sender, FaceDetectedEventArgs args)
{
    foreach (Windows.Media.FaceAnalysis.DetectedFace face in args.ResultFrame.DetectedFaces)
    {
        BitmapBounds faceRect = face.FaceBox;

        // Draw a rectangle on the preview stream for each face
    }
}

清理人脸检测效果

当你的应用完成捕获时,在处理 MediaCapture 对象之前,应该使用 FaceDetectionEffect.Enabled 禁用人脸检测效果并取消注册 FaceDetected 事件处理程序(如果你之前已注册一个处理程序)。 请调用 MediaCapture.ClearEffectsAsync,从而指定视频预览流,因为该流是已添加效果的流。 最后,将你的成员变量设置为 null。

// Disable detection
_faceDetectionEffect.Enabled = false;

// Unregister the event handler
_faceDetectionEffect.FaceDetected -= FaceDetectionEffect_FaceDetected;

// Remove the effect from the preview stream
await _mediaCapture.ClearEffectsAsync(MediaStreamType.VideoPreview);

// Clear the member variable that held the effect instance
_faceDetectionEffect = null;

查看对检测到的人脸的焦点和曝光支持

并非所有设备都具有可根据检测到的人脸调整其焦点和曝光的捕获设备。 因为人脸检测会消耗设备资源,因此你可能只希望在可使用该功能增强捕获的设备上启用人脸检测。 若要查看基于人脸的捕获优化是否可用,请为初始化的 MediaCapture 获取 VideoDeviceController,然后获取视频设备控制器的 RegionsOfInterestControl。 查看 MaxRegions 是否支持至少一个区域。 然后,查看 AutoExposureSupportedAutoFocusSupported 是否为 true。 如果满足这些条件,则设备可以充分利用人脸检测来增强捕获。

var regionsControl = _mediaCapture.VideoDeviceController.RegionsOfInterestControl;
bool faceDetectionFocusAndExposureSupported =
    regionsControl.MaxRegions > 0 &&
    (regionsControl.AutoExposureSupported || regionsControl.AutoFocusSupported);