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

本指南介绍了如何使用快照功能将人脸数据(如已保存的人脸 PersonGroup)迁移到其他人脸 API 订阅。This guide shows you how to move face data (such as a saved PersonGroup of faces) to a different Face API subscription using the Snapshot feature. 这样一来,就不用在迁移或扩展操作时重复生成和训练 PersonGroup 或 FaceList 了。This allows you to avoid having to repeatedly build and train a PersonGroup or FaceList when moving or expanding your operations. 例如,你可能已使用试用订阅创建了 PersonGroup,现在要将它迁移到付费订阅,或者可能需要跨区域同步人脸数据,以便执行大规模的企业操作。For example, you may have created a PersonGroup using a trial subscription and now want to migrate it to your paid subscription, or you may 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 are not 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

  • 两个人脸 API 订阅密钥(一个包含现有数据,另一个是迁移目标)。Two Face API subscription keys (one with the existing data, and one to migrate to). 请按照创建认知服务帐户中的说明操作,订阅人脸 API 服务并获取密钥。Follow the instructions in Create a Cognitive Services account to subscribe to the Face API service and get your key.
  • 对应于目标订阅的人脸 API 订阅 ID 字符串(位于 Azure 门户上的“概览”边栏选项卡中)。The Face API subscription ID string corresponding to the target subscription (found in the Overview blade on the Azure portal).
  • 任何版本的 Visual Studio 2015 或 2017Any edition of Visual Studio 2015 or 2017.

创建 Visual Studio 项目Create the Visual Studio project

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

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

创建人脸客户端Create face clients

在 Program.cs 的 Main 方法中,创建两个 FaceClient 实例,分别对应于来源订阅和目标订阅。In the Main method in Program.cs, create two FaceClient instances for your source and target subscriptions. 此示例使用“中国东部 2”区域的人脸订阅作为来源订阅,并使用中国北部订阅作为目标订阅。In this example, we will use a Face subscription in the China East 2 region as the source, and a China North subscription as the target. 这会演示如何将数据从一个 Azure 区域迁移到另一个 Azure 区域。This will demonstrate how to migrate data from one Azure region to another. 如果订阅位于其他区域,需要更改 Endpoint 字符串。If your subscriptions are in different regions, you will need to 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。You will need to 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 对象列表;再获取 PersonGroup.PersonGroupId 属性。Use the PersonGroupOperationsExtensions.ListAsync method to retrieve a list of your PersonGroup objects; then get the PersonGroup.PersonGroupId property. 此过程因 PersonGroup 对象而异。This process will look different depending on what PersonGroup objects you have. 在本指南中,来源 PersonGroup ID 存储在 personGroupId 中。In the this guide, the source PersonGroup ID is stored in personGroupId.

Note

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

拍摄 PersonGroup 快照Take Snapshot of PersonGroup

快照是特定人脸数据类型的临时远程存储。A snapshot is a temporary remote storage for certain Face data types. 它可用作一种剪贴板,用于将数据从一个订阅复制到另一个订阅。It functions as a kind of clipboard to copy data from one subscription to another. 用户先“拍摄”来源订阅中数据的快照,再将快照“应用”到目标订阅中的新数据对象。First the user "takes" a snapshot of the data in the source subscription, and then they "apply" it to a new data object in the target subscription.

通过结合使用 TakeAsync 与 PersonGroup ID 和目标订阅 ID,使用来源订阅的 FaceClient 实例拍摄 PersonGroup 快照。Use the source subscription's FaceClient instance to take a snapshot of the PersonGroup, using TakeAsync with the PersonGroup ID and the target subscription's ID. 如果有多个目标订阅,可以将它们作为数组项添加到第三个参数中。If you have multiple target subscriptions, you can 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 will not disrupt any regular calls to the source or target PersonGroups (or FaceLists). 不过,不建议同时执行更改来源对象的调用(例如,FaceList 管理调用PersonGroup 训练调用),因为快照操作可能会先于或晚于这些操作执行,也可能会遇到错误。However, we do not recommend making simultaneous calls that change the source object (FaceList management calls or the PersonGroup Train call, for example), because the snapshot operation may execute before or after those operations or may encounter errors.

检索快照 IDRetrieve the Snapshot ID

由于快照拍摄方法是异步的,因此需要等待它完成(无法取消快照操作)。The snapshot taking method is asynchronous, so you'll need to wait for its completion (snapshot operations cannot be canceled). 在下面的代码中,WaitForOperation 方法监视异步调用,即每 100 毫秒检查一次状态。In this code, the WaitForOperation method monitors the asynchronous call, checking the status every 100ms. 当操作完成后,你便能检索操作 ID。When the operation completes, you will be able to retrieve an operation ID. 可以通过分析 OperationLocation 字段来获取 ID。You can obtain it by parsing the OperationLocation field.

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

典型的 OperationLocation 值如下所示:A typical OperationLocation value will look 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 了。When the operation status is marked as Succeeded, you can then 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 will look like this:

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

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

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

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

Note

快照对象仅在 48 小时内有效。A Snapshot object is only valid for 48 hours. 只有在打算不久后使用快照进行数据迁移时,才应拍摄快照。You should only take a snapshot if you intend to use it for data migration soon after.

快照应用请求会返回另一个操作 ID。A snapshot apply request will return another operation ID. 可以通过分析返回的 applySnapshotResult 实例的 OperationLocation 字段来获取此 ID。You can get this ID by parsing 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 complete.

operationStatus = await WaitForOperation(FaceClientChinaNorth, applyOperationId);

测试数据迁移Test the data migration

在快照应用后,目标订阅中的新 PersonGroup 应填充有原始人脸数据。After you've applied the snapshot, the new PersonGroup in the target subscription should be populated with the original face data. 默认情况下,还会复制训练结果。因此,新的 PersonGroup 可以执行人脸识别调用,无需重新训练。By default, training results are also copied, so the new PersonGroup will be ready for face identification calls without needing retraining.

若要测试数据迁移,可以执行下面的操作,并比较控制台中打印输出的结果。To test the data migration, you can 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 begin using the new PersonGroup in the target subscription.

日后若要再次更新目标 PersonGroup,需要新建用于接收快照的 PersonGroup(按照本指南中的步骤操作)。If you wish to update the target PersonGroup again in the future, you will need to create a new PersonGroup (following the steps of this guide) to receive the snapshot. 一次只能向一个 PersonGroup 对象应用快照。A single PersonGroup object can only have a snapshot applied to it one time.

清理资源Clean up resources

建议在完成人脸数据迁移后立即手动删除快照对象。Once you are finished migrating face data, we recommend you 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.