您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

使用 Azure 媒体分析进行面部修订

媒体服务徽标


概述

Azure 媒体修订器 是一种 Azure 媒体分析媒体处理器 (MP),可用于在云中进行可缩放的面部修订。 使用面部修订,可对视频进行修改,使所选个人的面部模糊显示。 用户可能想要在公共安全和新闻媒体场景中使用面部修订服务。 对于时长仅几分钟但包含多张面孔的镜头,进行手动面部修订可能需要几个小时,但使用此服务仅需几个简单步骤即可完成该过程。

本文提供有关 Azure 媒体编修器 的详细信息,并演示如何通过适用于 .NET 的媒体服务 SDK 使用它。

面部修订模式

面部修订的工作方式是:检测每一帧视频中的面部,并跟踪之前和之后的面部对象,以便同一个人在其他角度也模糊显示。 自动编修过程很复杂,并且无法始终生成 100% 符合要求的输出,因此,媒体分析提供了几种修改最终输出的方式。

除了完全自动模式外,还可使用双步工作流通过 ID 列表选择/取消选择找到的面部。 此外,为了对每一帧进行任意调整,MP 使用 JSON 格式的元数据文件。 此工作流拆分为“分析”和“修订”模式。 可将这两个模式组合为在一个作业中运行两项任务的单个过程;此模式称为“组合”。

备注

已于 2020 年 6 月弃用 Face Detector Media Processor,Azure 媒体服务组件。 请考虑使用 Azure 媒体服务 v3 API。

组合模式

这会自动生成经过编修的 mp4,而无需任何手动输入。

阶段 文件名 说明
输入资产 foo.bar WMV、MOV 或 MP4 格式的视频
输入配置 作业配置预设 {'version':'1.0', 'options': {'mode':'combined'}}
输出资产 foo_redacted.mp4 进行了模糊处理的视频

分析模式

双步工作流的 分析 步骤使用视频输入,并生成表示面部位置的 JSON 文件,以及显示每个检测到的面部 jpg 图像。

阶段 文件名 说明
输入资产 foo.bar WMV、MPV 或 MP4 格式的视频
输入配置 作业配置预设 {'version':'1.0', 'options': {'mode':'analyze'}}
输出资产 foo_annotations.json JSON 格式的面部位置批注数据。 用户可编辑此数据,以修改模糊边界框。 请查看以下示例。
输出资产 foo_thumb%06d.jpg [foo_thumb000001.jpg, foo_thumb000002.jpg] 裁剪后的 jpg 文件,显示每个检测到的面部,其中的数字指示面部的标签 ID

输出示例

{
  "version": 1,
  "timescale": 24000,
  "offset": 0,
  "framerate": 23.976,
  "width": 1280,
  "height": 720,
  "fragments": [
    {
      "start": 0,
      "duration": 48048,
      "interval": 1001,
      "events": [
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [],
        [
          {
            "index": 13,
            "id": 1138,
            "x": 0.29537,
            "y": -0.18987,
            "width": 0.36239,
            "height": 0.80335
          },
          {
            "index": 13,
            "id": 2028,
            "x": 0.60427,
            "y": 0.16098,
            "width": 0.26958,
            "height": 0.57943
          }
        ],

    ... truncated

修订模式

工作流的第二步使用更大数量的输入,这些输入必须合并为单个资产。

这包括要模糊处理的 ID 的列表、原始视频和批注 JSON。 此模式使用批注来对输入视频进行模糊处理。

“分析”步骤的输出不包括原始视频。 需要将该视频上传到“修订”模式任务的输入资产中,并将其选作主文件。

阶段 文件名 说明
输入资产 foo.bar WMV、MPV 或 MP4 格式的视频。 与步骤 1 中相同的视频。
输入资产 foo_annotations.json 第一阶段中的批注元数据文件,包含可选的修改。
输入资产 foo_IDList.txt(可选) 要进行修订的可选面部 ID 列表,以新行进行分隔。 如果留空,则模糊所有面部。
输入配置 作业配置预设 {'version':'1.0', 'options': {'mode':'redact'}}
输出资产 foo_redacted.mp4 基于批注进行了模糊处理的视频

示例输出

这是来自选择了一个 ID 的 ID 列表的输出。

示例 foo_IDList.txt

1
2
3

模糊类型

在“组合”或“修订”模式下,可通过 JSON 输入配置在 5 种不同的模糊模式中选择:“低”、“中”、“高”、“框”和“黑色”。 默认情况下使用“中”。

可以查找以下模糊类型的示例。

示例 JSON

{
    'version':'1.0',
    'options': {
        'Mode': 'Combined',
        'BlurType': 'High'
    }
}

低

中

高

Box

Box

黑色

黑色

输出 JSON 文件中的元素

修订 MP 提供高精确度的面部位置检测和跟踪功能,可在一个视频帧中检测到最多 64 张人脸。 正面的面部可提供最佳效果,而检测和跟踪侧面的面部和较小的面部(小于或等于 24x24 像素)可能具有一定难度。

作业将生成一个 JSON 输出文件,其中包含有关检测到的和跟踪的面部的元数据。 元数据包括指示面部位置的坐标,以及指示正在跟踪该人员的面部 ID 编号。 在正面面部长时间于帧中消失或重叠的情况下,面部 ID 编号很容易重置,导致某些人员被分配多个 ID。

输出 JSON 包含以下元素:

根 JSON 元素

元素 说明
版本 这是指视频 API 的版本。
时间刻度 视频每秒的“刻度”数。
offset 这是时间戳的时间偏移量。 在版本 1.0 的视频 API 中,此属性始终为 0。 在我们将来支持的方案中,此值可能会更改。
宽度、高度 输出视频帧的宽度和高度,以像素为单位。
帧速率 视频的每秒帧数。
片段 元数据划分成称为“片段”的不同段。 每个片段包含开始时间、持续时间、间隔数字和事件。

片段 JSON 元素

元素 说明
start 第一个事件的开始时间(以“刻度”为单位)。
duration 片段的长度(以“刻度”为单位)。
index (仅适用于 Azure 媒体编修器)定义当前事件的帧索引。
interval 片段中每个事件条目的间隔(以“刻度”为单位)。
events 每个事件包含在该持续时间内检测到并跟踪的面部。 它是事件的数组。 外部数组代表一个时间间隔。 内部数组包含在该时间点发生的 0 个或多个事件。 空括号 [] 代表没有检测到人脸。
id 正在跟踪的面部的 ID。 如果某个面部后来未被检测到,此编号可能会意外更改。 给定人员在整个视频中应该拥有相同的 ID,但由于检测算法的限制(例如受到阻挡等情况),我们无法保证这一点。
x, y 规范化 0.0 到 1.0 比例中面部边框左上角的 X 和 Y 坐标。
-X 和 Y 坐标总是相对于横向方向,因此如果视频是纵向(或使用 iOS 时上下颠倒),便需要相应地变换坐标。
宽度、高度 规范化 0.0 到 1.0 比例中面部边框的宽度和高度。
facesDetected 位于 JSON 结果的末尾,汇总在生成视频期间算法所检测到的面部数。 由于 ID 可能在面部无法检测时(例如面部离开屏幕、转向别处)意外重置,此数字并不一定与视频中的实际面部数相同。

.NET 示例代码

以下程序演示如何:

  1. 创建资产并将媒体文件上传到资产。

  2. 基于包含以下 json 预设的配置文件创建含有人脸编修任务的作业:

            {
                'version':'1.0',
                'options': {
                    'mode':'combined'
                }
            }
    
  3. 下载输出 JSON 文件。

创建和配置 Visual Studio 项目

设置开发环境,并在 app.config 文件中填充连接信息,如使用 .NET 进行媒体服务开发中所述。

示例

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.Threading;
using System.Threading.Tasks;

namespace FaceRedaction
{
    class Program
    {
        // Read values from the App.config file.
        private static readonly string _AADTenantDomain =
            ConfigurationManager.AppSettings["AMSAADTenantDomain"];
        private static readonly string _RESTAPIEndpoint =
            ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
        private static readonly string _AMSClientId =
            ConfigurationManager.AppSettings["AMSClientId"];
        private static readonly string _AMSClientSecret =
            ConfigurationManager.AppSettings["AMSClientSecret"];

        // Field for service context.
        private static CloudMediaContext _context = null;

        static void Main(string[] args)
        {
            AzureAdTokenCredentials tokenCredentials =
                new AzureAdTokenCredentials(_AADTenantDomain,
                    new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
                    AzureEnvironments.AzureCloudEnvironment);

            var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

            _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

            // Run the FaceRedaction job.
            var asset = RunFaceRedactionJob(@"C:\supportFiles\FaceRedaction\SomeFootage.mp4",
                        @"C:\supportFiles\FaceRedaction\config.json");

            // Download the job output asset.
            DownloadAsset(asset, @"C:\supportFiles\FaceRedaction\Output");
        }

        static IAsset RunFaceRedactionJob(string inputMediaFilePath, string configurationFile)
        {
            // Create an asset and upload the input media file to storage.
            IAsset asset = CreateAssetAndUploadSingleFile(inputMediaFilePath,
            "My Face Redaction Input Asset",
            AssetCreationOptions.None);

            // Declare a new job.
            IJob job = _context.Jobs.Create("My Face Redaction Job");

            // Get a reference to Azure Media Redactor.
            string MediaProcessorName = "Azure Media Redactor";

            var processor = GetLatestMediaProcessorByName(MediaProcessorName);

            // Read configuration from the specified file.
            string configuration = File.ReadAllText(configurationFile);

            // Create a task with the encoding details, using a string preset.
            ITask task = job.Tasks.AddNew("My Face Redaction Task",
            processor,
            configuration,
            TaskOptions.None);

            // Specify the input asset.
            task.InputAssets.Add(asset);

            // Add an output asset to contain the results of the job.
            task.OutputAssets.AddNew("My Face Redaction Output Asset", AssetCreationOptions.None);

            // Use the following event handler to check job progress.  
            job.StateChanged += new EventHandler<JobStateChangedEventArgs>(StateChanged);

            // Launch the job.
            job.Submit();

            // Check job execution and wait for job to finish.
            Task progressJobTask = job.GetExecutionProgressTask(CancellationToken.None);

            progressJobTask.Wait();

            // If job state is Error, the event handling
            // method for job progress should log errors.  Here we check
            // for error state and exit if needed.
            if (job.State == JobState.Error)
            {
                ErrorDetail error = job.Tasks.First().ErrorDetails.First();
                Console.WriteLine(string.Format("Error: {0}. {1}",
                                error.Code,
                                error.Message));
                return null;
            }

            return job.OutputMediaAssets[0];
        }

        static IAsset CreateAssetAndUploadSingleFile(string filePath, string assetName, AssetCreationOptions options)
        {
            IAsset asset = _context.Assets.Create(assetName, options);

            var assetFile = asset.AssetFiles.Create(Path.GetFileName(filePath));
            assetFile.Upload(filePath);

            return asset;
        }

        static void DownloadAsset(IAsset asset, string outputDirectory)
        {
            foreach (IAssetFile file in asset.AssetFiles)
            {
                file.Download(Path.Combine(outputDirectory, file.Name));
            }
        }

        static IMediaProcessor GetLatestMediaProcessorByName(string mediaProcessorName)
        {
            var processor = _context.MediaProcessors
            .Where(p => p.Name == mediaProcessorName)
            .ToList()
            .OrderBy(p => new Version(p.Version))
            .LastOrDefault();

            if (processor == null)
                throw new ArgumentException(string.Format("Unknown media processor",
                                       mediaProcessorName));

            return processor;
        }

        static private void StateChanged(object sender, JobStateChangedEventArgs e)
        {
            Console.WriteLine("Job state changed event:");
            Console.WriteLine("  Previous state: " + e.PreviousState);
            Console.WriteLine("  Current state: " + e.CurrentState);

            switch (e.CurrentState)
            {
                case JobState.Finished:
                    Console.WriteLine();
                    Console.WriteLine("Job is finished.");
                    Console.WriteLine();
                    break;
                case JobState.Canceling:
                case JobState.Queued:
                case JobState.Scheduled:
                case JobState.Processing:
                    Console.WriteLine("Please wait...\n");
                    break;
                case JobState.Canceled:
                case JobState.Error:
                    // Cast sender as a job.
                    IJob job = (IJob)sender;
                    // Display or log error details as needed.
                    // LogJobStop(job.Id);
                    break;
                default:
                    break;
            }
        }
    }
}

后续步骤

媒体服务 v3(最新版本)

查看最新版本的 Azure 媒体服务!

媒体服务 v2(旧版)

提供反馈

使用 用户之声 论坛提供反馈意见,并提出有关如何改进 Azure 媒体服务的建议。 还可以直接转到以下类别之一:

Azure 媒体服务分析概述

Azure 媒体分析演示