将人脸数据迁移到其他人脸订阅Migrate your face data to a different Face subscription

本指南介绍如何将人脸数据(例如包含人脸的已保存 PersonGroup 对象)转移到不同的 Azure 认知服务人脸 API 订阅。This guide shows you how to move face data, such as a saved PersonGroup object with faces, to a different Azure Cognitive Services Face API subscription. 若要移动数据,可以使用快照功能。To move the data, you use the Snapshot feature. 这样,在转移或扩展操作时就无需反复生成并训练 PersonGroup 或 FaceList 对象。This way you avoid having to repeatedly build and train a PersonGroup or FaceList object when you move or expand your operations. 例如,你可能已使用试用订阅创建了一个 PersonGroup 对象,现在想要将它迁移到付费的订阅。For example, perhaps you created a PersonGroup object by using a trial subscription and now want to migrate it to your paid subscription. 或者,你可能需要跨区域同步人脸数据,以执行大规模的企业操作。Or you might need to sync face data across regions for a large enterprise operation.

此迁移策略同样适用于 LargePersonGroup 和 LargeFaceList 对象。This same migration strategy also applies to LargePersonGroup and LargeFaceList objects. 如果你不熟悉本指南中的概念,请查看人脸识别概念指南中的相关定义。If you aren't familiar with the concepts in this guide, see their definitions in the Face recognition concepts guide. 本指南结合使用人脸 API .NET 客户端库与 C#。This guide uses the Face API .NET client library with C#.

先决条件Prerequisites

需要准备好以下各项:You need the following items:

  • 两个人脸 API 订阅密钥,其中一个包含现有数据,另一个是迁移目标。Two Face API subscription keys, one with the existing data and one to migrate to. 若要订阅人脸 API 服务并获取密钥,请遵照创建认知服务帐户中的说明操作。To subscribe to the Face API service and get your key, follow the instructions in Create a Cognitive Services account.
  • 对应于目标订阅的人脸 API 订阅 ID 字符串。The Face API subscription ID string that corresponds to the target subscription. 在 Azure 门户中选择“概述”可以找到该字符串。 To find it, select Overview in the Azure portal.
  • 任何版本的 Visual Studio 2015 或 2017Any edition of Visual Studio 2015 or 2017.

创建 Visual Studio 项目Create the Visual Studio project

本指南使用一个简单的控制台应用来运行人脸数据迁移。This guide uses a simple console app to run the face data migration. 有关完整的实现,请参阅 GitHub 上的人脸 API 快照示例For a full implementation, see the Face API snapshot sample on GitHub.

  1. 在 Visual Studio 中创建新的控制台应用 .NET Framework 项目。In Visual Studio, create a new Console app .NET Framework project. 将其命名为 FaceApiSnapshotSampleName it FaceApiSnapshotSample.
  2. 获取所需的 NuGet 包。Get the required NuGet packages. 在解决方案资源管理器中,右键单击该项目并选择“管理 NuGet 包” 。Right-click your project in the Solution Explorer, and select Manage NuGet Packages. 选择“浏览”选项卡,然后选择“包括预发行版” 。Select the Browse tab, and select Include prerelease. 找到并安装以下包:Find and install the following package:

创建人脸客户端Create face clients

Program.csMain 方法中,创建两个 FaceClient 实例,分别对应于源订阅和目标订阅。In the Main method in Program.cs, create two FaceClient instances for your source and target subscriptions. 此示例使用“中国北部”区域的某个人脸订阅作为源,使用“中国北部”的某个订阅作为目标。This example uses a Face subscription in the China North region as the source and a China North subscription as the target. 此示例演示如何将数据从一个 Azure 区域迁移到另一个 Azure 区域。This example demonstrates how to migrate data from one Azure region to another. 如果订阅位于其他区域,请更改 Endpoint 字符串。If your subscriptions are in different regions, change the Endpoint strings.

var FaceClientChinaEast2 = new FaceClient(new ApiKeyServiceClientCredentials("<China East 2 Subscription Key>"))
    {
        Endpoint = "https://chinaeast2.api.cognitive.azure.cn/>"
    };

var FaceClientChinaNorth = new FaceClient(new ApiKeyServiceClientCredentials("<China North Subscription Key>"))
    {
        Endpoint = "https://chinanorth.api.cognitive.azure.cn/"
    };

填写源订阅和目标订阅的订阅密钥值与终结点 URL。Fill in the subscription key values and endpoint URLs for your source and target subscriptions.

让 PersonGroup 做好迁移准备Prepare a PersonGroup for migration

