얼굴을 대량으로 추가하는 방법

등록일시: 2017-12-14 08:00,  수정일시: 2017-12-14 08:00
조회수: 3,006
이 문서는 Cognitive Services 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 인물 그룹에 대량의 인물 및 얼굴을 추가하는 모범 사례를 살펴봅니다.

본문에서는 인물 그룹에 대량의 인물 및 얼굴을 추가하는 모범 사례를 살펴봅니다. 이 방법은 얼굴 목록을 대상으로도 동일하게 적용됩니다. 본문의 예제는 Face API 클라이언트 라이브러리를 사용해서 C#으로 작성되었습니다.

단계 1: 초기화

몇 가지 변수를 선언하고, 요청을 예약하기 위해 헬퍼 함수를 구현합니다.

  • PersonCount는 전체 인원 수입니다.
  • CallLimitPerSecond는 구독 계층을 감안한 초당 최대 호출 수입니다.
  • _timeStampQueue는 요청 타임스탬프를 기록하는 큐입니다.
  • await WaitCallLimitPerSecondAsync()는 다음 요청을 보낼 수 있는 상태가 될 때까지 대기합니다.
const int PersonCount = 10000;
const int CallLimitPerSecond = 10;
static Queue<DateTime> _timeStampQueue = new Queue<DateTime>(CallLimitPerSecond);

static async Task WaitCallLimitPerSecondAsync()
{
    Monitor.Enter(_timeStampQueue);
    try
    {
        if (_timeStampQueue.Count >= CallLimitPerSecond)
        {
            TimeSpan timeInterval = DateTime.UtcNow - _timeStampQueue.Peek();
            if (timeInterval < TimeSpan.FromSeconds(1))
            {
                await Task.Delay(TimeSpan.FromSeconds(1) - timeInterval);
            }
            _timeStampQueue.Dequeue();
        }
        _timeStampQueue.Enqueue(DateTime.UtcNow);
    }
    finally
    {
        Monitor.Exit(_timeStampQueue);
    }
}

단계 2: API 호출 권한 부여하기

클라이언트 라이브러리를 사용하는 경우에는 다음과 같이 FaceServiceClient 클래스의 생성자를 통해서 구독 키를 전달합니다:

FaceServiceClient faceServiceClient = new FaceServiceClient("Your subscription key");

구독 키는 Azure 관리 포털의 Marketplace 페이지에서 발급받을 수 있습니다. Cognitive Services 체험하기 페이지를 참고하시기 바랍니다.

단계 3: 인물 그룹 생성하기

인물들을 저장하기 위한 "MyPersonGroup"이라는 이름의 인물 그룹을 생성합니다. 또한, 전반적인 유효성을 보장하기 위해 _timeStampQueue의 끝 부분에 요청 시간을 추가합니다.

const string personGroupId = "mypersongroupid";
const string personGroupName = "MyPersonGroup";
_timeStampQueue.Enqueue(DateTime.UtcNow);
await faceServiceClient.CreatePersonGroupAsync(personGroupId, personGroupName);

단계 4: 인물 그룹에 인물 생성하기

인물들을 동시에 병렬로 생성하고, 호출 횟수 제한을 초과하지 않도록 await WaitCallLimitPerSecondAsync()를 적용합니다.

CreatePersonResult[] persons = new CreatePersonResult[PersonCount];
Parallel.For(0, PersonCount, async i =>
{
    await WaitCallLimitPerSecondAsync();

    string personName = $"PersonName#{i}";
    persons[i] = await faceServiceClient.CreatePersonAsync(personGroupId, personName);
});

단계 5: 인물에 얼굴 추가하기

각 인물들의 얼굴을 추가하는 작업 자체는 동시에 병렬로 처리하는 반면, 특정 인물 한 명에 대한 얼굴 추가 작업은 순차적으로 진행하는 것이 좋습니다. 그리고 역시 이번에도 await WaitCallLimitPerSecondAsync()를 호출해서 요청 빈도가 제한 범위 내에 머물도록 보장합니다.

Parallel.For(0, PersonCount, async i =>
{
    Guid personId = persons[i].PersonId;
    string personImageDir = @"/path/to/person/i/images";

    foreach (string imagePath in Directory.GetFiles(personImageDir, "*.jpg"))
    {
        await WaitCallLimitPerSecondAsync();

        using (Stream stream = File.OpenRead(imagePath))
        {
            await faceServiceClient.AddPersonFaceAsync(personGroupId, personId, stream);
        }
    }
});

요약

본문에서는 대량의 인물 및 얼굴을 담는 인물 그룹을 생성하는 과정을 알아봤습니다. 이를 정리해보면:

  • 본문의 전략은 얼굴 목록에 얼굴을 추가할 때도 적용됩니다. 별개의 얼굴 목록에 얼굴을 추가하거나 삭제하는 작업은 동시에 병렬로 처리할 수 있지만, 특정 얼굴 목록 하나를 대상으로 동일한 작업을 처리하는 작업들은 순차적으로 수행합니다.
  • 본문에서는 설명 상의 편의를 위해 잠재적으로 발생할 수 있는 예외 처리에 대한 내용은 생략되었습니다. 보다 견고한 구현을 위해서는 적절한 재시도 정책을 적용해야 합니다.

다음은 지금까지 살펴보고 실제로 구현해본 기능들을 간단히 요약한 목록입니다: