빠른 시작: Face 클라이언트 라이브러리 사용

.NET용 Face 클라이언트 라이브러리를 사용하여 얼굴 인식을 시작합니다. 이러한 단계에 따라 패키지를 설치하고 기본 작업을 위한 예제 코드를 사용해 봅니다. Face 서비스는 이미지에서 사람의 얼굴을 감지하고 인식하기 위한 고급 알고리즘에 대한 액세스를 제공합니다.

.NET용 Face 클라이언트 라이브러리를 사용하여 다음을 수행합니다.

참조 설명서 | 라이브러리 소스 코드 | 패키지(NuGet) | 샘플

사전 요구 사항

  • Azure 구독 - 체험 구독 만들기
  • Visual Studio IDE 또는 현재 버전의 .NET Core.
  • Azure 구독을 보유한 후에는 Azure Portal에서 Face 리소스 를 만들어 키와 엔드포인트를 가져옵니다. 배포 후 리소스로 이동 을 클릭합니다.
    • 애플리케이션을 Face API에 연결하려면 만든 리소스의 키와 엔드포인트가 필요합니다. 이 빠른 시작의 뒷부분에 나오는 코드에 키와 엔드포인트를 붙여넣습니다.
    • 평가판 가격 책정 계층(F0)을 통해 서비스를 사용해보고, 나중에 프로덕션용 유료 계층으로 업그레이드할 수 있습니다.

설치

새 C# 애플리케이션 만들기

Visual Studio를 사용하여 새 .NET Core 애플리케이션을 만듭니다.

클라이언트 라이브러리 설치

새 프로젝트를 만든 후 솔루션 탐색기 에서 프로젝트 솔루션을 마우스 오른쪽 단추로 클릭하고 NuGet 패키지 관리 를 선택하여 클라이언트 라이브러리를 설치합니다. 열리는 패키지 관리자에서 찾아보기 를 선택하고, 시험판 포함 을 선택하고, Microsoft.Azure.CognitiveServices.Vision.Face를 검색합니다. 2.7.0-preview.1 버전, 설치 를 차례로 선택합니다.

한 번에 전체 빠른 시작 코드 파일을 보시겠습니까? GitHub에서 찾을 수 있으며 이 빠른 시작의 코드 예제를 포함합니다.

프로젝트 디렉터리에서 program.cs 파일을 열고 using 지시문을 추가합니다.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.Azure.CognitiveServices.Vision.Face;
using Microsoft.Azure.CognitiveServices.Vision.Face.Models;

애플리케이션의 Program 클래스에서 리소스의 키 및 엔드포인트에 대한 변수를 만듭니다.

중요

Azure Portal로 이동합니다. 필수 구성 요소 섹션에서 만든 Face 리소스가 성공적으로 배포된 경우 다음 단계 아래에서 리소스로 이동 단추를 클릭합니다. 리소스 관리 아래에 있는 리소스의 키 및 엔드포인트 페이지에서 키 및 엔드포인트를 찾을 수 있습니다.

완료되면 코드에서 키를 제거하고 공개적으로 게시하지 마세요. 프로덕션의 경우 자격 증명을 안전하게 저장하고 액세스하는 방법을 사용하는 것이 좋습니다. 자세한 내용은 Cognitive Services 보안 문서를 참조하세요.

// From your Face subscription in the Azure portal, get your subscription key and endpoint.
const string SUBSCRIPTION_KEY = "<your subscription key>";
const string ENDPOINT = "<your api endpoint>";

애플리케이션의 Main 메서드에서 이 빠른 시작에 사용된 메서드에 대한 호출을 추가합니다. 이러한 기능은 나중에 구현합니다.

// Authenticate.
IFaceClient client = Authenticate(ENDPOINT, SUBSCRIPTION_KEY);

// Detect - get features from faces.
DetectFaceExtract(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait();
// Find Similar - find a similar face from a list of faces.
FindSimilar(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait();
// Verify - compare two images if the same person or not.
Verify(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait();

// Identify - recognize a face(s) in a person group (a person group is created in this example).
IdentifyInPersonGroup(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait();
// LargePersonGroup - create, then get data.
LargePersonGroup(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait();
// Group faces - automatically group similar faces.
Group(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait();
// FaceList - create a face list, then get data

개체 모델

Face .NET 클라이언트 라이브러리의 주요 기능 중 일부를 처리하는 클래스와 인터페이스는 다음과 같습니다.

Name Description
FaceClient 이 클래스는 Face 서비스를 사용할 수 있는 권한의 부여를 나타내며 모든 Face 기능에 필요합니다. 구독 정보를 사용하여 인스턴스화하고, 다른 클래스의 인스턴스를 생성하는 데 사용합니다.
FaceOperations 이 클래스는 사람 얼굴을 사용하여 수행할 수 있는 기본 감지 및 인식 작업을 처리합니다.
DetectedFace 이 클래스는 이미지의 한 얼굴에서 감지된 모든 데이터를 나타냅니다. 얼굴에 대한 자세한 정보를 검색하는 데 사용할 수 있습니다.
FaceListOperations 이 클래스는 분류된 얼굴 세트를 저장하는 클라우드 저장 FaceList 구문을 관리합니다.
PersonGroupPersonExtensions 이 클래스는 한 사람에게 속한 얼굴 세트를 저장하는 클라우드 저장 Person 구문을 관리합니다.
PersonGroupOperations 이 클래스는 분류된 Person 개체 세트를 저장하는 클라우드 저장 PersonGroup 구문을 관리합니다.

코드 예제

아래 코드 조각에서는 .NET용 Face 클라이언트 라이브러리를 사용하여 다음 작업을 수행하는 방법을 보여 줍니다.

클라이언트 인증

새 메서드에서 엔드포인트 및 키를 사용하여 클라이언트를 인스턴스화합니다. 키를 사용하여 ApiKeyServiceClientCredentials 개체를 만들고, 엔드포인트에서 이를 사용하여 FaceClient 개체를 만듭니다.

/*
 *	AUTHENTICATE
 *	Uses subscription key and region to create a client.
 */
public static IFaceClient Authenticate(string endpoint, string key)
{
    return new FaceClient(new ApiKeyServiceClientCredentials(key)) { Endpoint = endpoint };
}

도우미 필드 선언

다음 필드는 나중에 추가할 몇 가지 얼굴 작업에 필요합니다. Program 클래스의 루트에서 다음 URL 문자열을 정의합니다. 이 URL은 샘플 이미지 폴더를 가리킵니다.

// Used for all examples.
// URL for the images.
const string IMAGE_BASE_URL = "https://csdx.blob.core.windows.net/resources/Face/Images/";

Main 메서드에서 다른 인식 모델 유형을 가리키는 문자열을 정의합니다. 나중에 얼굴 감지에 사용할 인식 모델을 지정할 수 있습니다. 이러한 옵션에 대한 자세한 내용은 인식 모델 지정을 참조하세요.

// Recognition model 4 was released in 2021 February.
// It is recommended since its accuracy is improved
// on faces wearing masks compared with model 3,
// and its overall accuracy is improved compared
// with models 1 and 2.
const string RECOGNITION_MODEL4 = RecognitionModel.Recognition04;

이미지에서 얼굴 감지

검색된 얼굴 개체 가져오기

얼굴을 감지하는 새 메서드를 만듭니다. DetectFaceExtract 메서드는 지정된 URL에서 세 개의 이미지를 처리하고 DetectedFace 개체의 목록을 프로그램 메모리에 만듭니다. FaceAttributeType 값 목록은 추출할 기능을 지정합니다.

/* 
 * DETECT FACES
 * Detects features from faces and IDs them.
 */
public static async Task DetectFaceExtract(IFaceClient client, string url, string recognitionModel)
{
    Console.WriteLine("========DETECT FACES========");
    Console.WriteLine();

    // Create a list of images
    List<string> imageFileNames = new List<string>
                    {
                        "detection1.jpg",    // single female with glasses
                        // "detection2.jpg", // (optional: single man)
                        // "detection3.jpg", // (optional: single male construction worker)
                        // "detection4.jpg", // (optional: 3 people at cafe, 1 is blurred)
                        "detection5.jpg",    // family, woman child man
                        "detection6.jpg"     // elderly couple, male female
                    };

    foreach (var imageFileName in imageFileNames)
    {
        IList<DetectedFace> detectedFaces;

        // Detect faces with all attributes from image url.
        detectedFaces = await client.Face.DetectWithUrlAsync($"{url}{imageFileName}",
                returnFaceAttributes: new List<FaceAttributeType?> { FaceAttributeType.Accessories, FaceAttributeType.Age,
                FaceAttributeType.Blur, FaceAttributeType.Emotion, FaceAttributeType.Exposure, FaceAttributeType.FacialHair,
                FaceAttributeType.Gender, FaceAttributeType.Glasses, FaceAttributeType.Hair, FaceAttributeType.HeadPose,
                FaceAttributeType.Makeup, FaceAttributeType.Noise, FaceAttributeType.Occlusion, FaceAttributeType.Smile },
                // We specify detection model 1 because we are retrieving attributes.
                detectionModel: DetectionModel.Detection01,
                recognitionModel: recognitionModel);

        Console.WriteLine($"{detectedFaces.Count} face(s) detected from image `{imageFileName}`.");

로컬 이미지에서 얼굴을 검색할 수도 있습니다. IFaceOperations 메서드(예: DetectWithStreamAsync)를 참조하세요.

검색된 얼굴 데이터 표시

나머지 DetectFaceExtract 메서드는 검색된 각 얼굴에 대한 특성 데이터를 구문 분석하고 출력합니다. 각 특성은 원래 얼굴 검색 API 호출( FaceAttributeType 목록의)에서 별도로 지정해야 합니다. 다음 코드는 모든 특성을 처리하지만 하나 또는 몇 가지를 사용해야 할 가능성이 높습니다.

        // Parse and print all attributes of each detected face.
        foreach (var face in detectedFaces)
        {
            Console.WriteLine($"Face attributes for {imageFileName}:");

            // Get bounding box of the faces
            Console.WriteLine($"Rectangle(Left/Top/Width/Height) : {face.FaceRectangle.Left} {face.FaceRectangle.Top} {face.FaceRectangle.Width} {face.FaceRectangle.Height}");

            // Get accessories of the faces
            List<Accessory> accessoriesList = (List<Accessory>)face.FaceAttributes.Accessories;
            int count = face.FaceAttributes.Accessories.Count;
            string accessory; string[] accessoryArray = new string[count];
            if (count == 0) { accessory = "NoAccessories"; }
            else
            {
                for (int i = 0; i < count; ++i) { accessoryArray[i] = accessoriesList[i].Type.ToString(); }
                accessory = string.Join(",", accessoryArray);
            }
            Console.WriteLine($"Accessories : {accessory}");

            // Get face other attributes
            Console.WriteLine($"Age : {face.FaceAttributes.Age}");
            Console.WriteLine($"Blur : {face.FaceAttributes.Blur.BlurLevel}");

            // Get emotion on the face
            string emotionType = string.Empty;
            double emotionValue = 0.0;
            Emotion emotion = face.FaceAttributes.Emotion;
            if (emotion.Anger > emotionValue) { emotionValue = emotion.Anger; emotionType = "Anger"; }
            if (emotion.Contempt > emotionValue) { emotionValue = emotion.Contempt; emotionType = "Contempt"; }
            if (emotion.Disgust > emotionValue) { emotionValue = emotion.Disgust; emotionType = "Disgust"; }
            if (emotion.Fear > emotionValue) { emotionValue = emotion.Fear; emotionType = "Fear"; }
            if (emotion.Happiness > emotionValue) { emotionValue = emotion.Happiness; emotionType = "Happiness"; }
            if (emotion.Neutral > emotionValue) { emotionValue = emotion.Neutral; emotionType = "Neutral"; }
            if (emotion.Sadness > emotionValue) { emotionValue = emotion.Sadness; emotionType = "Sadness"; }
            if (emotion.Surprise > emotionValue) { emotionType = "Surprise"; }
            Console.WriteLine($"Emotion : {emotionType}");

            // Get more face attributes
            Console.WriteLine($"Exposure : {face.FaceAttributes.Exposure.ExposureLevel}");
            Console.WriteLine($"FacialHair : {string.Format("{0}", face.FaceAttributes.FacialHair.Moustache + face.FaceAttributes.FacialHair.Beard + face.FaceAttributes.FacialHair.Sideburns > 0 ? "Yes" : "No")}");
            Console.WriteLine($"Gender : {face.FaceAttributes.Gender}");
            Console.WriteLine($"Glasses : {face.FaceAttributes.Glasses}");

            // Get hair color
            Hair hair = face.FaceAttributes.Hair;
            string color = null;
            if (hair.HairColor.Count == 0) { if (hair.Invisible) { color = "Invisible"; } else { color = "Bald"; } }
            HairColorType returnColor = HairColorType.Unknown;
            double maxConfidence = 0.0f;
            foreach (HairColor hairColor in hair.HairColor)
            {
                if (hairColor.Confidence <= maxConfidence) { continue; }
                maxConfidence = hairColor.Confidence; returnColor = hairColor.Color; color = returnColor.ToString();
            }
            Console.WriteLine($"Hair : {color}");

            // Get more attributes
            Console.WriteLine($"HeadPose : {string.Format("Pitch: {0}, Roll: {1}, Yaw: {2}", Math.Round(face.FaceAttributes.HeadPose.Pitch, 2), Math.Round(face.FaceAttributes.HeadPose.Roll, 2), Math.Round(face.FaceAttributes.HeadPose.Yaw, 2))}");
            Console.WriteLine($"Makeup : {string.Format("{0}", (face.FaceAttributes.Makeup.EyeMakeup || face.FaceAttributes.Makeup.LipMakeup) ? "Yes" : "No")}");
            Console.WriteLine($"Noise : {face.FaceAttributes.Noise.NoiseLevel}");
            Console.WriteLine($"Occlusion : {string.Format("EyeOccluded: {0}", face.FaceAttributes.Occlusion.EyeOccluded ? "Yes" : "No")} " +
                $" {string.Format("ForeheadOccluded: {0}", face.FaceAttributes.Occlusion.ForeheadOccluded ? "Yes" : "No")}   {string.Format("MouthOccluded: {0}", face.FaceAttributes.Occlusion.MouthOccluded ? "Yes" : "No")}");
            Console.WriteLine($"Smile : {face.FaceAttributes.Smile}");
            Console.WriteLine();
        }
    }
}

유사 얼굴 찾기

다음 코드에서는 감지된 하나의 얼굴(원본)을 가져오고, 다른 얼굴(대상) 세트를 검색하여 일치 항목을 찾습니다(이미지별 얼굴 검색). 일치 항목을 찾으면 일치하는 얼굴의 ID를 콘솔에 출력합니다.

비교할 얼굴 감지

먼저 두 번째 얼굴 감지 메서드를 정의합니다. 이미지를 비교하기 전에 이미지에서 얼굴을 감지해야 하며, 이 감지 메서드는 비교 작업에 최적화되어 있습니다. 위의 섹션과 같이 자세한 얼굴 특성을 추출하지 않으며 다른 인식 모델을 사용합니다.

private static async Task<List<DetectedFace>> DetectFaceRecognize(IFaceClient faceClient, string url, string recognition_model)
{
    // Detect faces from image URL. Since only recognizing, use the recognition model 1.
    // We use detection model 3 because we are not retrieving attributes.
    IList<DetectedFace> detectedFaces = await faceClient.Face.DetectWithUrlAsync(url, recognitionModel: recognition_model, detectionModel: DetectionModel.Detection03);
    Console.WriteLine($"{detectedFaces.Count} face(s) detected from image `{Path.GetFileName(url)}`");
    return detectedFaces.ToList();
}

일치 항목 찾기

다음 메서드는 대상 이미지 세트와 단일 원본 이미지에서 얼굴을 감지합니다. 그런 다음, 이를 비교하여 원본 이미지와 유사한 모든 대상 이미지를 찾습니다.

/*
 * FIND SIMILAR
 * This example will take an image and find a similar one to it in another image.
 */
public static async Task FindSimilar(IFaceClient client, string url, string recognition_model)
{
    Console.WriteLine("========FIND SIMILAR========");
    Console.WriteLine();

    List<string> targetImageFileNames = new List<string>
                        {
                            "Family1-Dad1.jpg",
                            "Family1-Daughter1.jpg",
                            "Family1-Mom1.jpg",
                            "Family1-Son1.jpg",
                            "Family2-Lady1.jpg",
                            "Family2-Man1.jpg",
                            "Family3-Lady1.jpg",
                            "Family3-Man1.jpg"
                        };

    string sourceImageFileName = "findsimilar.jpg";
    IList<Guid?> targetFaceIds = new List<Guid?>();
    foreach (var targetImageFileName in targetImageFileNames)
    {
        // Detect faces from target image url.
        var faces = await DetectFaceRecognize(client, $"{url}{targetImageFileName}", recognition_model);
        // Add detected faceId to list of GUIDs.
        targetFaceIds.Add(faces[0].FaceId.Value);
    }

    // Detect faces from source image url.
    IList<DetectedFace> detectedFaces = await DetectFaceRecognize(client, $"{url}{sourceImageFileName}", recognition_model);
    Console.WriteLine();

    // Find a similar face(s) in the list of IDs. Comapring only the first in list for testing purposes.
    IList<SimilarFace> similarResults = await client.Face.FindSimilarAsync(detectedFaces[0].FaceId.Value, null, null, targetFaceIds);

다음 코드에서는 일치 항목 세부 정보를 콘솔에 출력합니다.

foreach (var similarResult in similarResults)
{
    Console.WriteLine($"Faces from {sourceImageFileName} & ID:{similarResult.FaceId} are similar with confidence: {similarResult.Confidence}.");
}
Console.WriteLine();

얼굴 식별

Identify(식별) 작업은 사람(또는 여러 사람)의 이미지를 가져와서 이미지에서 각 얼굴의 ID를 찾습니다(얼굴 인식 검색). 감지된 각 얼굴을 얼굴 특징이 알려진 다른 Person 개체의 데이터베이스인 PersonGroup 과 비교합니다. 식별 작업을 수행하려면 먼저 PersonGroup 을 만들고 학습해야 합니다.

PersonGroup 만들기

다음 코드에서는 6개의 서로 다른 Person 개체를 사용하여 PersonGroup 을 만듭니다. 각 Person 을 예제 이미지 세트와 연결한 다음, 해당 얼굴 특성을 통해 각 사람을 인식하도록 학습시킵니다. PersonPersonGroup 개체는 Verify(검증), Identify(식별) 및 Group(그룹) 작업에 사용됩니다.

PersonGroup 의 ID를 나타내도록 클래스의 루트에서 문자열 변수를 선언합니다.

static string personGroupId = Guid.NewGuid().ToString();

새 메서드에서 다음 코드를 추가합니다. 이 메서드는 식별 작업을 수행합니다. 첫 번째 코드 블록은 사람의 이름을 해당 예제 이미지와 연결합니다.

public static async Task IdentifyInPersonGroup(IFaceClient client, string url, string recognitionModel)
{
    Console.WriteLine("========IDENTIFY FACES========");
    Console.WriteLine();

    // Create a dictionary for all your images, grouping similar ones under the same key.
    Dictionary<string, string[]> personDictionary =
        new Dictionary<string, string[]>
            { { "Family1-Dad", new[] { "Family1-Dad1.jpg", "Family1-Dad2.jpg" } },
              { "Family1-Mom", new[] { "Family1-Mom1.jpg", "Family1-Mom2.jpg" } },
              { "Family1-Son", new[] { "Family1-Son1.jpg", "Family1-Son2.jpg" } },
              { "Family1-Daughter", new[] { "Family1-Daughter1.jpg", "Family1-Daughter2.jpg" } },
              { "Family2-Lady", new[] { "Family2-Lady1.jpg", "Family2-Lady2.jpg" } },
              { "Family2-Man", new[] { "Family2-Man1.jpg", "Family2-Man2.jpg" } }
            };
    // A group photo that includes some of the persons you seek to identify from your dictionary.
    string sourceImageFileName = "identification1.jpg";

이 코드는 sourceImageFileName 변수를 정의합니다. 이 변수는 식별할 사람이 포함된 원본 이미지에 해당합니다.

다음으로, 다음 코드를 추가하여 Dictionary(사전)의 각 사람에 대한 Person 개체를 만들고 적절한 이미지에서 얼굴 데이터를 추가합니다. 각 Person 개체는 고유 ID 문자열을 통해 동일한 PersonGroup 과 연결됩니다. client, urlRECOGNITION_MODEL1 변수를 이 메서드에 전달해야 합니다.

// Create a person group. 
Console.WriteLine($"Create a person group ({personGroupId}).");
await client.PersonGroup.CreateAsync(personGroupId, personGroupId, recognitionModel: recognitionModel);
// The similar faces will be grouped into a single person group person.
foreach (var groupedFace in personDictionary.Keys)
{
    // Limit TPS
    await Task.Delay(250);
    Person person = await client.PersonGroupPerson.CreateAsync(personGroupId: personGroupId, name: groupedFace);
    Console.WriteLine($"Create a person group person '{groupedFace}'.");

    // Add face to the person group person.
    foreach (var similarImage in personDictionary[groupedFace])
    {
        Console.WriteLine($"Add face to the person group person({groupedFace}) from image `{similarImage}`");
        PersistedFace face = await client.PersonGroupPerson.AddFaceFromUrlAsync(personGroupId, person.PersonId,
            $"{url}{similarImage}", similarImage);
    }
}

로컬 이미지에서 PersonGroup 을 만들 수도 있습니다. IPersonGroupPerson 메서드(예: AddFaceFromStreamAsync)를 참조하세요.

PersonGroup 학습

이미지에서 얼굴 데이터를 추출하여 다른 Person 개체에 정렬했으면 각 Person 개체와 연결된 시각적 기능을 식별하도록 PersonGroup 을 학습시켜야 합니다. 다음 코드에서는 비동기 train 메서드를 호출하고, 결과를 폴링하여 상태를 콘솔에 출력합니다.

// Start to train the person group.
Console.WriteLine();
Console.WriteLine($"Train person group {personGroupId}.");
await client.PersonGroup.TrainAsync(personGroupId);

// Wait until the training is completed.
while (true)
{
    await Task.Delay(1000);
    var trainingStatus = await client.PersonGroup.GetTrainingStatusAsync(personGroupId);
    Console.WriteLine($"Training status: {trainingStatus.Status}.");
    if (trainingStatus.Status == TrainingStatusType.Succeeded) { break; }
}
Console.WriteLine();

Face API는 기본적으로 정적인 사전 빌드된 모델 세트에서 실행됩니다(서비스가 실행될 때 모델의 성능이 저하되거나 향상되지 않음). Microsoft에서 완전히 새로운 모델 버전으로 마이그레이션하지 않고 모델의 백엔드를 업데이트하면 모델이 생성하는 결과가 변경될 수 있습니다. 최신 버전의 모델을 사용하려면 PersonGroup 을 동일한 등록 이미지를 가진 매개 변수로 지정하여 다시 학습할 수 있습니다.

이제 이 Person 그룹 및 연결된 해당 Person 개체는 Verify(검증), Identify(식별) 또는 Group(그룹) 작업에 사용할 수 있습니다.

얼굴 식별

다음 코드에서는 원본 이미지를 가져와서 이미지에서 감지된 모든 얼굴의 목록을 만듭니다. 이러한 얼굴은 PersonGroup 과 비교하여 식별되는 얼굴입니다.

List<Guid?> sourceFaceIds = new List<Guid?>();
// Detect faces from source image url.
List<DetectedFace> detectedFaces = await DetectFaceRecognize(client, $"{url}{sourceImageFileName}", recognitionModel);

// Add detected faceId to sourceFaceIds.
foreach (var detectedFace in detectedFaces) { sourceFaceIds.Add(detectedFace.FaceId.Value); }

다음 코드 조각에서는 IdentifyAsync 작업을 호출하고 결과를 콘솔에 출력합니다. 여기서는 서비스에서 원본 이미지의 각 얼굴을 지정된 PersonGroupPerson 과 일치시키려고 합니다. 이렇게 하면 Identify 메서드가 종료됩니다.

    // Identify the faces in a person group. 
    var identifyResults = await client.Face.IdentifyAsync(sourceFaceIds, personGroupId);

    foreach (var identifyResult in identifyResults)
    {
        Person person = await client.PersonGroupPerson.GetAsync(personGroupId, identifyResult.Candidates[0].PersonId);
        Console.WriteLine($"Person '{person.Name}' is identified for face in: {sourceImageFileName} - {identifyResult.FaceId}," +
            $" confidence: {identifyResult.Candidates[0].Confidence}.");
    }
    Console.WriteLine();
}

애플리케이션 실행

IDE 창의 위쪽에서 디버그 단추를 클릭하여 애플리케이션을 실행합니다.

리소스 정리

Cognitive Services 구독을 정리하고 제거하려면 리소스나 리소스 그룹을 삭제하면 됩니다. 리소스 그룹을 삭제하면 해당 리소스 그룹에 연결된 다른 모든 리소스가 함께 삭제됩니다.

이 빠른 시작에서는 PersonGroup 을 만들었으며, 이를 삭제하려면 프로그램에서 다음 코드를 실행합니다.

// At end, delete person groups in both regions (since testing only)
Console.WriteLine("========DELETE PERSON GROUP========");
Console.WriteLine();
DeletePersonGroup(client, personGroupId).Wait();

다음 코드를 사용하여 삭제 메서드를 정의합니다.

/*
 * DELETE PERSON GROUP
 * After this entire example is executed, delete the person group in your Azure account,
 * otherwise you cannot recreate one with the same name (if running example repeatedly).
 */
public static async Task DeletePersonGroup(IFaceClient client, String personGroupId)
{
    await client.PersonGroup.DeleteAsync(personGroupId);
    Console.WriteLine($"Deleted the person group {personGroupId}.");
}

다음 단계

이 빠른 시작에서는 .NET용 Face 클라이언트 라이브러리를 사용하여 기본 얼굴 인식 작업을 수행하는 방법을 알아보았습니다. 다음으로 라이브러리에 대해 자세히 알아보려면 참조 설명서를 살펴보세요.

Go용 Face 클라이언트 라이브러리를 사용하여 얼굴 인식을 시작합니다. 이러한 단계에 따라 패키지를 설치하고 기본 작업을 위한 예제 코드를 사용해 봅니다. Face 서비스는 이미지에서 사람의 얼굴을 감지하고 인식하기 위한 고급 알고리즘에 대한 액세스를 제공합니다.

Go용 Face 서비스 클라이언트 라이브러리를 사용하여 다음을 수행합니다.

참조 설명서 | 라이브러리 소스 코드 | SDK 다운로드

필수 구성 요소

  • 최신 버전의 Go
  • Azure 구독 - 체험 구독 만들기
  • Azure 구독을 보유한 후에는 Azure Portal에서 Face 리소스 를 만들어 키와 엔드포인트를 가져옵니다. 배포 후 리소스로 이동 을 클릭합니다.
    • 애플리케이션을 Face API에 연결하려면 만든 리소스의 키와 엔드포인트가 필요합니다. 이 빠른 시작의 뒷부분에 나오는 코드에 키와 엔드포인트를 붙여넣습니다.
    • 평가판 가격 책정 계층(F0)을 통해 서비스를 사용해보고, 나중에 프로덕션용 유료 계층으로 업그레이드할 수 있습니다.
  • 키와 엔드포인트를 가져온 후에는 각각 FACE_SUBSCRIPTION_KEYFACE_ENDPOINT라는 키 및 엔드포인트에 대한 환경 변수를 만듭니다.

설치

Go 프로젝트 디렉터리 만들기

콘솔 창(cmd, PowerShell, 터미널, Bash)에서 Go 프로젝트에 대한 새 작업 영역 my-app을 만들고 해당 작업 영역으로 이동합니다.

mkdir -p my-app/{src, bin, pkg}  
cd my-app

작업 영역에는 다음 세 개의 폴더가 있습니다.

  • src - 이 디렉터리에는 소스 코드와 패키지가 포함됩니다. go get 명령으로 설치된 패키지는 이 디렉터리에 있습니다.
  • pkg - 이 디렉터리에는 컴파일된 Go 패키지 개체가 포함됩니다. 이러한 파일의 확장명은 모두 .a입니다.
  • bin - 이 디렉터리에는 go install을 실행할 때 만들어지는 이진 실행 파일이 포함됩니다.

Go 작업 영역의 구조에 대한 자세한 내용은 Go 언어 설명서를 참조하세요. 이 가이드에는 $GOPATH$GOROOT 설정에 대한 정보가 있습니다.

Go용 클라이언트 라이브러리 설치

다음으로, Go용 클라이언트 라이브러리를 설치합니다.

go get -u github.com/Azure/azure-sdk-for-go/tree/master/services/cognitiveservices/v1.0/face

dep를 사용하는 경우에는 리포지토리 내에서 다음을 실행합니다.

dep ensure -add https://github.com/Azure/azure-sdk-for-go/tree/master/services/cognitiveservices/v1.0/face

Go 애플리케이션 빌드

다음으로, src 디렉터리에 sample-app.go라는 파일을 만듭니다.

cd src
touch sample-app.go

원하는 IDE 또는 텍스트 편집기에서 sample-app.go를 엽니다. 그런 다음, 패키지 이름을 추가하고 다음 라이브러리를 가져옵니다.

package main

import (
    "encoding/json"
    "container/list"
    "context"
    "fmt"
    "github.com/Azure/azure-sdk-for-go/services/cognitiveservices/v1.0/face"
    "github.com/Azure/go-autorest/autorest"
    "github.com/satori/go.uuid"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path"
    "strconv"
    "strings"
    "time"
)

다음으로, 다른 Face 서비스 작업을 수행하는 코드를 추가하겠습니다.

개체 모델

Face 서비스 Go 클라이언트 라이브러리의 주요 기능 중 일부를 처리하는 클래스와 인터페이스는 다음과 같습니다.

Name Description
BaseClient 이 클래스는 Face 서비스를 사용할 수 있는 권한의 부여를 나타내며 모든 Face 기능에 필요합니다. 구독 정보를 사용하여 인스턴스화하고, 다른 클래스의 인스턴스를 생성하는 데 사용합니다.
클라이언트 이 클래스는 사람 얼굴을 사용하여 수행할 수 있는 기본 감지 및 인식 작업을 처리합니다.
DetectedFace 이 클래스는 이미지의 한 얼굴에서 감지된 모든 데이터를 나타냅니다. 얼굴에 대한 자세한 정보를 검색하는 데 사용할 수 있습니다.
ListClient 이 클래스는 분류된 얼굴 세트를 저장하는 클라우드 저장 FaceList 구문을 관리합니다.
PersonGroupPersonClient 이 클래스는 한 사람에게 속한 얼굴 세트를 저장하는 클라우드 저장 Person 구문을 관리합니다.
PersonGroupClient 이 클래스는 분류된 Person 개체 세트를 저장하는 클라우드 저장 PersonGroup 구문을 관리합니다.
SnapshotClient 이 클래스는 스냅샷 기능을 관리합니다. 이를 사용하여 모든 클라우드 기반 Face 데이터를 임시로 저장하고, 해당 데이터를 새 Azure 구독으로 마이그레이션할 수 있습니다.

코드 예제

다음 코드 샘플에서는 Go용 Face 서비스 클라이언트 라이브러리를 사용하여 기본 작업을 완료하는 방법을 보여줍니다.

클라이언트 인증

참고

이 빠른 시작에서는 각각 FACE_SUBSCRIPTION_KEYFACE_ENDPOINT라는 Face 키 및 엔드포인트에 대한 환경 변수를 만들었다고 가정합니다.

main 함수를 만들고, 클라이언트를 엔드포인트 및 키로 인스턴스화하는 다음 코드를 이 함수에 추가합니다. 키를 사용하여 CognitiveServicesAuthorizer 개체를 만들고, 엔드포인트에서 이 개체를 사용하여 Client 개체를 만듭니다. 또한 이 코드는 클라이언트 개체를 만드는 데 필요한 컨텍스트 개체를 인스턴스화합니다. 뿐만 아니라 이 빠른 시작의 샘플 이미지 중 일부가 있는 원격 위치를 정의합니다.

func main() {

    // A global context for use in all samples
    faceContext := context.Background()

    // Base url for the Verify and Large Face List examples
    const imageBaseURL = "https://csdx.blob.core.windows.net/resources/Face/Images/"

    /*
    Authenticate
    */
    // Add FACE_SUBSCRIPTION_KEY, FACE_ENDPOINT, and AZURE_SUBSCRIPTION_ID to your environment variables.
    subscriptionKey := os.Getenv("FACE_SUBSCRIPTION_KEY")
    endpoint := os.Getenv("FACE_ENDPOINT")

    // Client used for Detect Faces, Find Similar, and Verify examples.
    client := face.NewClient(endpoint)
    client.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscriptionKey)
    /*
    END - Authenticate
    */

이미지에서 얼굴 감지

main 메서드에 다음 코드를 추가합니다. 이 코드는 원격 샘플 이미지를 정의하고 이미지에서 추출할 얼굴 특징을 지정합니다. 또한 감지된 얼굴에서 데이터를 추출하는 데 사용할 AI 모델을 지정합니다. 이러한 옵션에 대한 자세한 내용은 인식 모델 지정을 참조하세요. 마지막으로, DetectWithURL 메서드는 이미지에서 얼굴 검색 작업을 수행하고 그 결과를 프로그램 메모리에 저장합니다.

// Detect a face in an image that contains a single face
singleFaceImageURL := "https://www.biography.com/.image/t_share/MTQ1MzAyNzYzOTgxNTE0NTEz/john-f-kennedy---mini-biography.jpg" 
singleImageURL := face.ImageURL { URL: &singleFaceImageURL } 
singleImageName := path.Base(singleFaceImageURL)
// Array types chosen for the attributes of Face
attributes := []face.AttributeType {"age", "emotion", "gender"}
returnFaceID := true
returnRecognitionModel := false
returnFaceLandmarks := false

// API call to detect faces in single-faced image, using recognition model 4
// We specify detection model 1 because we are retrieving attributes.
detectSingleFaces, dErr := client.DetectWithURL(faceContext, singleImageURL, &returnFaceID, &returnFaceLandmarks, attributes, face.Recognition04, &returnRecognitionModel, face.Detection01)
if dErr != nil { log.Fatal(dErr) }

// Dereference *[]DetectedFace, in order to loop through it.
dFaces := *detectSingleFaces.Value

로컬 이미지에서 얼굴을 검색할 수도 있습니다. 클라이언트 메서드(예: DetectWithStream)를 참조하세요.

검색된 얼굴 데이터 표시

코드의 그 다음 블록은 DetectedFace 개체 배열의 첫 번째 요소를 가져와서 해당 특성을 콘솔에 출력합니다. 여러 얼굴에 이미지를 사용한 경우 그 대신 배열을 반복해야 합니다.

fmt.Println("Detected face in (" + singleImageName + ") with ID(s): ")
fmt.Println(dFaces[0].FaceID)
fmt.Println()
// Find/display the age and gender attributes
for _, dFace := range dFaces { 
    fmt.Println("Face attributes:")
    fmt.Printf("  Age: %.0f", *dFace.FaceAttributes.Age) 
    fmt.Println("\n  Gender: " + dFace.FaceAttributes.Gender) 
} 
// Get/display the emotion attribute
emotionStruct := *dFaces[0].FaceAttributes.Emotion
// Convert struct to a map
var emotionMap map[string]float64
result, _ := json.Marshal(emotionStruct)
json.Unmarshal(result, &emotionMap)
// Find the emotion with the highest score (confidence level). Range is 0.0 - 1.0.
var highest float64 
emotion := ""
dScore := -1.0
for name, value := range emotionMap{
    if (value > highest) {
        emotion, dScore = name, value
        highest = value
    }
}
fmt.Println("  Emotion: " + emotion + " (score: " + strconv.FormatFloat(dScore, 'f', 3, 64) + ")")

유사 얼굴 찾기

다음 코드에서는 감지된 하나의 얼굴(원본)을 가져오고, 다른 얼굴(대상) 세트를 검색하여 일치 항목을 찾습니다(이미지별 얼굴 검색). 일치 항목을 찾으면 일치하는 얼굴의 ID를 콘솔에 출력합니다.

비교할 얼굴 감지

먼저 이미지에서 얼굴 감지 섹션에서 감지한 얼굴의 참조를 저장합니다. 이 얼굴이 원본입니다.

// Select an ID in single-faced image for comparison to faces detected in group image. Used in Find Similar.
firstImageFaceID := dFaces[0].FaceID

그런 다음, 다른 이미지에서 얼굴 세트를 감지할 다음 코드를 입력합니다. 여기서 감지되는 얼굴이 대상입니다.

// Detect the faces in an image that contains multiple faces
groupImageURL := "http://www.historyplace.com/kennedy/president-family-portrait-closeup.jpg"
groupImageName := path.Base(groupImageURL)
groupImage := face.ImageURL { URL: &groupImageURL } 

// API call to detect faces in group image, using recognition model 4. This returns a ListDetectedFace struct.
// We specify detection model 3 because we are not retrieving attributes.
detectedGroupFaces, dgErr := client.DetectWithURL(faceContext, groupImage, &returnFaceID, &returnFaceLandmarks, nil, face.Recognition04, &returnRecognitionModel, face.Detection03)
if dgErr != nil { log.Fatal(dgErr) }
fmt.Println()

// Detect faces in the group image.
// Dereference *[]DetectedFace, in order to loop through it.
dFaces2 := *detectedGroupFaces.Value
// Make slice list of UUIDs
faceIDs := make([]uuid.UUID, len(dFaces2))
fmt.Print("Detected faces in (" + groupImageName + ") with ID(s):\n")
for i, face := range dFaces2 {
    faceIDs[i] = *face.FaceID // Dereference DetectedFace.FaceID
    fmt.Println(*face.FaceID)
}

일치 항목 찾기

다음 코드는 FindSimilar 메서드를 사용하여 원본 얼굴과 일치하는 모든 대상 얼굴을 찾습니다.

// Add single-faced image ID to struct
findSimilarBody := face.FindSimilarRequest { FaceID: firstImageFaceID, FaceIds: &faceIDs }
// Get the list of similar faces found in the group image of previously detected faces
listSimilarFaces, sErr := client.FindSimilar(faceContext, findSimilarBody)
if sErr != nil { log.Fatal(sErr) }

// The *[]SimilarFace 
simFaces := *listSimilarFaces.Value

다음 코드에서는 일치 항목 세부 정보를 콘솔에 출력합니다.

// Print the details of the similar faces detected 
fmt.Print("Similar faces found in (" + groupImageName + ") with ID(s):\n")
var sScore float64
for _, face := range simFaces {
    fmt.Println(face.FaceID)
    // Confidence of the found face with range 0.0 to 1.0.
    sScore = *face.Confidence
    fmt.Println("The similarity confidence: ", strconv.FormatFloat(sScore, 'f', 3, 64))
}

PersonGroup 만들기 및 학습

이 시나리오를 단계별로 실행하려면 https://github.com/Azure-Samples/cognitive-services-sample-data-files/tree/master/Face/images 의 이미지를 프로젝트의 루트 디렉터리에 저장해야 합니다.

이 이미지 그룹에는 서로 다른 세 명의 사람과 일치하는 세 개의 단일 얼굴 이미지 세트가 포함되어 있습니다. 이 코드는 세 개의 PersonGroup Person 개체를 정의하고, woman, manchild로 시작하는 이미지 파일에 이 개체를 연결합니다.

PersonGroup 만들기

이미지를 다운로드한 후에는 main 메서드의 맨 아래에 다음 코드를 추가합니다. 이 코드는 PersonGroupClient 개체를 인증 한 다음, 이 개체를 사용하여 새 PersonGroup 을 정의합니다.

// Get working directory
root, rootErr := os.Getwd()
if rootErr != nil { log.Fatal(rootErr) }

// Full path to images folder
imagePathRoot := path.Join(root+"\\images\\")

// Authenticate - Need a special person group client for your person group
personGroupClient := face.NewPersonGroupClient(endpoint)
personGroupClient.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscriptionKey)

// Create the Person Group
// Create an empty Person Group. Person Group ID must be lower case, alphanumeric, and/or with '-', '_'.
personGroupID := "unique-person-group"
fmt.Println("Person group ID: " + personGroupID)
metadata := face.MetaDataContract { Name: &personGroupID }

// Create the person group
personGroupClient.Create(faceContext, personGroupID, metadata)

PersonGroup Person 만들기

다음 코드 블록은 PersonGroupPersonClient 개체를 인증하고, 이 개체를 사용하여 세 개의 새 PersonGroup Person 개체를 정의합니다. 이러한 개체는 각각 이미지 세트의 사용자 한 명을 나타냅니다.

// Authenticate - Need a special person group person client for your person group person
personGroupPersonClient := face.NewPersonGroupPersonClient(endpoint)
personGroupPersonClient.Authorizer = autorest.NewCognitiveServicesAuthorizer(subscriptionKey)

// Create each person group person for each group of images (woman, man, child)
// Define woman friend
w := "Woman"
nameWoman := face.NameAndUserDataContract { Name: &w }
// Returns a Person type
womanPerson, wErr := personGroupPersonClient.Create(faceContext, personGroupID, nameWoman)
if wErr != nil { log.Fatal(wErr) }
fmt.Print("Woman person ID: ")
fmt.Println(womanPerson.PersonID)
// Define man friend
m := "Man"
nameMan := face.NameAndUserDataContract { Name: &m }
// Returns a Person type
manPerson, wErr := personGroupPersonClient.Create(faceContext, personGroupID, nameMan)
if wErr != nil { log.Fatal(wErr) }
fmt.Print("Man person ID: ")
fmt.Println(manPerson.PersonID)
// Define child friend
ch := "Child"
nameChild := face.NameAndUserDataContract { Name: &ch }
// Returns a Person type
childPerson, wErr := personGroupPersonClient.Create(faceContext, personGroupID, nameChild)
if wErr != nil { log.Fatal(wErr) }
fmt.Print("Child person ID: ")
fmt.Println(childPerson.PersonID)

Person에 얼굴 할당

다음 코드는 접두사를 기준으로 이미지를 정렬하고, 얼굴을 감지하고, 이미지 파일 이름에 따라 얼굴을 각 PersonGroup Person 개체에 할당합니다.

// Detect faces and register to correct person
// Lists to hold all their person images
womanImages := list.New()
manImages := list.New()
childImages := list.New()

// Collect the local images for each person, add them to their own person group person
images, fErr := ioutil.ReadDir(imagePathRoot)
if fErr != nil { log.Fatal(fErr)}
for _, f := range images {
    path:= (imagePathRoot+f.Name())
    if strings.HasPrefix(f.Name(), "w") {
        var wfile io.ReadCloser
        wfile, err:= os.Open(path)
        if err != nil { log.Fatal(err) }
        womanImages.PushBack(wfile)
        personGroupPersonClient.AddFaceFromStream(faceContext, personGroupID, *womanPerson.PersonID, wfile, "", nil, face.Detection03)
    }
    if strings.HasPrefix(f.Name(), "m") {
        var mfile io.ReadCloser
        mfile, err:= os.Open(path)
        if err != nil { log.Fatal(err) }
        manImages.PushBack(mfile)
        personGroupPersonClient.AddFaceFromStream(faceContext, personGroupID, *manPerson.PersonID, mfile, "", nil, face.Detection03)
    }
    if strings.HasPrefix(f.Name(), "ch") {
        var chfile io.ReadCloser
        chfile, err:= os.Open(path)
        if err != nil { log.Fatal(err) }
        childImages.PushBack(chfile)
        personGroupPersonClient.AddFaceFromStream(faceContext, personGroupID, *childPerson.PersonID, chfile, "", nil, face.Detection03)
    }
}

URL에서 참조하는 원격 이미지에서 PersonGroup 을 만들 수도 있습니다. PersonGroupPersonClient 메서드(예: AddFaceFromURL)를 참조하세요.

PersonGroup 학습

얼굴을 할당한 후에는 각 Person 개체와 관련된 시각적 특징을 식별할 수 있도록 PersonGroup 을 학습시켜야 합니다. 다음 코드는 비동기 train 메서드를 호출하고, 결과를 폴링하여 상태를 콘솔에 출력합니다.

// Train the person group
personGroupClient.Train(faceContext, personGroupID)

// Wait for it to succeed in training
for {
    trainingStatus, tErr := personGroupClient.GetTrainingStatus(faceContext, personGroupID)
    if tErr != nil { log.Fatal(tErr) }
    
    if trainingStatus.Status == "succeeded" {
        fmt.Println("Training status:", trainingStatus.Status)
        break
    }
    time.Sleep(2)
}

Face API는 기본적으로 정적인 사전 빌드된 모델 세트에서 실행됩니다(서비스가 실행될 때 모델의 성능이 저하되거나 향상되지 않음). Microsoft에서 완전히 새로운 모델 버전으로 마이그레이션하지 않고 모델의 백엔드를 업데이트하면 모델이 생성하는 결과가 변경될 수 있습니다. 최신 버전의 모델을 사용하려면 PersonGroup 을 동일한 등록 이미지를 가진 매개 변수로 지정하여 다시 학습할 수 있습니다.

얼굴 식별

Identify(식별) 작업은 사람(또는 여러 사람)의 이미지를 가져와서 이미지에서 각 얼굴의 ID를 찾습니다(얼굴 인식 검색). 감지된 각 얼굴을 얼굴 특징이 알려진 다른 Person 개체의 데이터베이스인 PersonGroup 과 비교합니다.

중요

이 예제를 실행하려면 먼저 PersonGroup 만들기 및 학습에서 코드를 실행해야 합니다.

테스트 이미지 가져오기

다음 코드는 프로젝트의 루트에서 test-image-person-group.jpg 이미지를 찾아 프로그램 메모리에 로드합니다. 이 이미지는 PersonGroup 만들기 및 학습: https://github.com/Azure-Samples/cognitive-services-sample-data-files/tree/master/Face/images 에 사용한 이미지와 동일한 리포지토리에서 찾을 수 있습니다.

personGroupTestImageName := "test-image-person-group.jpg"
// Use image path root from the one created in person group
personGroupTestImagePath := imagePathRoot
var personGroupTestImage io.ReadCloser
// Returns a ReaderCloser
personGroupTestImage, identErr:= os.Open(personGroupTestImagePath+personGroupTestImageName)
if identErr != nil { log.Fatal(identErr) }

테스트 이미지에서 원본 얼굴 감지

다음 코드 블록은 테스트 이미지를 대상으로 일반적인 얼굴 감지를 수행하여 모든 얼굴을 감지하고 배열에 저장합니다.

// Detect faces in group test image, using recognition model 1 (default)
returnIdentifyFaceID := true
// Returns a ListDetectedFaces
// Recognition04 is not compatible.
// We specify detection model 3 because we are not retrieving attributes.
detectedTestImageFaces, dErr := client.DetectWithStream(faceContext, personGroupTestImage, &returnIdentifyFaceID, nil, nil, face.Recognition01, nil, face.Detection03)
if dErr != nil { log.Fatal(dErr) }

// Make list of face IDs from the detection. 
length := len(*detectedTestImageFaces.Value)
testImageFaceIDs := make([]uuid.UUID, length)
// ListDetectedFace is a struct with a Value property that returns a *[]DetectedFace
for i, f := range *detectedTestImageFaces.Value {
    testImageFaceIDs[i] = *f.FaceID
}

얼굴 식별

Identify 메서드는 감지된 얼굴 배열을 가져와서 지정된 (이전 섹션에서 정의하고 학습시킨) PersonGroup 과 비교합니다. 감지된 얼굴을 Person 과 매칭할 수 있으면 결과가 저장됩니다.

// Identify the faces in the test image with everyone in the person group as a query
identifyRequestBody := face.IdentifyRequest { FaceIds: &testImageFaceIDs, PersonGroupID: &personGroupID }
identifiedFaces, err := client.Identify(faceContext, identifyRequestBody)
if err != nil { log.Fatal(err) }

그런 다음, 이 코드는 자세한 매칭 결과를 콘솔에 출력합니다.

// Get the result which person(s) were identified
iFaces := *identifiedFaces.Value
for _, person := range iFaces {
    fmt.Println("Person for face ID: " )
    fmt.Print(person.FaceID)
    fmt.Println(" is identified in " + personGroupTestImageName + ".")
}

얼굴 확인

확인 작업은 얼굴 ID와 다른 얼굴 ID 또는 Person 개체를 가져와서 동일한 사람에게 속하는지 여부를 확인합니다.

다음 코드는 두 개의 원본 이미지에서 얼굴을 감지한 다음, 대상 이미지에서 검색된 각 얼굴과 대조합니다.

테스트 이미지 가져오기

다음 코드 블록은 확인 작업을 위한 원본 및 대상 이미지를 가리키는 변수를 선언합니다.

// Create a slice list to hold the target photos of the same person
targetImageFileNames :=  make([]string, 2)
targetImageFileNames[0] = "Family1-Dad1.jpg"
targetImageFileNames[1] = "Family1-Dad2.jpg"

// The source photos contain this person, maybe
sourceImageFileName1 := "Family1-Dad3.jpg"
sourceImageFileName2 := "Family1-Son1.jpg"

확인을 위한 얼굴 감지

다음 코드는 소스 및 대상 이미지에서 얼굴을 감지하고 변수에 저장합니다.

// DetectWithURL parameters
urlSource1 := imageBaseURL + sourceImageFileName1
urlSource2 := imageBaseURL + sourceImageFileName2
url1 :=  face.ImageURL { URL: &urlSource1 }
url2 := face.ImageURL { URL: &urlSource2 }
returnFaceIDVerify := true
returnFaceLandmarksVerify := false
returnRecognitionModelVerify := false

// Detect face(s) from source image 1, returns a ListDetectedFace struct
// We specify detection model 3 because we are not retrieving attributes.
detectedVerifyFaces1, dErrV1 := client.DetectWithURL(faceContext, url1 , &returnFaceIDVerify, &returnFaceLandmarksVerify, nil, face.Recognition04, &returnRecognitionModelVerify, face.Detection03)
if dErrV1 != nil { log.Fatal(dErrV1) }
// Dereference the result, before getting the ID
dVFaceIds1 := *detectedVerifyFaces1.Value 
// Get ID of the detected face
imageSource1Id := dVFaceIds1[0].FaceID
fmt.Println(fmt.Sprintf("%v face(s) detected from image: %v", len(dVFaceIds1), sourceImageFileName1))

// Detect face(s) from source image 2, returns a ListDetectedFace struct
// We specify detection model 3 because we are not retrieving attributes.
detectedVerifyFaces2, dErrV2 := client.DetectWithURL(faceContext, url2 , &returnFaceIDVerify, &returnFaceLandmarksVerify, nil, face.Recognition04, &returnRecognitionModelVerify, face.Detection03)
if dErrV2 != nil { log.Fatal(dErrV2) }
// Dereference the result, before getting the ID
dVFaceIds2 := *detectedVerifyFaces2.Value 
// Get ID of the detected face
imageSource2Id := dVFaceIds2[0].FaceID
fmt.Println(fmt.Sprintf("%v face(s) detected from image: %v", len(dVFaceIds2), sourceImageFileName2))
// Detect faces from each target image url in list. DetectWithURL returns a VerifyResult with Value of list[DetectedFaces]
// Empty slice list for the target face IDs (UUIDs)
var detectedVerifyFacesIds [2]uuid.UUID
for i, imageFileName := range targetImageFileNames {
    urlSource := imageBaseURL + imageFileName 
    url :=  face.ImageURL { URL: &urlSource}
    // We specify detection model 3 because we are not retrieving attributes.
    detectedVerifyFaces, dErrV := client.DetectWithURL(faceContext, url, &returnFaceIDVerify, &returnFaceLandmarksVerify, nil, face.Recognition04, &returnRecognitionModelVerify, face.Detection03)
    if dErrV != nil { log.Fatal(dErrV) }
    // Dereference *[]DetectedFace from Value in order to loop through it.
    dVFaces := *detectedVerifyFaces.Value
    // Add the returned face's face ID
    detectedVerifyFacesIds[i] = *dVFaces[0].FaceID
    fmt.Println(fmt.Sprintf("%v face(s) detected from image: %v", len(dVFaces), imageFileName))
}

확인 결과 가져오기

다음 코드는 각 원본 이미지를 대상 이미지와 비교하고 동일한 사람에 속하는지 여부를 나타내는 메시지를 출력합니다.

// Verification example for faces of the same person. The higher the confidence, the more identical the faces in the images are.
// Since target faces are the same person, in this example, we can use the 1st ID in the detectedVerifyFacesIds list to compare.
verifyRequestBody1 := face.VerifyFaceToFaceRequest{ FaceID1: imageSource1Id, FaceID2: &detectedVerifyFacesIds[0] }
verifyResultSame, vErrSame := client.VerifyFaceToFace(faceContext, verifyRequestBody1)
if vErrSame != nil { log.Fatal(vErrSame) }

fmt.Println()

// Check if the faces are from the same person.
if (*verifyResultSame.IsIdentical) {
    fmt.Println(fmt.Sprintf("Faces from %v & %v are of the same person, with confidence %v", 
    sourceImageFileName1, targetImageFileNames[0], strconv.FormatFloat(*verifyResultSame.Confidence, 'f', 3, 64)))
} else {
    // Low confidence means they are more differant than same.
    fmt.Println(fmt.Sprintf("Faces from %v & %v are of a different person, with confidence %v", 
    sourceImageFileName1, targetImageFileNames[0], strconv.FormatFloat(*verifyResultSame.Confidence, 'f', 3, 64)))
}

// Verification example for faces of different persons. 
// Since target faces are same person, in this example, we can use the 1st ID in the detectedVerifyFacesIds list to compare.
verifyRequestBody2 := face.VerifyFaceToFaceRequest{ FaceID1: imageSource2Id, FaceID2: &detectedVerifyFacesIds[0] }
verifyResultDiff, vErrDiff := client.VerifyFaceToFace(faceContext, verifyRequestBody2)
if vErrDiff != nil { log.Fatal(vErrDiff) }
// Check if the faces are from the same person.
if (*verifyResultDiff.IsIdentical) {
    fmt.Println(fmt.Sprintf("Faces from %v & %v are of the same person, with confidence %v", 
    sourceImageFileName2, targetImageFileNames[0], strconv.FormatFloat(*verifyResultDiff.Confidence, 'f', 3, 64)))
} else {
    // Low confidence means they are more differant than same.
    fmt.Println(fmt.Sprintf("Faces from %v & %v are of a different person, with confidence %v", 
    sourceImageFileName2, targetImageFileNames[0], strconv.FormatFloat(*verifyResultDiff.Confidence, 'f', 3, 64)))
}

애플리케이션 실행

go run <app-name> 명령을 사용하여 애플리케이션 디렉터리에서 얼굴 인식 앱을 실행합니다.

go run sample-app.go

리소스 정리

Cognitive Services 구독을 정리하고 제거하려면 리소스나 리소스 그룹을 삭제하면 됩니다. 리소스 그룹을 삭제하면 해당 리소스 그룹에 연결된 다른 모든 리소스가 함께 삭제됩니다.

이 빠른 시작에서 PersonGroup 을 만든 경우 Delete 메서드를 호출하여 삭제할 수 있습니다.

다음 단계

이 빠른 시작에서는 Go용 Face 클라이언트 라이브러리를 사용하여 기본 얼굴 인식 작업을 수행하는 방법을 알아보았습니다. 다음으로 라이브러리에 대해 자세히 알아보려면 참조 설명서를 살펴보세요.

빠른 시작: JavaScript용 Face 클라이언트 라이브러리

JavaScript용 Face 클라이언트 라이브러리를 사용하여 얼굴 인식을 시작합니다. 이러한 단계에 따라 패키지를 설치하고 기본 작업을 위한 예제 코드를 사용해 봅니다. Face 서비스는 이미지에서 사람의 얼굴을 감지하고 인식하기 위한 고급 알고리즘에 대한 액세스를 제공합니다.

JavaScript용 Face 클라이언트 라이브러리를 사용하여 다음을 수행합니다.

참조 설명서 | 라이브러리 소스 코드 | 패키지(npm) | 샘플

필수 구성 요소

  • Azure 구독 - 체험 구독 만들기
  • 최신 버전의 Node.js
  • Azure 구독을 보유한 후에는 Azure Portal에서 Face 리소스를 만들어 키와 엔드포인트를 가져옵니다. 배포 후 리소스로 이동 을 클릭합니다.
    • 애플리케이션을 Face API에 연결하려면 만든 리소스의 키와 엔드포인트가 필요합니다. 이 빠른 시작의 뒷부분에 나오는 코드에 키와 엔드포인트를 붙여넣습니다.
    • 평가판 가격 책정 계층(F0)을 통해 서비스를 사용해보고, 나중에 프로덕션용 유료 계층으로 업그레이드할 수 있습니다.

설치

새 Node.js 애플리케이션 만들기

콘솔 창(예: cmd, PowerShell 또는 Bash)에서 앱에 대한 새 디렉터리를 만들고 이 디렉터리로 이동합니다.

mkdir myapp && cd myapp

package.json 파일을 사용하여 노드 애플리케이션을 만들려면 npm init 명령을 실행합니다.

npm init

클라이언트 라이브러리 설치

ms-rest-azureazure-cognitiveservices-face NPM 패키지를 설치합니다.

npm install @azure/cognitiveservices-face @azure/ms-rest-js

종속성이 있는 앱의 package.json 파일이 업데이트됩니다.

파일 index.js를 만들고 다음 라이브러리를 가져옵니다.

한 번에 전체 빠른 시작 코드 파일을 보시겠습니까? GitHub에서 찾을 수 있으며 이 빠른 시작의 코드 예제를 포함합니다.

const msRest = require("@azure/ms-rest-js");
const Face = require("@azure/cognitiveservices-face");
const uuid = require("uuid/v4");

리소스의 Azure 엔드포인트 및 키에 대한 변수를 만듭니다.

중요

Azure Portal로 이동합니다. 필수 구성 요소 섹션에서 만든 Face 리소스가 성공적으로 배포된 경우 다음 단계 아래에서 리소스로 이동 단추를 클릭합니다. 리소스 관리 아래에 있는 리소스의 키 및 엔드포인트 페이지에서 키 및 엔드포인트를 찾을 수 있습니다.

완료되면 코드에서 키를 제거하고 공개적으로 게시하지 마세요. 프로덕션의 경우 자격 증명을 안전하게 저장하고 액세스하는 방법을 사용하는 것이 좋습니다. 자세한 내용은 Cognitive Services 보안 문서를 참조하세요.

key = "<paste-your-face-key-here>"
endpoint = "<paste-your-face-endpoint-here>"

개체 모델

Face .NET 클라이언트 라이브러리의 주요 기능 중 일부를 처리하는 클래스와 인터페이스는 다음과 같습니다.

Name Description
FaceClient 이 클래스는 Face 서비스를 사용할 수 있는 권한의 부여를 나타내며 모든 Face 기능에 필요합니다. 구독 정보를 사용하여 인스턴스화하고, 다른 클래스의 인스턴스를 생성하는 데 사용합니다.
Face 이 클래스는 사람 얼굴을 사용하여 수행할 수 있는 기본 감지 및 인식 작업을 처리합니다.
DetectedFace 이 클래스는 이미지의 한 얼굴에서 감지된 모든 데이터를 나타냅니다. 얼굴에 대한 자세한 정보를 검색하는 데 사용할 수 있습니다.
FaceList 이 클래스는 분류된 얼굴 세트를 저장하는 클라우드 저장 FaceList 구문을 관리합니다.
PersonGroupPerson 이 클래스는 한 사람에게 속한 얼굴 세트를 저장하는 클라우드 저장 Person 구문을 관리합니다.
PersonGroup 이 클래스는 분류된 Person 개체 세트를 저장하는 클라우드 저장 PersonGroup 구문을 관리합니다.

코드 예제

아래 코드 조각에서는 .NET용 Face 클라이언트 라이브러리를 사용하여 다음 작업을 수행하는 방법을 보여 줍니다.

한 번에 전체 빠른 시작 코드 파일을 보시겠습니까? GitHub에서 찾을 수 있으며 이 빠른 시작의 코드 예제를 포함합니다.

클라이언트 인증

엔드포인트 및 키를 사용하여 클라이언트를 인스턴스화합니다. 키를 사용하여 ApiKeyCredentials 개체를 만들고, 엔드포인트에서 이를 사용하여 FaceClient 개체를 만듭니다.

const credentials = new msRest.ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': key } });
const client = new Face.FaceClient(credentials, endpoint);

전역 값 및 도우미 함수 선언

다음 전역 값은 나중에 추가할 몇 가지 Face 작업에 필요합니다.

URL은 샘플 이미지 폴더를 가리킵니다. UUID는 만들 PersonGroup의 이름과 ID로 사용됩니다.

const image_base_url = "https://csdx.blob.core.windows.net/resources/Face/Images/";
const person_group_id = uuid();

다음 함수를 사용하여 PersonGroup의 학습이 완료될 때까지 기다립니다.

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

이미지에서 얼굴 감지

검색된 얼굴 개체 가져오기

얼굴을 감지하는 새 메서드를 만듭니다. DetectFaceExtract 메서드는 지정된 URL에서 세 개의 이미지를 처리하고 DetectedFace 개체의 목록을 프로그램 메모리에 만듭니다. FaceAttributeType 값 목록은 추출할 기능을 지정합니다.

그런 다음 DetectFaceExtract 메서드는 검색된 각 얼굴에 대한 특성 데이터를 구문 분석하고 출력합니다. 각 특성은 원래 얼굴 검색 API 호출( FaceAttributeType 목록의)에서 별도로 지정해야 합니다. 다음 코드는 모든 특성을 처리하지만 하나 또는 몇 가지를 사용해야 할 가능성이 높습니다.

async function DetectFaceExtract() {
    console.log("========DETECT FACES========");
    console.log();

    // Create a list of images
    const image_file_names = [
        "detection1.jpg",    // single female with glasses
        // "detection2.jpg", // (optional: single man)
        // "detection3.jpg", // (optional: single male construction worker)
        // "detection4.jpg", // (optional: 3 people at cafe, 1 is blurred)
        "detection5.jpg",    // family, woman child man
        "detection6.jpg"     // elderly couple, male female
    ];

// NOTE await does not work properly in for, forEach, and while loops. Use Array.map and Promise.all instead.
    await Promise.all (image_file_names.map (async function (image_file_name) {
        let detected_faces = await client.face.detectWithUrl(image_base_url + image_file_name,
            {
                returnFaceAttributes: ["Accessories","Age","Blur","Emotion","Exposure","FacialHair","Gender","Glasses","Hair","HeadPose","Makeup","Noise","Occlusion","Smile"],
                // We specify detection model 1 because we are retrieving attributes.
                detectionModel: "detection_01"
            });
        console.log (detected_faces.length + " face(s) detected from image " + image_file_name + ".");
        console.log("Face attributes for face(s) in " + image_file_name + ":");

// Parse and print all attributes of each detected face.
        detected_faces.forEach (async function (face) {
            // Get the bounding box of the face
            console.log("Bounding box:\n  Left: " + face.faceRectangle.left + "\n  Top: " + face.faceRectangle.top + "\n  Width: " + face.faceRectangle.width + "\n  Height: " + face.faceRectangle.height);

            // Get the accessories of the face
            let accessories = face.faceAttributes.accessories.join();
            if (0 === accessories.length) {
                console.log ("No accessories detected.");
            }
            else {
                console.log ("Accessories: " + accessories);
            }

            // Get face other attributes
            console.log("Age: " + face.faceAttributes.age);
            console.log("Blur: " + face.faceAttributes.blur.blurLevel);

            // Get emotion on the face
            let emotions = "";
            let emotion_threshold = 0.0;
            if (face.faceAttributes.emotion.anger > emotion_threshold) { emotions += "anger, "; }
            if (face.faceAttributes.emotion.contempt > emotion_threshold) { emotions += "contempt, "; }
            if (face.faceAttributes.emotion.disgust > emotion_threshold) { emotions +=  "disgust, "; }
            if (face.faceAttributes.emotion.fear > emotion_threshold) { emotions +=  "fear, "; }
            if (face.faceAttributes.emotion.happiness > emotion_threshold) { emotions +=  "happiness, "; }
            if (face.faceAttributes.emotion.neutral > emotion_threshold) { emotions +=  "neutral, "; }
            if (face.faceAttributes.emotion.sadness > emotion_threshold) { emotions +=  "sadness, "; }
            if (face.faceAttributes.emotion.surprise > emotion_threshold) { emotions +=  "surprise, "; }
            if (emotions.length > 0) {
                console.log ("Emotions: " + emotions.slice (0, -2));
            }
            else {
                console.log ("No emotions detected.");
            }
            
            // Get more face attributes
            console.log("Exposure: " + face.faceAttributes.exposure.exposureLevel);
            if (face.faceAttributes.facialHair.moustache + face.faceAttributes.facialHair.beard + face.faceAttributes.facialHair.sideburns > 0) {
                console.log("FacialHair: Yes");
            }
            else {
                console.log("FacialHair: No");
            }
            console.log("Gender: " + face.faceAttributes.gender);
            console.log("Glasses: " + face.faceAttributes.glasses);

            // Get hair color
            var color = "";
            if (face.faceAttributes.hair.hairColor.length === 0) {
                if (face.faceAttributes.hair.invisible) { color = "Invisible"; } else { color = "Bald"; }
            }
            else {
                color = "Unknown";
                var highest_confidence = 0.0;
                face.faceAttributes.hair.hairColor.forEach (function (hair_color) {
                    if (hair_color.confidence > highest_confidence) {
                        highest_confidence = hair_color.confidence;
                        color = hair_color.color;
                    }
                });
            }
            console.log("Hair: " + color);

            // Get more attributes
            console.log("Head pose:");
            console.log("  Pitch: " + face.faceAttributes.headPose.pitch);
            console.log("  Roll: " + face.faceAttributes.headPose.roll);
            console.log("  Yaw: " + face.faceAttributes.headPose.yaw);
 
            console.log("Makeup: " + ((face.faceAttributes.makeup.eyeMakeup || face.faceAttributes.makeup.lipMakeup) ? "Yes" : "No"));
            console.log("Noise: " + face.faceAttributes.noise.noiseLevel);

            console.log("Occlusion:");
            console.log("  Eye occluded: " + (face.faceAttributes.occlusion.eyeOccluded ? "Yes" : "No"));
            console.log("  Forehead occluded: " + (face.faceAttributes.occlusion.foreheadOccluded ? "Yes" : "No"));
            console.log("  Mouth occluded: " + (face.faceAttributes.occlusion.mouthOccluded ? "Yes" : "No"));

            console.log("Smile: " + face.faceAttributes.smile);
            console.log();
        });
    }));
}

로컬 이미지에서 얼굴을 검색할 수도 있습니다. Face 메서드(예: DetectWithStreamAsync)를 참조하세요.

유사 얼굴 찾기

다음 코드에서는 감지된 하나의 얼굴(원본)을 가져오고, 다른 얼굴(대상) 세트를 검색하여 일치 항목을 찾습니다(이미지별 얼굴 검색). 일치 항목을 찾으면 일치하는 얼굴의 ID를 콘솔에 출력합니다.

비교할 얼굴 감지

먼저 두 번째 얼굴 감지 메서드를 정의합니다. 이미지를 비교하기 전에 이미지에서 얼굴을 감지해야 하며, 이 감지 메서드는 비교 작업에 최적화되어 있습니다. 위의 섹션과 같이 자세한 얼굴 특성을 추출하지 않으며 다른 인식 모델을 사용합니다.

async function DetectFaceRecognize(url) {
    // Detect faces from image URL. Since only recognizing, use the recognition model 4.
    // We use detection model 3 because we are not retrieving attributes.
    let detected_faces = await client.face.detectWithUrl(url,
        {
            detectionModel: "detection_03",
            recognitionModel: "recognition_04"
        });
    return detected_faces;
}

일치 항목 찾기

다음 메서드는 대상 이미지 세트와 단일 원본 이미지에서 얼굴을 감지합니다. 그런 다음, 이를 비교하여 원본 이미지와 유사한 모든 대상 이미지를 찾습니다. 마지막으로, 일치 항목 세부 정보를 콘솔에 출력합니다.

async function FindSimilar() {
    console.log("========FIND SIMILAR========");
    console.log();

    const source_image_file_name = "findsimilar.jpg";
    const target_image_file_names = [
        "Family1-Dad1.jpg",
        "Family1-Daughter1.jpg",
        "Family1-Mom1.jpg",
        "Family1-Son1.jpg",
        "Family2-Lady1.jpg",
        "Family2-Man1.jpg",
        "Family3-Lady1.jpg",
        "Family3-Man1.jpg"
    ];

    let target_face_ids = (await Promise.all (target_image_file_names.map (async function (target_image_file_name) {
        // Detect faces from target image url.
        var faces = await DetectFaceRecognize(image_base_url + target_image_file_name);
        console.log(faces.length + " face(s) detected from image: " +  target_image_file_name + ".");
        return faces.map (function (face) { return face.faceId });;
    }))).flat();

    // Detect faces from source image url.
    let detected_faces = await DetectFaceRecognize(image_base_url + source_image_file_name);

    // Find a similar face(s) in the list of IDs. Comapring only the first in list for testing purposes.
    let results = await client.face.findSimilar(detected_faces[0].faceId, { faceIds : target_face_ids });
    results.forEach (function (result) {
        console.log("Faces from: " + source_image_file_name + " and ID: " + result.faceId + " are similar with confidence: " + result.confidence + ".");
    });
    console.log();
}

얼굴 식별

식별 작업은 한 사람(또는 여러 사람)의 이미지를 가져와 이미지에서 각 얼굴의 ID를 찾습니다(얼굴 인식 검색). 감지된 각 얼굴을 얼굴 특징이 알려진 다른 Person 개체의 데이터베이스인 PersonGroup과 비교합니다. 식별 작업을 수행하려면 먼저 PersonGroup을 만들고 학습해야 합니다.

PersonGroup에 얼굴 추가

다음 함수를 만들어 PersonGroup에 얼굴을 추가합니다.

async function AddFacesToPersonGroup(person_dictionary, person_group_id) {
    console.log ("Adding faces to person group...");
    // The similar faces will be grouped into a single person group person.
    
    await Promise.all (Object.keys(person_dictionary).map (async function (key) {
        const value = person_dictionary[key];

        // Wait briefly so we do not exceed rate limits.
        await sleep (1000);

        let person = await client.personGroupPerson.create(person_group_id, { name : key });
        console.log("Create a person group person: " + key + ".");

        // Add faces to the person group person.
        await Promise.all (value.map (async function (similar_image) {
            console.log("Add face to the person group person: (" + key + ") from image: " + similar_image + ".");
            await client.personGroupPerson.addFaceFromUrl(person_group_id, person.personId, image_base_url + similar_image);
        }));
    }));

    console.log ("Done adding faces to person group.");
}

PersonGroup의 학습 대기

다음 도우미 함수를 만들어 PersonGroup 이 학습을 완료할 때까지 기다립니다.

async function WaitForPersonGroupTraining(person_group_id) {
    // Wait so we do not exceed rate limits.
    console.log ("Waiting 10 seconds...");
    await sleep (10000);
    let result = await client.personGroup.getTrainingStatus(person_group_id);
    console.log("Training status: " + result.status + ".");
    if (result.status !== "succeeded") {
        await WaitForPersonGroupTraining(person_group_id);
    }
}

PersonGroup 만들기

코드는 다음과 같습니다.

  • PersonGroup 만들기
  • 이전에 정의한 AddFacesToPersonGroup을 호출하여 PersonGroup 에 얼굴을 추가합니다.
  • PersonGroup 을 학습합니다.
  • PersonGroup 의 얼굴을 식별합니다.

이제 이 PersonGroup 및 연결된 해당 Person 개체는 Verify(검증), Identify(식별) 또는 Group(그룹) 작업에 사용할 수 있습니다.

async function IdentifyInPersonGroup() {
    console.log("========IDENTIFY FACES========");
    console.log();

// Create a dictionary for all your images, grouping similar ones under the same key.
    const person_dictionary = {
        "Family1-Dad" : ["Family1-Dad1.jpg", "Family1-Dad2.jpg"],
        "Family1-Mom" : ["Family1-Mom1.jpg", "Family1-Mom2.jpg"],
        "Family1-Son" : ["Family1-Son1.jpg", "Family1-Son2.jpg"],
        "Family1-Daughter" : ["Family1-Daughter1.jpg", "Family1-Daughter2.jpg"],
        "Family2-Lady" : ["Family2-Lady1.jpg", "Family2-Lady2.jpg"],
        "Family2-Man" : ["Family2-Man1.jpg", "Family2-Man2.jpg"]
    };

    // A group photo that includes some of the persons you seek to identify from your dictionary.
    let source_image_file_name = "identification1.jpg";

    // Create a person group. 
    console.log("Creating a person group with ID: " + person_group_id);
    await client.personGroup.create(person_group_id, { name : person_group_id, recognitionModel : "recognition_04" });

    await AddFacesToPersonGroup(person_dictionary, person_group_id);

    // Start to train the person group.
    console.log();
    console.log("Training person group: " + person_group_id + ".");
    await client.personGroup.train(person_group_id);

    await WaitForPersonGroupTraining(person_group_id);
    console.log();

    // Detect faces from source image url.
    let face_ids = (await DetectFaceRecognize(image_base_url + source_image_file_name)).map (face => face.faceId);

// Identify the faces in a person group.
    let results = await client.face.identify(face_ids, { personGroupId : person_group_id});
    await Promise.all (results.map (async function (result) {
        let person = await client.personGroupPerson.get(person_group_id, result.candidates[0].personId);
        console.log("Person: " + person.name + " is identified for face in: " + source_image_file_name + " with ID: " + result.faceId + ". Confidence: " + result.candidates[0].confidence + ".");
    }));
    console.log();
}

로컬 이미지에서 PersonGroup 을 만들 수도 있습니다. PersonGroupPerson 메서드(예: AddFaceFromStream)를 참조하세요.

마지막으로, main 함수를 만들고 호출합니다.

async function main() {
    await DetectFaceExtract();
    await FindSimilar();
    await IdentifyInPersonGroup();
    console.log ("Done.");
}
main();

애플리케이션 실행

quickstart 파일의 node 명령을 사용하여 애플리케이션을 실행합니다.

node index.js

리소스 정리

Cognitive Services 구독을 정리하고 제거하려면 리소스나 리소스 그룹을 삭제하면 됩니다. 리소스 그룹을 삭제하면 해당 리소스 그룹에 연결된 다른 모든 리소스가 함께 삭제됩니다.

다음 단계

이 빠른 시작에서는 JavaScript용 Face 클라이언트 라이브러리를 사용하여 기본 얼굴 인식 작업을 수행하는 방법을 알아보았습니다. 다음으로 라이브러리에 대해 자세히 알아보려면 참조 설명서를 살펴보세요.

Python용 Face 클라이언트 라이브러리를 사용하여 얼굴 인식을 시작합니다. 이러한 단계에 따라 패키지를 설치하고 기본 작업을 위한 예제 코드를 사용해 봅니다. Face 서비스는 이미지에서 사람의 얼굴을 감지하고 인식하기 위한 고급 알고리즘에 대한 액세스를 제공합니다.

Python용 Face 클라이언트 라이브러리를 사용하여 다음을 수행합니다.

참조 설명서 | 라이브러리 소스 코드 | 패키지(PiPy) | 샘플

필수 구성 요소

  • Azure 구독 - 체험 구독 만들기
  • Python 3.x
    • Python 설치에 pip가 포함되어야 합니다. 명령줄에서 pip --version을 실행하여 pip가 설치되어 있는지 확인할 수 있습니다. 최신 버전의 Python을 설치하여 pip를 받으세요.
  • Azure 구독이 있으면 Azure Portal에서 Face 리소스를 만들어 키와 엔드포인트를 가져옵니다. 배포 후 리소스로 이동 을 클릭합니다.
    • 애플리케이션을 Face API에 연결하려면 만든 리소스의 키와 엔드포인트가 필요합니다. 이 빠른 시작의 뒷부분에 나오는 코드에 키와 엔드포인트를 붙여넣습니다.
    • 평가판 가격 책정 계층(F0)을 통해 서비스를 사용해보고, 나중에 프로덕션용 유료 계층으로 업그레이드할 수 있습니다.

설치

클라이언트 라이브러리 설치

Python을 설치한 후, 다음을 사용하여 클라이언트 라이브러리를 설치할 수 있습니다.

pip install --upgrade azure-cognitiveservices-vision-face

새 Python 애플리케이션 만들기

예를 들어 새 Python 스크립트(quickstart-file.py)를 만듭니다. 그런 다음, 원하는 편집기 또는 IDE에서 이 파일을 열고, 다음 라이브러리를 가져옵니다.

import asyncio
import io
import glob
import os
import sys
import time
import uuid
import requests
from urllib.parse import urlparse
from io import BytesIO
# To install this module, run:
# python -m pip install Pillow
from PIL import Image, ImageDraw
from azure.cognitiveservices.vision.face import FaceClient
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.vision.face.models import TrainingStatusType, Person

한 번에 전체 빠른 시작 코드 파일을 보시겠습니까? GitHub에서 찾을 수 있으며 이 빠른 시작의 코드 예제를 포함합니다.

그런 다음, 리소스의 Azure 엔드포인트 및 키에 대한 변수를 만듭니다.

# This key will serve all examples in this document.
KEY = "PASTE_YOUR_FACE_SUBSCRIPTION_KEY_HERE"

# This endpoint will be used in all examples in this quickstart.
ENDPOINT = "PASTE_YOUR_FACE_ENDPOINT_HERE"

중요

Azure Portal로 이동합니다. 필수 구성 요소 섹션에서 만든 Face 리소스가 성공적으로 배포된 경우 다음 단계 아래에서 리소스로 이동 단추를 클릭합니다. 리소스 관리 아래에 있는 리소스의 키 및 엔드포인트 페이지에서 키 및 엔드포인트를 찾을 수 있습니다.

완료되면 코드에서 키를 제거하고 공개적으로 게시하지 마세요. 프로덕션의 경우 자격 증명을 안전하게 저장하고 액세스하는 방법을 사용하는 것이 좋습니다. 예를 들어 Azure Key Vault입니다.

개체 모델

Face Python 클라이언트 라이브러리의 주요 기능 중 일부를 처리하는 클래스와 인터페이스는 다음과 같습니다.

Name Description
FaceClient 이 클래스는 Face 서비스를 사용할 수 있는 권한의 부여를 나타내며 모든 Face 기능에 필요합니다. 구독 정보를 사용하여 인스턴스화하고, 다른 클래스의 인스턴스를 생성하는 데 사용합니다.
FaceOperations 이 클래스는 사람 얼굴을 사용하여 수행할 수 있는 기본 감지 및 인식 작업을 처리합니다.
DetectedFace 이 클래스는 이미지의 한 얼굴에서 감지된 모든 데이터를 나타냅니다. 얼굴에 대한 자세한 정보를 검색하는 데 사용할 수 있습니다.
FaceListOperations 이 클래스는 분류된 얼굴 세트를 저장하는 클라우드 저장 FaceList 구문을 관리합니다.
PersonGroupPersonOperations 이 클래스는 한 사람에게 속한 얼굴 세트를 저장하는 클라우드 저장 Person 구문을 관리합니다.
PersonGroupOperations 이 클래스는 분류된 Person 개체 세트를 저장하는 클라우드 저장 PersonGroup 구문을 관리합니다.
ShapshotOperations 이 클래스는 스냅샷 기능을 관리합니다. 이를 사용하여 모든 클라우드 기반 얼굴 데이터를 임시로 저장하고 해당 데이터를 새 Azure 구독으로 마이그레이션할 수 있습니다.

코드 예제

여기에 나와 있는 코드 조각에서는 Python용 Face 클라이언트 라이브러리를 사용하여 다음 작업을 수행하는 방법을 보여 줍니다.

클라이언트 인증

엔드포인트 및 키를 사용하여 클라이언트를 인스턴스화합니다. 키를 사용하여 CognitiveServicesCredentials 개체를 만들고, 엔드포인트에서 이를 사용하여 FaceClient 개체를 만듭니다.

# Create an authenticated FaceClient.
face_client = FaceClient(ENDPOINT, CognitiveServicesCredentials(KEY))

이미지에서 얼굴 감지

다음 코드에서는 원격 이미지에서 얼굴을 감지합니다. 감지된 얼굴의 ID를 콘솔에 출력하고, 프로그램 메모리에 저장합니다. 그런 다음, 여러 사람이 있는 이미지에서도 얼굴을 감지하고, 해당 ID를 콘솔에 출력합니다. detect_with_url 메서드의 매개 변수를 변경하면 각 DetectedFace 개체와 관련된 다른 정보를 반환할 수 있습니다.

# Detect a face in an image that contains a single face
single_face_image_url = 'https://www.biography.com/.image/t_share/MTQ1MzAyNzYzOTgxNTE0NTEz/john-f-kennedy---mini-biography.jpg'
single_image_name = os.path.basename(single_face_image_url)
# We use detection model 3 to get better performance.
detected_faces = face_client.face.detect_with_url(url=single_face_image_url, detection_model='detection_03')
if not detected_faces:
    raise Exception('No face detected from image {}'.format(single_image_name))

# Display the detected face ID in the first single-face image.
# Face IDs are used for comparison to faces (their IDs) detected in other images.
print('Detected face ID from', single_image_name, ':')
for face in detected_faces: print (face.face_id)
print()

# Save this ID for use in Find Similar
first_image_face_ID = detected_faces[0].face_id

로컬 이미지에서 얼굴을 검색할 수도 있습니다. FaceOperations 메서드(예: detect_with_stream)를 참조하세요.

표시 및 프레임 면

다음 코드는 DetectedFace.faceRectangle 속성을 사용하여 지정된 이미지를 디스플레이에 출력하고 얼굴 주위에 사각형을 그립니다.

# Detect a face in an image that contains a single face
single_face_image_url = 'https://raw.githubusercontent.com/Microsoft/Cognitive-Face-Windows/master/Data/detection1.jpg'
single_image_name = os.path.basename(single_face_image_url)
# We use detection model 3 to get better performance.
detected_faces = face_client.face.detect_with_url(url=single_face_image_url, detection_model='detection_03')
if not detected_faces:
    raise Exception('No face detected from image {}'.format(single_image_name))

# Convert width height to a point in a rectangle
def getRectangle(faceDictionary):
    rect = faceDictionary.face_rectangle
    left = rect.left
    top = rect.top
    right = left + rect.width
    bottom = top + rect.height
    
    return ((left, top), (right, bottom))

def drawFaceRectangles() :
# Download the image from the url
    response = requests.get(single_face_image_url)
    img = Image.open(BytesIO(response.content))

# For each face returned use the face rectangle and draw a red box.
    print('Drawing rectangle around face... see popup for results.')
    draw = ImageDraw.Draw(img)
    for face in detected_faces:
        draw.rectangle(getRectangle(face), outline='red')

# Display the image in the default image browser.
    img.show()

# Uncomment this to show the face rectangles.
#    drawFaceRectangles()

얼굴 주위에 빨간색 사각형이 그려진 젊은 여자

유사 얼굴 찾기

다음 코드에서는 감지된 하나의 얼굴(원본)을 가져오고, 다른 얼굴(대상) 세트를 검색하여 일치 항목을 찾습니다(이미지별 얼굴 검색). 일치 항목을 찾으면 일치하는 얼굴의 ID를 콘솔에 출력합니다.

일치 항목 찾기

먼저 위의 섹션(이미지에서 얼굴 감지)에서 코드를 실행하여 단일 얼굴에 대한 참조를 저장합니다. 그런 다음, 다음 코드를 실행하여 그룹 이미지에서 여러 얼굴에 대한 참조를 가져옵니다.

# Detect the faces in an image that contains multiple faces
# Each detected face gets assigned a new ID
multi_face_image_url = "http://www.historyplace.com/kennedy/president-family-portrait-closeup.jpg"
multi_image_name = os.path.basename(multi_face_image_url)
# We use detection model 3 to get better performance.
detected_faces2 = face_client.face.detect_with_url(url=multi_face_image_url, detection_model='detection_03')

그런 다음, 다음 코드 블록을 추가하여 그룹에서 첫 번째 얼굴의 인스턴스를 찾습니다. 이 동작을 수정하는 방법에 대한 자세한 내용은 find_simply 메서드를 참조하세요.

# Search through faces detected in group image for the single face from first image.
# First, create a list of the face IDs found in the second image.
second_image_face_IDs = list(map(lambda x: x.face_id, detected_faces2))
# Next, find similar face IDs like the one detected in the first image.
similar_faces = face_client.face.find_similar(face_id=first_image_face_ID, face_ids=second_image_face_IDs)
if not similar_faces:
    print('No similar faces found in', multi_image_name, '.')

다음 코드를 사용하여 일치 항목 세부 정보를 콘솔에 출력합니다.

# Print the details of the similar faces detected
else:
    print('Similar faces found in', multi_image_name + ':')
    for face in similar_faces:
        first_image_face_ID = face.face_id
        # The similar face IDs of the single face image and the group image do not need to match, 
        # they are only used for identification purposes in each image.
        # The similar faces are matched using the Cognitive Services algorithm in find_similar().
        face_info = next(x for x in detected_faces2 if x.face_id == first_image_face_ID)
        if face_info:
            print('  Face ID: ', first_image_face_ID)
            print('  Face rectangle:')
            print('    Left: ', str(face_info.face_rectangle.left))
            print('    Top: ', str(face_info.face_rectangle.top))
            print('    Width: ', str(face_info.face_rectangle.width))
            print('    Height: ', str(face_info.face_rectangle.height))

PersonGroup 만들기 및 학습

다음 코드에서는 서로 다른 세 개의 Person 개체를 사용하여 PersonGroup 을 만듭니다. 각 Person 을 예제 이미지 세트와 연결한 다음, 각 사용자를 인식할 수 있도록 학습시킵니다.

PersonGroup 만들기

이 시나리오를 단계별로 실행하려면 https://github.com/Azure-Samples/cognitive-services-sample-data-files/tree/master/Face/images 의 이미지를 프로젝트의 루트 디렉터리에 저장해야 합니다.

이 이미지 그룹에는 서로 다른 세 명의 사람에 해당하는 세 개의 얼굴 이미지 세트가 포함되어 있습니다. 코드에서는 세 개의 Person 개체를 정의하고, woman, manchild로 시작하는 이미지 파일에 연결합니다.

이미지가 설정되면 만들 PersonGroup 개체에 대한 레이블을 스크립트의 위쪽에 정의합니다.

# Used in the Person Group Operations and Delete Person Group examples.
# You can call list_person_groups to print a list of preexisting PersonGroups.
# SOURCE_PERSON_GROUP_ID should be all lowercase and alphanumeric. For example, 'mygroupname' (dashes are OK).
PERSON_GROUP_ID = str(uuid.uuid4()) # assign a random ID (or name it anything)

# Used for the Delete Person Group example.
TARGET_PERSON_GROUP_ID = str(uuid.uuid4()) # assign a random ID (or name it anything)

그런 다음, 다음 코드를 Python 스크립트의 아래쪽에 추가합니다. 이 코드는 PersonGroup 및 세 개의 Person 개체를 만듭니다.

'''
Create the PersonGroup
'''
# Create empty Person Group. Person Group ID must be lower case, alphanumeric, and/or with '-', '_'.
print('Person group:', PERSON_GROUP_ID)
face_client.person_group.create(person_group_id=PERSON_GROUP_ID, name=PERSON_GROUP_ID)

# Define woman friend
woman = face_client.person_group_person.create(PERSON_GROUP_ID, "Woman")
# Define man friend
man = face_client.person_group_person.create(PERSON_GROUP_ID, "Man")
# Define child friend
child = face_client.person_group_person.create(PERSON_GROUP_ID, "Child")

Person에 얼굴 할당

다음 코드는 접두사를 기준으로 이미지를 정렬하고, 얼굴을 감지하며, 해당 얼굴을 각 Person 개체에 할당합니다.

'''
Detect faces and register to correct person
'''
# Find all jpeg images of friends in working directory
woman_images = [file for file in glob.glob('*.jpg') if file.startswith("w")]
man_images = [file for file in glob.glob('*.jpg') if file.startswith("m")]
child_images = [file for file in glob.glob('*.jpg') if file.startswith("ch")]

# Add to a woman person
for image in woman_images:
    w = open(image, 'r+b')
    face_client.person_group_person.add_face_from_stream(PERSON_GROUP_ID, woman.person_id, w)

# Add to a man person
for image in man_images:
    m = open(image, 'r+b')
    face_client.person_group_person.add_face_from_stream(PERSON_GROUP_ID, man.person_id, m)

# Add to a child person
for image in child_images:
    ch = open(image, 'r+b')
    face_client.person_group_person.add_face_from_stream(PERSON_GROUP_ID, child.person_id, ch)

URL에서 참조하는 원격 이미지에서 PersonGroup 을 만들 수도 있습니다. PersonGroupPersonOperations 메서드(예: add_face_from_url)를 참조하세요.

PersonGroup 학습

얼굴이 할당되면 각 Person 개체와 관련된 시각적 기능을 식별할 수 있도록 PersonGroup 을 학습시켜야 합니다. 다음 코드는 비동기 train 메서드를 호출하고, 결과를 폴링하여 상태를 콘솔에 출력합니다.

'''
Train PersonGroup
'''
print()
print('Training the person group...')
# Train the person group
face_client.person_group.train(PERSON_GROUP_ID)

while (True):
    training_status = face_client.person_group.get_training_status(PERSON_GROUP_ID)
    print("Training status: {}.".format(training_status.status))
    print()
    if (training_status.status is TrainingStatusType.succeeded):
        break
    elif (training_status.status is TrainingStatusType.failed):
        face_client.person_group.delete(person_group_id=PERSON_GROUP_ID)
        sys.exit('Training the person group has failed.')
    time.sleep(5)

Face API는 기본적으로 정적인 사전 빌드된 모델 세트에서 실행됩니다(서비스가 실행될 때 모델의 성능이 저하되거나 향상되지 않음). Microsoft에서 완전히 새로운 모델 버전으로 마이그레이션하지 않고 모델의 백엔드를 업데이트하면 모델이 생성하는 결과가 변경될 수 있습니다. 최신 버전의 모델을 사용하려면 PersonGroup 을 동일한 등록 이미지를 가진 매개 변수로 지정하여 다시 학습할 수 있습니다.

얼굴 식별

Identify(식별) 작업은 사람(또는 여러 사람)의 이미지를 가져와서 이미지에서 각 얼굴의 ID를 찾습니다(얼굴 인식 검색). 감지된 각 얼굴을 얼굴 특징이 알려진 다른 Person 개체의 데이터베이스인 PersonGroup 과 비교합니다.

중요

이 예제를 실행하려면 먼저 PersonGroup 만들기 및 학습에서 코드를 실행해야 합니다.

테스트 이미지 가져오기

다음 코드는 프로젝트 루트에서 test-image-person-group.jpg 이미지를 살펴보고, 이미지에서 얼굴을 감지합니다. 이 이미지는 PersonGroup 관리에 사용된 이미지(https://github.com/Azure-Samples/cognitive-services-sample-data-files/tree/master/Face/images )에서 찾을 수 있습니다.

'''
Identify a face against a defined PersonGroup
'''
# Group image for testing against
test_image_array = glob.glob('test-image-person-group.jpg')
image = open(test_image_array[0], 'r+b')

print('Pausing for 60 seconds to avoid triggering rate limit on free account...')
time.sleep (60)

# Detect faces
face_ids = []
# We use detection model 3 to get better performance.
faces = face_client.face.detect_with_stream(image, detection_model='detection_03')
for face in faces:
    face_ids.append(face.face_id)

얼굴 식별

identify 메서드는 감지된 얼굴의 배열을 사용하여 PersonGroup 과 비교합니다. 감지된 얼굴을 Person 과 일치시킬 수 있으면 결과가 저장됩니다. 이 코드는 자세한 일치 항목 결과를 콘솔에 출력합니다.

# Identify faces
results = face_client.face.identify(face_ids, PERSON_GROUP_ID)
print('Identifying faces in {}'.format(os.path.basename(image.name)))
if not results:
    print('No person identified in the person group for faces from {}.'.format(os.path.basename(image.name)))
for person in results:
    if len(person.candidates) > 0:
        print('Person for face ID {} is identified in {} with a confidence of {}.'.format(person.face_id, os.path.basename(image.name), person.candidates[0].confidence)) # Get topmost confidence score
    else:
        print('No person identified for face ID {} in {}.'.format(person.face_id, os.path.basename(image.name)))

얼굴 확인

확인 작업은 얼굴 ID와 다른 얼굴 ID 또는 Person 개체를 가져와서 동일한 사람에게 속하는지 여부를 확인합니다.

다음 코드는 두 개의 원본 이미지에서 얼굴을 감지한 다음, 대상 이미지에서 검색된 얼굴에 대해 확인합니다.

테스트 이미지 가져오기

다음 코드 블록은 확인 작업을 위한 소스 및 대상 이미지를 가리키는 변수를 선언합니다.

# Base url for the Verify and Facelist/Large Facelist operations
IMAGE_BASE_URL = 'https://csdx.blob.core.windows.net/resources/Face/Images/'
# Create a list to hold the target photos of the same person
target_image_file_names = ['Family1-Dad1.jpg', 'Family1-Dad2.jpg']
# The source photos contain this person
source_image_file_name1 = 'Family1-Dad3.jpg'
source_image_file_name2 = 'Family1-Son1.jpg'

확인을 위한 얼굴 감지

다음 코드는 소스 및 대상 이미지에서 얼굴을 감지하고 변수에 저장합니다.

# Detect face(s) from source image 1, returns a list[DetectedFaces]
# We use detection model 3 to get better performance.
detected_faces1 = face_client.face.detect_with_url(IMAGE_BASE_URL + source_image_file_name1, detection_model='detection_03')
# Add the returned face's face ID
source_image1_id = detected_faces1[0].face_id
print('{} face(s) detected from image {}.'.format(len(detected_faces1), source_image_file_name1))

# Detect face(s) from source image 2, returns a list[DetectedFaces]
detected_faces2 = face_client.face.detect_with_url(IMAGE_BASE_URL + source_image_file_name2, detection_model='detection_03')
# Add the returned face's face ID
source_image2_id = detected_faces2[0].face_id
print('{} face(s) detected from image {}.'.format(len(detected_faces2), source_image_file_name2))

# List for the target face IDs (uuids)
detected_faces_ids = []
# Detect faces from target image url list, returns a list[DetectedFaces]
for image_file_name in target_image_file_names:
    # We use detection model 3 to get better performance.
    detected_faces = face_client.face.detect_with_url(IMAGE_BASE_URL + image_file_name, detection_model='detection_03')
    # Add the returned face's face ID
    detected_faces_ids.append(detected_faces[0].face_id)
    print('{} face(s) detected from image {}.'.format(len(detected_faces), image_file_name))

확인 결과 가져오기

다음 코드는 각 원본 이미지를 대상 이미지와 비교하고 동일한 사람에 속하는지 여부를 나타내는 메시지를 출력합니다.

# Verification example for faces of the same person. The higher the confidence, the more identical the faces in the images are.
# Since target faces are the same person, in this example, we can use the 1st ID in the detected_faces_ids list to compare.
verify_result_same = face_client.face.verify_face_to_face(source_image1_id, detected_faces_ids[0])
print('Faces from {} & {} are of the same person, with confidence: {}'
    .format(source_image_file_name1, target_image_file_names[0], verify_result_same.confidence)
    if verify_result_same.is_identical
    else 'Faces from {} & {} are of a different person, with confidence: {}'
        .format(source_image_file_name1, target_image_file_names[0], verify_result_same.confidence))

# Verification example for faces of different persons.
# Since target faces are same person, in this example, we can use the 1st ID in the detected_faces_ids list to compare.
verify_result_diff = face_client.face.verify_face_to_face(source_image2_id, detected_faces_ids[0])
print('Faces from {} & {} are of the same person, with confidence: {}'
    .format(source_image_file_name2, target_image_file_names[0], verify_result_diff.confidence)
    if verify_result_diff.is_identical
    else 'Faces from {} & {} are of a different person, with confidence: {}'
        .format(source_image_file_name2, target_image_file_names[0], verify_result_diff.confidence))

애플리케이션 실행

python 명령을 사용하여 애플리케이션 디렉터리에서 얼굴 인식 앱을 실행합니다.

python quickstart-file.py

리소스 정리

Cognitive Services 구독을 정리하고 제거하려면 리소스나 리소스 그룹을 삭제하면 됩니다. 리소스 그룹을 삭제하면 해당 리소스 그룹에 연결된 다른 모든 리소스가 함께 삭제됩니다.

이 빠른 시작에서는 PersonGroup 을 만들었으며, 이를 삭제하려면 스크립트에서 다음 코드를 실행합니다.

# Delete the main person group.
face_client.person_group.delete(person_group_id=PERSON_GROUP_ID)
print("Deleted the person group {} from the source location.".format(PERSON_GROUP_ID))
print()

다음 단계

이 빠른 시작에서는 Python용 Face 클라이언트 라이브러리를 사용하여 기본 얼굴 인식 작업을 수행하는 방법을 알아보았습니다. 다음으로 라이브러리에 대해 자세히 알아보려면 참조 설명서를 살펴보세요.

Face REST API를 사용하여 얼굴 인식을 시작합니다. Face 서비스는 이미지에서 사람의 얼굴을 감지하고 인식하기 위한 고급 알고리즘에 대한 액세스를 제공합니다.

Face REST API를 사용하여 다음을 수행합니다.

참고

이 빠른 시작에서는 cURL 명령을 사용하여 REST API를 호출합니다. 프로그래밍 언어를 사용하여 REST API를 호출할 수도 있습니다. C#, Python, Java, JavaScript, Go의 예는 GitHub 샘플을 참조하세요.

필수 구성 요소

  • Azure 구독 - 체험 구독 만들기
  • Azure 구독을 보유한 후에는 Azure Portal에서 Face 리소스 를 만들어 키와 엔드포인트를 가져옵니다. 배포 후 리소스로 이동 을 클릭합니다.
    • 애플리케이션을 Face API에 연결하려면 생성한 리소스의 키와 엔드포인트가 필요합니다. 이 빠른 시작의 뒷부분에 나오는 코드에 키와 엔드포인트를 붙여넣습니다.
    • 평가판 가격 책정 계층(F0)을 통해 서비스를 사용해보고, 나중에 프로덕션용 유료 계층으로 업그레이드할 수 있습니다.
  • PowerShell 버전 6.0 이상 또는 유사한 명령줄 애플리케이션.

이미지에서 얼굴 감지

다음과 같은 명령을 사용하여 Face API를 호출하고 이미지에서 얼굴 특성 데이터를 가져옵니다. 먼저, 텍스트 편집기에 코드를 복사합니다. 코드를 명령의 특정 부분으로 변경해야 실행할 수 있습니다.—

curl -H "Ocp-Apim-Subscription-Key: TODO_INSERT_YOUR_FACE_SUBSCRIPTION_KEY_HERE" "TODO_INSERT_YOUR_FACE_ENDPOINT_HERE/face/v1.0/detect?detectionModel=detection_03&returnFaceId=true&returnFaceLandmarks=false" -H "Content-Type: application/json" --data-ascii "{\"url\":\"https://upload.wikimedia.org/wikipedia/commons/c/c3/RH_Louise_Lillian_Gish.jpg\"}"

다음과 같이 변경합니다.

  1. Ocp-Apim-Subscription-Key를 유효한 Face 구독 키에 할당합니다.
  2. 쿼리 URL의 첫 번째 부분을 구독 키에 해당하는 엔드포인트에 맞게 변경합니다.

    참고

    2019년 7월 1일 이후에 만들어진 새 리소스는 사용자 지정 하위 도메인 이름을 사용합니다. 자세한 내용 및 지역별 엔드포인트의 전체 목록은 Cognitive Services에 대한 사용자 지정 하위 도메인 이름을 참조하세요.

  3. 필요에 따라 다른 이미지를 가리키도록 요청의 본문에서 URL을 변경합니다.

변경한 후에는 명령 프롬프트를 열고 새 명령을 입력합니다.

결과 검사

콘솔 창에 얼굴 정보가 JSON 데이터로 표시됩니다. 예를 들면 다음과 같습니다.

[
  {
    "faceId": "49d55c17-e018-4a42-ba7b-8cbbdfae7c6f",
    "faceRectangle": {
      "top": 131,
      "left": 177,
      "width": 162,
      "height": 162
    }
  }
]  

얼굴 특성 가져오기

얼굴 특성을 추출하려면 Detect API를 다시 호출하되, detectionModeldetection_01로 설정합니다. returnFaceAttributes 쿼리 매개 변수도 추가합니다. 이제 명령은 다음과 같이 표시됩니다. 이전과 같이 Face 구독 키와 엔드포인트를 삽입합니다.

curl -H "Ocp-Apim-Subscription-Key: TODO_INSERT_YOUR_FACE_SUBSCRIPTION_KEY_HERE" "TODO_INSERT_YOUR_FACE_ENDPOINT_HERE/face/v1.0/detect?detectionModel=detection_01&returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses,emotion,hair,makeup,occlusion,accessories,blur,exposure,noise" -H "Content-Type: application/json" --data-ascii "{\"url\":\"https://upload.wikimedia.org/wikipedia/commons/c/c3/RH_Louise_Lillian_Gish.jpg\"}"

결과 검사

이제 반환된 얼굴 정보에 얼굴 특성이 포함됩니다. 예를 들면 다음과 같습니다.

[
  {
    "faceId": "49d55c17-e018-4a42-ba7b-8cbbdfae7c6f",
    "faceRectangle": {
      "top": 131,
      "left": 177,
      "width": 162,
      "height": 162
    },
    "faceAttributes": {
      "smile": 0,
      "headPose": {
        "pitch": 0,
        "roll": 0.1,
        "yaw": -32.9
      },
      "gender": "female",
      "age": 22.9,
      "facialHair": {
        "moustache": 0,
        "beard": 0,
        "sideburns": 0
      },
      "glasses": "NoGlasses",
      "emotion": {
        "anger": 0,
        "contempt": 0,
        "disgust": 0,
        "fear": 0,
        "happiness": 0,
        "neutral": 0.986,
        "sadness": 0.009,
        "surprise": 0.005
      },
      "blur": {
        "blurLevel": "low",
        "value": 0.06
      },
      "exposure": {
        "exposureLevel": "goodExposure",
        "value": 0.67
      },
      "noise": {
        "noiseLevel": "low",
        "value": 0
      },
      "makeup": {
        "eyeMakeup": true,
        "lipMakeup": true
      },
      "accessories": [],
      "occlusion": {
        "foreheadOccluded": false,
        "eyeOccluded": false,
        "mouthOccluded": false
      },
      "hair": {
        "bald": 0,
        "invisible": false,
        "hairColor": [
          {
            "color": "brown",
            "confidence": 1
          },
          {
            "color": "black",
            "confidence": 0.87
          },
          {
            "color": "other",
            "confidence": 0.51
          },
          {
            "color": "blond",
            "confidence": 0.08
          },
          {
            "color": "red",
            "confidence": 0.08
          },
          {
            "color": "gray",
            "confidence": 0.02
          }
        ]
      }
    }
  }
]

유사 얼굴 찾기

이 작업에서는 감지된 하나의 얼굴(원본)을 가져오고, 다른 얼굴(대상) 세트를 검색하여 일치 항목을 찾습니다(이미지별 얼굴 검색). 일치 항목을 찾으면 일치하는 얼굴의 ID를 콘솔에 출력합니다.

비교할 얼굴 감지

먼저 이미지에서 얼굴을 감지해야 이를 비교할 수 있습니다. 얼굴 감지 섹션에서 했던 것처럼 이 명령을 실행합니다. 이 검색 방법은 비교 작업에 최적화되어 있습니다. 위의 섹션과 같이 자세한 얼굴 특성을 추출하지 않으며 다른 검색 모델을 사용합니다.

curl -H "Ocp-Apim-Subscription-Key: TODO_INSERT_YOUR_FACE_SUBSCRIPTION_KEY_HERE" "TODO_INSERT_YOUR_FACE_ENDPOINT_HERE/face/v1.0/detect?detectionModel=detection_03&returnFaceId=true&returnFaceLandmarks=false" -H "Content-Type: application/json" --data-ascii "{\"url\":\"https://csdx.blob.core.windows.net/resources/Face/Images/Family1-Dad1.jpg\"}"

JSON 응답에서 "faceId" 값을 찾아 임시 위치에 저장합니다. 그런 다음, 이러한 다른 이미지 URL에 대해 위의 명령을 다시 호출하고 얼굴 ID도 저장합니다. 이러한 ID를 대상 얼굴 그룹으로 사용하여 비슷한 얼굴을 찾습니다.

https://csdx.blob.core.windows.net/resources/Face/Images/Family1-Daughter1.jpg
https://csdx.blob.core.windows.net/resources/Face/Images/Family1-Mom1.jpg
https://csdx.blob.core.windows.net/resources/Face/Images/Family1-Son1.jpg
https://csdx.blob.core.windows.net/resources/Face/Images/Family2-Lady1.jpg
https://csdx.blob.core.windows.net/resources/Face/Images/Family2-Man1.jpg
https://csdx.blob.core.windows.net/resources/Face/Images/Family3-Lady1.jpg
https://csdx.blob.core.windows.net/resources/Face/Images/Family3-Man1.jpg

마지막으로 매칭에 사용할 단일 원본 얼굴을 검색하고 ID를 저장합니다. 이 ID는 다른 ID와 구분하여 보관합니다.

https://csdx.blob.core.windows.net/resources/Face/Images/findsimilar.jpg

일치 항목 찾기

다음 명령을 텍스트 편집기에 복사합니다.

curl -v -X POST "https://westus.api.cognitive.microsoft.com/face/v1.0/findsimilars" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{body}"

그런 다음, 다음과 같이 변경합니다.

  1. Ocp-Apim-Subscription-Key를 유효한 Face 구독 키에 할당합니다.
  2. 쿼리 URL의 첫 번째 부분을 구독 키에 해당하는 엔드포인트에 맞게 변경합니다.

body 값에 다음 JSON 콘텐츠를 사용합니다.

{
    "faceId": "",
    "faceIds": [],
    "maxNumOfCandidatesReturned": 10,
    "mode": "matchPerson"
}
  1. "faceId"에 원본 얼굴 ID를 사용합니다.
  2. 다른 얼굴 ID를 "faceIds" 배열의 용어로 붙여 넣습니다.

결과 검사

쿼리 얼굴과 일치하는 얼굴의 ID를 나열하는 JSON 응답을 받게 됩니다.

[
    {
        "persistedFaceId" : "015839fb-fbd9-4f79-ace9-7675fc2f1dd9",
        "confidence" : 0.82
    },
    ...
] 

리소스 정리

Cognitive Services 구독을 정리하고 제거하려면 리소스나 리소스 그룹을 삭제하면 됩니다. 리소스 그룹을 삭제하면 해당 리소스 그룹에 연결된 다른 모든 리소스가 함께 삭제됩니다.

다음 단계

이 빠른 시작에서는 Face REST API를 사용하여 기본 얼굴 인식 작업을 수행하는 방법을 알아보았습니다. 다음으로 라이브러리에 대해 자세히 알아보려면 참조 설명서를 살펴보세요.