需要使用源订阅中 PersonGroup 的 ID 将它迁移到目标订阅。You need the ID of the PersonGroup in your source subscription to migrate it to the target subscription. 使用 PersonGroupOperationsExtensions.ListAsync 方法检索 PersonGroup 对象的列表。Use the PersonGroupOperationsExtensions.ListAsync method to retrieve a list of your PersonGroup objects. 然后获取 PersonGroup.PersonGroupId 属性。Then get the PersonGroup.PersonGroupId property. 此过程根据使用的 PersonGroup 对象而异。This process looks different based on what PersonGroup objects you have. 在本指南中,源 PersonGroup ID 存储在 personGroupId 中。In this guide, the source PersonGroup ID is stored in personGroupId.

Note

示例代码将创建并训练要迁移的新 PersonGroup。The sample code creates and trains a new PersonGroup to migrate. 在大多数情况下,你应该已有一个可用的 PersonGroup。In most cases, you should already have a PersonGroup to use.

创建 PersonGroup 的快照Take a snapshot of a PersonGroup

快照是特定人脸数据类型的临时远程存储。A snapshot is temporary remote storage for certain Face data types. 它可用作一种剪贴板,用于将数据从一个订阅复制到另一个订阅。It functions as a kind of clipboard to copy data from one subscription to another. 首先创建源订阅中数据的快照。First, you take a snapshot of the data in the source subscription. 然后将此快照应用到目标订阅中的新数据对象。Then you apply it to a new data object in the target subscription.

使用源订阅的 FaceClient 实例创建 PersonGroup 快照。Use the source subscription's FaceClient instance to take a snapshot of the PersonGroup. 请将 TakeAsync 与 PersonGroup ID 和目标订阅 ID 配合使用。Use TakeAsync with the PersonGroup ID and the target subscription's ID. 如果有多个目标订阅,请将其添加为第三个参数中的数组项。If you have multiple target subscriptions, add them as array entries in the third parameter.

var takeSnapshotResult = await FaceClientChinaEast2.Snapshot.TakeAsync(
    SnapshotObjectType.PersonGroup,
    personGroupId,
    new[] { "<Azure China North Subscription ID>" /* Put other IDs here, if multiple target subscriptions wanted */ });

Note

创建和应用快照的过程不会中断对源或者目标 PersonGroup 或 FaceList 的任何常规调用。The process of taking and applying snapshots doesn't disrupt any regular calls to the source or target PersonGroups or FaceLists. 请不要同时发出会更改源对象的调用,例如,FaceList 管理调用PersonGroup 训练调用。Don't make simultaneous calls that change the source object, such as FaceList management calls or the PersonGroup Train call, for example. 快照操作可能会先于或晚于这些操作运行,或者可能会遇到错误。The snapshot operation might run before or after those operations or might encounter errors.

检索快照 IDRetrieve the snapshot ID

用于创建快照的方法是异步的,因此必须等待该操作完成。The method used to take snapshots is asynchronous, so you must wait for its completion. 快照操作不可取消。Snapshot operations can't be canceled. 在以下代码中,WaitForOperation 方法监视异步调用。In this code, the WaitForOperation method monitors the asynchronous call. 它每隔 100 毫秒检查一次状态。It checks the status every 100 ms. 完成该操作后,通过分析 OperationLocation 字段来检索操作 ID。After the operation finishes, retrieve an operation ID by parsing the OperationLocation field.

var takeOperationId = Guid.Parse(takeSnapshotResult.OperationLocation.Split('/')[2]);
var operationStatus = await WaitForOperation(FaceClientChinaEast2, takeOperationId);

典型的 OperationLocation 值如下所示:A typical OperationLocation value looks like this:

"/operations/a63a3bdd-a1db-4d05-87b8-dbad6850062a"

WaitForOperation 帮助程序方法如下:The WaitForOperation helper method is here:

/// <summary>
/// Waits for the take/apply operation to complete and returns the final operation status.
/// </summary>
/// <returns>The final operation status.</returns>
private static async Task<OperationStatus> WaitForOperation(IFaceClient client, Guid operationId)
{
    OperationStatus operationStatus = null;
    do
    {
        if (operationStatus != null)
        {
            Thread.Sleep(TimeSpan.FromMilliseconds(100));
        }

        // Get the status of the operation.
        operationStatus = await client.Snapshot.GetOperationStatusAsync(operationId);

        Console.WriteLine($"Operation Status: {operationStatus.Status}");
    }
    while (operationStatus.Status != OperationStatusType.Succeeded
            && operationStatus.Status != OperationStatusType.Failed);

    return operationStatus;
}

在操作状态显示为 Succeeded 后,通过分析返回的 OperationStatus 实例的 ResourceLocation 字段来获取快照 ID。After the operation status shows Succeeded, get the snapshot ID by parsing the ResourceLocation field of the returned OperationStatus instance.

var snapshotId = Guid.Parse(operationStatus.ResourceLocation.Split('/')[2]);

典型的 resourceLocation 值如下所示:A typical resourceLocation value looks like this:

"/snapshots/e58b3f08-1e8b-4165-81df-aa9858f233dc"

将快照应用到目标订阅Apply a snapshot to a target subscription

接下来,使用随机生成的 ID 在目标订阅中新建 PersonGroup。Next, create the new PersonGroup in the target subscription by using a randomly generated ID. 然后,使用目标订阅的 FaceClient 实例将快照应用到此 PersonGroup。Then use the target subscription's FaceClient instance to apply the snapshot to this PersonGroup. 传入快照 ID 和新的 PersonGroup ID。Pass in the snapshot ID and the new PersonGroup ID.

var newPersonGroupId = Guid.NewGuid().ToString();
var applySnapshotResult = await FaceClientChinaNorth.Snapshot.ApplyAsync(snapshotId, newPersonGroupId);

Note

快照对象仅在 48 小时内有效。A Snapshot object is valid for only 48 hours. 仅当你打算在不久后要使用某个快照进行数据迁移时,才创建该快照。Only take a snapshot if you intend to use it for data migration soon after.

快照应用请求将返回另一个操作 ID。A snapshot apply request returns another operation ID. 若要获取此 ID,请分析返回的 applySnapshotResult 实例的 OperationLocation 字段。To get this ID, parse the OperationLocation field of the returned applySnapshotResult instance.

var applyOperationId = Guid.Parse(applySnapshotResult.OperationLocation.Split('/')[2]);

由于快照应用过程也是异步的,因此请同样使用 WaitForOperation 来等待该过程完成。The snapshot application process is also asynchronous, so again use WaitForOperation to wait for it to finish.

operationStatus = await WaitForOperation(FaceClientChinaNorth, applyOperationId);

测试数据迁移Test the data migration

应用快照后,目标订阅中的新 PersonGroup 会填充原始人脸数据。After you apply the snapshot, the new PersonGroup in the target subscription populates with the original face data. 默认情况下,还会复制训练结果。By default, training results are also copied. 新的 PersonGroup 已准备好进行人脸识别调用,而无需重新训练。The new PersonGroup is ready for face identification calls without needing retraining.

若要测试数据迁移,请运行以下操作,并比较这些操作在控制台中列显的结果:To test the data migration, run the following operations and compare the results they print to the console:

await DisplayPersonGroup(FaceClientChinaEast2, personGroupId);
await IdentifyInPersonGroup(FaceClientChinaEast2, personGroupId);

await DisplayPersonGroup(FaceClientChinaNorth, newPersonGroupId);
// No need to retrain the person group before identification,
// training results are copied by snapshot as well.
await IdentifyInPersonGroup(FaceClientChinaNorth, newPersonGroupId);

使用以下帮助程序方法:Use the following helper methods:

private static async Task DisplayPersonGroup(IFaceClient client, string personGroupId)
{
    var personGroup = await client.PersonGroup.GetAsync(personGroupId);
    Console.WriteLine("Person Group:");
    Console.WriteLine(JsonConvert.SerializeObject(personGroup));

    // List persons.
    var persons = await client.PersonGroupPerson.ListAsync(personGroupId);

    foreach (var person in persons)
    {
        Console.WriteLine(JsonConvert.SerializeObject(person));
    }

    Console.WriteLine();
}
private static async Task IdentifyInPersonGroup(IFaceClient client, string personGroupId)
{
    using (var fileStream = new FileStream("data\\PersonGroup\\Daughter\\Daughter1.jpg", FileMode.Open, FileAccess.Read))
    {
        var detectedFaces = await client.Face.DetectWithStreamAsync(fileStream);

        var result = await client.Face.IdentifyAsync(detectedFaces.Select(face => face.FaceId.Value).ToList(), personGroupId);
        Console.WriteLine("Test identify against PersonGroup");
        Console.WriteLine(JsonConvert.SerializeObject(result));
        Console.WriteLine();
    }
}

现在可以使用目标订阅中的新 PersonGroup。Now you can use the new PersonGroup in the target subscription.

将来若要再次更新目标 PersonGroup,请创建一个新的 PersonGroup 用于接收快照。To update the target PersonGroup again in the future, create a new PersonGroup to receive the snapshot. 为此,请遵循本指南中的步骤。To do this, follow the steps in this guide. 一次只能向一个 PersonGroup 对象应用快照。A single PersonGroup object can have a snapshot applied to it only one time.

清理资源Clean up resources

迁移完人脸数据后,请手动删除快照对象。After you finish migrating face data, manually delete the snapshot object.

await FaceClientChinaEast2.Snapshot.DeleteAsync(snapshotId);

后续步骤Next steps

接下来,请参阅相关的 API 参考文档、浏览使用快照功能的示例应用,或遵循下面所述的操作指南开始使用其他 API 操作:Next, see the relevant API reference documentation, explore a sample app that uses the Snapshot feature, or follow a how-to guide to start using the other API operations mentioned here: