クイック スタート: Face サービスを使用する
重要
Microsoft 製品またはサービスを使用して生体認証データを処理する場合は、お客様の責任において、次のことを行っていただく必要があります: (i) 保有期間や破棄に関するものを含め、データ主体に通知する、(ii) データ主体から同意を得る、(iii) 生体認証データを削除する (該当するデータ保護要件に基づき、必要に応じてすべて)。 ''生体認証データ'' は、GDPR の第 4 条に規定されている意味を持ち、該当する場合は、他のデータ保護要件における同義語となります。 関連情報については、「Face のデータとプライバシー」を参照してください。
注意事項
Microsoft の責任ある AI の原則をサポートするために、Face サービスの利用は、適格性と使用基準に基づいて制限されています。 Face サービスは、Microsoft が管理する顧客とパートナーのみが利用できます。 顔認識受付フォームを使用して利用申請を行ってください。 詳細については、「Face の制限付きアクセス」ページを参照してください。
.NET 用 Face クライアント ライブラリを使用して顔認識を開始します。 Azure AI Face サービスを使うと、画像内の人間の顔を検出して認識するための高度なアルゴリズムにアクセスできます。 以下の手順に従って、パッケージをインストールし、リモート画像を使用した基本的な顔識別のためのコード例を試してみましょう。
リファレンスのドキュメント | ライブラリのソース コード | パッケージ (NuGet) | サンプル
前提条件
- Azure サブスクリプション - 無料アカウントを作成します
- Visual Studio IDE または現在のバージョンの .NET Core。
- Azure サブスクリプションを入手したら、Azure portal で Face リソースを作成し、キーとエンドポイントを取得します。 デプロイされたら、 [リソースに移動] を選択します。
- 対象のアプリケーションを Face API に接続するには、作成したリソースのキーとエンドポイントが必要です。
- Free 価格レベル (
F0
) を使用してサービスを試用し、後から運用環境用の有料レベルにアップグレードすることができます。
環境変数を作成する
この例では、アプリケーションを実行しているローカル コンピューター上の環境変数に資格情報を書き込みます。
Azure portal に移動します。 「前提条件」 セクションで作成したリソースが正常にデプロイされた場合、[次の手順] の下にある [リソースに移動] を選択します。 キーとエンドポイントは、[キーとエンドポイント] ページの [リソース管理] にあります。 リソース キーは Azure サブスクリプション ID と同じではありません。
キーとエンドポイントの環境変数を設定するには、コンソール ウィンドウを開き、オペレーティング システムと開発環境の指示に従います。
FACE_APIKEY
環境変数を設定するには、<your_key>
をリソースのキーの 1 つに置き換えます。FACE_ENDPOINT
環境変数を設定するには、<your_endpoint>
をリソースのエンドポイントに置き換えます。
重要
API キーを使用する場合は、それを Azure Key Vault などの別の場所に安全に保存します。 API キーは、コード内に直接含めないようにし、絶対に公開しないでください。
AI サービスのセキュリティの詳細については、「Azure AI サービスに対する要求の認証」を参照してください。
setx FACE_APIKEY <your_key>
setx FACE_ENDPOINT <your_endpoint>
実行中のプログラムのうち、環境変数の読み取りを必要とするプログラム (コンソール ウィンドウを含む) については、環境変数を読み込む再起動が必要となる場合があります。
顔を識別して検証する
新しい C# アプリケーションを作成する
Visual Studio を使用して、新しい .NET Core アプリケーションを作成します。
クライアント ライブラリをインストールする
新しいプロジェクトを作成したら、ソリューション エクスプローラーでプロジェクト ソリューションを右クリックし、 [NuGet パッケージの管理] を選択して、クライアント ライブラリをインストールします。 パッケージ マネージャーが開いたら、[参照] を選択し、[プレリリースを含める] をオンにして、
Azure.AI.Vision.Face
を検索します。 最新バージョンを選択し、[インストール] を選択します。Program.cs ファイルに次のコードを追加します。
Note
取り込みフォームを使用して Face サービスへのアクセスを受け取っていない場合、これらの関数の一部は機能しません。
using System.Net.Http.Headers; using System.Text; using Azure; using Azure.AI.Vision.Face; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace FaceQuickstart { class Program { static readonly string largePersonGroupId = Guid.NewGuid().ToString(); // URL path for the images. const string IMAGE_BASE_URL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/"; // From your Face subscription in the Azure portal, get your subscription key and endpoint. static readonly string SUBSCRIPTION_KEY = Environment.GetEnvironmentVariable("FACE_APIKEY") ?? "<apikey>"; static readonly string ENDPOINT = Environment.GetEnvironmentVariable("FACE_ENDPOINT") ?? "<endpoint>"; static void Main(string[] args) { // 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. FaceRecognitionModel RECOGNITION_MODEL4 = FaceRecognitionModel.Recognition04; // Authenticate. FaceClient client = Authenticate(ENDPOINT, SUBSCRIPTION_KEY); // Identify - recognize a face(s) in a large person group (a large person group is created in this example). IdentifyInLargePersonGroup(client, IMAGE_BASE_URL, RECOGNITION_MODEL4).Wait(); Console.WriteLine("End of quickstart."); } /* * AUTHENTICATE * Uses subscription key and region to create a client. */ public static FaceClient Authenticate(string endpoint, string key) { return new FaceClient(new Uri(endpoint), new AzureKeyCredential(key)); } // Detect faces from image url for recognition purposes. This is a helper method for other functions in this quickstart. // Parameter `returnFaceId` of `DetectAsync` must be set to `true` (by default) for recognition purposes. // Parameter `returnFaceAttributes` is set to include the QualityForRecognition attribute. // Recognition model must be set to recognition_03 or recognition_04 as a result. // Result faces with insufficient quality for recognition are filtered out. // The field `faceId` in returned `DetectedFace`s will be used in Verify and Identify. // It will expire 24 hours after the detection call. private static async Task<List<FaceDetectionResult>> DetectFaceRecognize(FaceClient faceClient, string url, FaceRecognitionModel recognition_model) { // Detect faces from image URL. Response<IReadOnlyList<FaceDetectionResult>> response = await faceClient.DetectAsync(new Uri(url), FaceDetectionModel.Detection03, recognition_model, returnFaceId: true, [FaceAttributeType.QualityForRecognition]); IReadOnlyList<FaceDetectionResult> detectedFaces = response.Value; List<FaceDetectionResult> sufficientQualityFaces = new List<FaceDetectionResult>(); foreach (FaceDetectionResult detectedFace in detectedFaces) { var faceQualityForRecognition = detectedFace.FaceAttributes.QualityForRecognition; if (faceQualityForRecognition.HasValue && (faceQualityForRecognition.Value != QualityForRecognition.Low)) { sufficientQualityFaces.Add(detectedFace); } } Console.WriteLine($"{detectedFaces.Count} face(s) with {sufficientQualityFaces.Count} having sufficient quality for recognition detected from image `{Path.GetFileName(url)}`"); return sufficientQualityFaces; } /* * IDENTIFY FACES * To identify faces, you need to create and define a large person group. * The Identify operation takes one or several face IDs from DetectedFace or PersistedFace and a LargePersonGroup and returns * a list of Person objects that each face might belong to. Returned Person objects are wrapped as Candidate objects, * which have a prediction confidence value. */ public static async Task IdentifyInLargePersonGroup(FaceClient client, string url, FaceRecognitionModel 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" } } }; // A group photo that includes some of the persons you seek to identify from your dictionary. string sourceImageFileName = "identification1.jpg"; // Create a large person group. Console.WriteLine($"Create a person group ({largePersonGroupId})."); HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY); using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["name"] = largePersonGroupId, ["recognitionModel"] = recognitionModel.ToString() })))) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); await httpClient.PutAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}", content); } // The similar faces will be grouped into a single large person group person. foreach (var groupedFace in personDictionary.Keys) { // Limit TPS await Task.Delay(250); string? personId = null; using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["name"] = groupedFace })))) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using (var response = await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}/persons", content)) { string contentString = await response.Content.ReadAsStringAsync(); personId = (string?)(JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString)?["personId"]); } } Console.WriteLine($"Create a person group person '{groupedFace}'."); // Add face to the large person group person. foreach (var similarImage in personDictionary[groupedFace]) { Console.WriteLine($"Check whether image is of sufficient quality for recognition"); Response<IReadOnlyList<FaceDetectionResult>> response = await client.DetectAsync(new Uri($"{url}{similarImage}"), FaceDetectionModel.Detection03, recognitionModel, returnFaceId: false, [FaceAttributeType.QualityForRecognition]); IReadOnlyList<FaceDetectionResult> detectedFaces1 = response.Value; bool sufficientQuality = true; foreach (var face1 in detectedFaces1) { var faceQualityForRecognition = face1.FaceAttributes.QualityForRecognition; // Only "high" quality images are recommended for person enrollment if (faceQualityForRecognition.HasValue && (faceQualityForRecognition.Value != QualityForRecognition.High)) { sufficientQuality = false; break; } } if (!sufficientQuality) { continue; } if (detectedFaces1.Count != 1) { continue; } // add face to the large person group Console.WriteLine($"Add face to the person group person({groupedFace}) from image `{similarImage}`"); using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["url"] = $"{url}{similarImage}" })))) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}/persons/{personId}/persistedfaces?detectionModel=detection_03", content); } } } // Start to train the large person group. Console.WriteLine(); Console.WriteLine($"Train person group {largePersonGroupId}."); await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}/train", null); // Wait until the training is completed. while (true) { await Task.Delay(1000); string? trainingStatus = null; using (var response = await httpClient.GetAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}/training")) { string contentString = await response.Content.ReadAsStringAsync(); trainingStatus = (string?)(JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString)?["status"]); } Console.WriteLine($"Training status: {trainingStatus}."); if ("succeeded".Equals(trainingStatus)) { break; } } Console.WriteLine(); Console.WriteLine("Pausing for 60 seconds to avoid triggering rate limit on free account..."); await Task.Delay(60000); List<Guid> sourceFaceIds = new List<Guid>(); // Detect faces from source image url. List<FaceDetectionResult> detectedFaces = await DetectFaceRecognize(client, $"{url}{sourceImageFileName}", recognitionModel); // Add detected faceId to sourceFaceIds. foreach (var detectedFace in detectedFaces) { sourceFaceIds.Add(detectedFace.FaceId.Value); } // Identify the faces in a large person group. List<Dictionary<string, object>> identifyResults = new List<Dictionary<string, object>>(); using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["faceIds"] = sourceFaceIds, ["largePersonGroupId"] = largePersonGroupId })))) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using (var response = await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/identify", content)) { string contentString = await response.Content.ReadAsStringAsync(); identifyResults = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(contentString) ?? []; } } foreach (var identifyResult in identifyResults) { string faceId = (string)identifyResult["faceId"]; List<Dictionary<string, object>> candidates = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(((JArray)identifyResult["candidates"]).ToString()) ?? []; if (candidates.Count == 0) { Console.WriteLine($"No person is identified for the face in: {sourceImageFileName} - {faceId},"); continue; } string? personName = null; using (var response = await httpClient.GetAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}/persons/{candidates.First()["personId"]}")) { string contentString = await response.Content.ReadAsStringAsync(); personName = (string?)(JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString)?["name"]); } Console.WriteLine($"Person '{personName}' is identified for the face in: {sourceImageFileName} - {faceId}," + $" confidence: {candidates.First()["confidence"]}."); Dictionary<string, object> verifyResult = new Dictionary<string, object>(); using (var content = new ByteArrayContent(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new Dictionary<string, object> { ["faceId"] = faceId, ["personId"] = candidates.First()["personId"], ["largePersonGroupId"] = largePersonGroupId })))) { content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using (var response = await httpClient.PostAsync($"{ENDPOINT}/face/v1.0/verify", content)) { string contentString = await response.Content.ReadAsStringAsync(); verifyResult = JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString) ?? []; } } Console.WriteLine($"Verification result: is a match? {verifyResult["isIdentical"]}. confidence: {verifyResult["confidence"]}"); } Console.WriteLine(); // Delete large person group. Console.WriteLine("========DELETE PERSON GROUP========"); Console.WriteLine(); await httpClient.DeleteAsync($"{ENDPOINT}/face/v1.0/largepersongroups/{largePersonGroupId}"); Console.WriteLine($"Deleted the person group {largePersonGroupId}."); Console.WriteLine(); } } }
アプリケーションの実行
IDE ウィンドウの上部にある [デバッグ] ボタンをクリックして、アプリケーションを実行します。
出力
========IDENTIFY FACES========
Create a person group (18d1c443-a01b-46a4-9191-121f74a831cd).
Create a person group person 'Family1-Dad'.
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Dad) from image `Family1-Dad1.jpg`
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Dad) from image `Family1-Dad2.jpg`
Create a person group person 'Family1-Mom'.
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Mom) from image `Family1-Mom1.jpg`
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Mom) from image `Family1-Mom2.jpg`
Create a person group person 'Family1-Son'.
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Son) from image `Family1-Son1.jpg`
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Son) from image `Family1-Son2.jpg`
Train person group 18d1c443-a01b-46a4-9191-121f74a831cd.
Training status: succeeded.
Pausing for 60 seconds to avoid triggering rate limit on free account...
4 face(s) with 4 having sufficient quality for recognition detected from image `identification1.jpg`
Person 'Family1-Dad' is identified for the face in: identification1.jpg - ad813534-9141-47b4-bfba-24919223966f, confidence: 0.96807.
Verification result: is a match? True. confidence: 0.96807
Person 'Family1-Mom' is identified for the face in: identification1.jpg - 1a39420e-f517-4cee-a898-5d968dac1a7e, confidence: 0.96902.
Verification result: is a match? True. confidence: 0.96902
No person is identified for the face in: identification1.jpg - 889394b1-e30f-4147-9be1-302beb5573f3,
Person 'Family1-Son' is identified for the face in: identification1.jpg - 0557d87b-356c-48a8-988f-ce0ad2239aa5, confidence: 0.9281.
Verification result: is a match? True. confidence: 0.9281
========DELETE PERSON GROUP========
Deleted the person group 18d1c443-a01b-46a4-9191-121f74a831cd.
End of quickstart.
ヒント
Face API は、本質的に静的な一連の事前構築済みモデルで実行されます (サービスの実行中にモデルのパフォーマンスが低下したり改善されたりすることはありません)。 Microsoft により、まったく新しいモデル バージョンに移行することなくモデルのバックエンドが更新されると、モデルによって生成される結果が変わる可能性があります。 より新しいバージョンのモデルを利用するには、同じ登録画像でより新しいモデルをパラメーターとして指定し、PersonGroup を再トレーニングすることができます。
リソースをクリーンアップする
Azure AI サービス サブスクリプションをクリーンアップして削除したい場合は、リソースまたはリソース グループを削除することができます。 リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。
次のステップ
このクイックスタートでは、.NET 用の Face クライアント ライブラリを使用して基本的な顔識別を行う方法について学習しました。 次に、さまざまな顔検出モデルと、ユース ケースに適したモデルを指定する方法について学習します。
- Face サービスとは
- より広範なサンプル コードが GitHub にあります。
Python 用 Face クライアント ライブラリを使用して顔認識を開始します。 以下の手順に従って、パッケージをインストールし、基本タスクのコード例を試してみましょう。 Face サービスは、画像内の人間の顔を検出および認識するための高度なアルゴリズムへのアクセスを提供します。 以下の手順に従って、パッケージをインストールし、リモート画像を使用した基本的な顔識別のためのコード例を試してみましょう。
リファレンス ドキュメント | ライブラリのソース コード | パッケージ (PiPy) | サンプル
前提条件
- Azure サブスクリプション - 無料アカウントを作成します
- Python 3.x
- Python のインストールには、pip が含まれている必要があります。 pip がインストールされているかどうかを確認するには、コマンド ラインで
pip --version
を実行します。 最新バージョンの Python をインストールして pip を入手してください。
- Python のインストールには、pip が含まれている必要があります。 pip がインストールされているかどうかを確認するには、コマンド ラインで
- Azure サブスクリプションを入手したら、Azure portal で Face リソースを作成し、キーとエンドポイントを取得します。 デプロイされたら、 [リソースに移動] を選択します。
- 対象のアプリケーションを Face API に接続するには、作成したリソースのキーとエンドポイントが必要です。
- Free 価格レベル (
F0
) を使用してサービスを試用し、後から運用環境用の有料レベルにアップグレードすることができます。
環境変数を作成する
この例では、アプリケーションを実行しているローカル コンピューター上の環境変数に資格情報を書き込みます。
Azure portal に移動します。 「前提条件」 セクションで作成したリソースが正常にデプロイされた場合、[次の手順] の下にある [リソースに移動] を選択します。 キーとエンドポイントは、[キーとエンドポイント] ページの [リソース管理] にあります。 リソース キーは Azure サブスクリプション ID と同じではありません。
キーとエンドポイントの環境変数を設定するには、コンソール ウィンドウを開き、オペレーティング システムと開発環境の指示に従います。
FACE_APIKEY
環境変数を設定するには、<your_key>
をリソースのキーの 1 つに置き換えます。FACE_ENDPOINT
環境変数を設定するには、<your_endpoint>
をリソースのエンドポイントに置き換えます。
重要
API キーを使用する場合は、それを Azure Key Vault などの別の場所に安全に保存します。 API キーは、コード内に直接含めないようにし、絶対に公開しないでください。
AI サービスのセキュリティの詳細については、「Azure AI サービスに対する要求の認証」を参照してください。
setx FACE_APIKEY <your_key>
setx FACE_ENDPOINT <your_endpoint>
実行中のプログラムのうち、環境変数の読み取りを必要とするプログラム (コンソール ウィンドウを含む) については、環境変数を読み込む再起動が必要となる場合があります。
顔を識別して検証する
クライアント ライブラリをインストールする
Python をインストールしたら、次を使用してクライアント ライブラリをインストールすることができます。
pip install --upgrade azure-ai-vision-face
新しい Python アプリケーションを作成する
新しい Python スクリプト (たとえば quickstart-file.py) を作成します。 次に、それを任意のエディターまたは IDE で開き、次のコードを貼り付けます。
Note
取り込みフォームを使用して Face サービスへのアクセスを受け取っていない場合、これらの関数の一部は機能しません。
import os import time import uuid import requests from azure.core.credentials import AzureKeyCredential from azure.ai.vision.face import FaceClient from azure.ai.vision.face.models import ( FaceAttributeTypeRecognition04, FaceDetectionModel, FaceRecognitionModel, QualityForRecognition, ) # This key will serve all examples in this document. KEY = os.environ["FACE_APIKEY"] # This endpoint will be used in all examples in this quickstart. ENDPOINT = os.environ["FACE_ENDPOINT"] # Used in the Large Person Group Operations and Delete Large Person Group examples. # LARGE_PERSON_GROUP_ID should be all lowercase and alphanumeric. For example, 'mygroupname' (dashes are OK). LARGE_PERSON_GROUP_ID = str(uuid.uuid4()) # assign a random ID (or name it anything) HEADERS = {"Ocp-Apim-Subscription-Key": KEY, "Content-Type": "application/json"} # Create an authenticated FaceClient. with FaceClient(endpoint=ENDPOINT, credential=AzureKeyCredential(KEY)) as face_client: ''' Create the LargePersonGroup ''' # Create empty Large Person Group. Large Person Group ID must be lower case, alphanumeric, and/or with '-', '_'. print("Person group:", LARGE_PERSON_GROUP_ID) response = requests.put( ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}", headers=HEADERS, json={"name": LARGE_PERSON_GROUP_ID, "recognitionModel": "recognition_04"}) response.raise_for_status() # Define woman friend response = requests.post(ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/persons", headers=HEADERS, json={"name": "Woman"}) response.raise_for_status() woman = response.json() # Define man friend response = requests.post(ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/persons", headers=HEADERS, json={"name": "Man"}) response.raise_for_status() man = response.json() # Define child friend response = requests.post(ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/persons", headers=HEADERS, json={"name": "Child"}) response.raise_for_status() child = response.json() ''' Detect faces and register them to each person ''' # Find all jpeg images of friends in working directory (TBD pull from web instead) woman_images = [ "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Mom1.jpg", # noqa: E501 "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Mom2.jpg", # noqa: E501 ] man_images = [ "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Dad1.jpg", # noqa: E501 "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Dad2.jpg", # noqa: E501 ] child_images = [ "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Son1.jpg", # noqa: E501 "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Son2.jpg", # noqa: E501 ] # Add to woman person for image in woman_images: # Check if the image is of sufficent quality for recognition. sufficientQuality = True detected_faces = face_client.detect_from_url( url=image, detection_model=FaceDetectionModel.DETECTION_03, recognition_model=FaceRecognitionModel.RECOGNITION_04, return_face_id=True, return_face_attributes=[FaceAttributeTypeRecognition04.QUALITY_FOR_RECOGNITION]) for face in detected_faces: if face.face_attributes.quality_for_recognition != QualityForRecognition.HIGH: sufficientQuality = False break if not sufficientQuality: continue if len(detected_faces) != 1: continue response = requests.post( ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/persons/{woman['personId']}/persistedFaces", headers=HEADERS, json={"url": image}) response.raise_for_status() print(f"face {face.face_id} added to person {woman['personId']}") # Add to man person for image in man_images: # Check if the image is of sufficent quality for recognition. sufficientQuality = True detected_faces = face_client.detect_from_url( url=image, detection_model=FaceDetectionModel.DETECTION_03, recognition_model=FaceRecognitionModel.RECOGNITION_04, return_face_id=True, return_face_attributes=[FaceAttributeTypeRecognition04.QUALITY_FOR_RECOGNITION]) for face in detected_faces: if face.face_attributes.quality_for_recognition != QualityForRecognition.HIGH: sufficientQuality = False break if not sufficientQuality: continue if len(detected_faces) != 1: continue response = requests.post( ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/persons/{man['personId']}/persistedFaces", headers=HEADERS, json={"url": image}) response.raise_for_status() print(f"face {face.face_id} added to person {man['personId']}") # Add to child person for image in child_images: # Check if the image is of sufficent quality for recognition. sufficientQuality = True detected_faces = face_client.detect_from_url( url=image, detection_model=FaceDetectionModel.DETECTION_03, recognition_model=FaceRecognitionModel.RECOGNITION_04, return_face_id=True, return_face_attributes=[FaceAttributeTypeRecognition04.QUALITY_FOR_RECOGNITION]) for face in detected_faces: if face.face_attributes.quality_for_recognition != QualityForRecognition.HIGH: sufficientQuality = False break if not sufficientQuality: continue if len(detected_faces) != 1: continue response = requests.post( ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/persons/{child['personId']}/persistedFaces", headers=HEADERS, json={"url": image}) response.raise_for_status() print(f"face {face.face_id} added to person {child['personId']}") ''' Train LargePersonGroup ''' # Train the large person group print(f"Train the person group {LARGE_PERSON_GROUP_ID}") response = requests.post(ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/train", headers=HEADERS) response.raise_for_status() while (True): response = requests.get(ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}/training", headers=HEADERS) response.raise_for_status() training_status = response.json()["status"] if training_status == "succeeded": break print(f"The person group {LARGE_PERSON_GROUP_ID} is trained successfully.") ''' Identify a face against a defined LargePersonGroup ''' # Group image for testing against test_image = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/identification1.jpg" # noqa: E501 print("Pausing for 60 seconds to avoid triggering rate limit on free account...") time.sleep(60) # Detect faces face_ids = [] # We use detection model 03 to get better performance, recognition model 04 to support quality for # recognition attribute. faces = face_client.detect_from_url( url=test_image, detection_model=FaceDetectionModel.DETECTION_03, recognition_model=FaceRecognitionModel.RECOGNITION_04, return_face_id=True, return_face_attributes=[FaceAttributeTypeRecognition04.QUALITY_FOR_RECOGNITION]) for face in faces: # Only take the face if it is of sufficient quality. if face.face_attributes.quality_for_recognition != QualityForRecognition.LOW: face_ids.append(face.face_id) # Identify faces response = requests.post( ENDPOINT + f"/face/v1.0/identify", headers=HEADERS, json={"faceIds": face_ids, "largePersonGroupId": LARGE_PERSON_GROUP_ID}) response.raise_for_status() results = response.json() print("Identifying faces in image") if not results: print("No person identified in the person group") for identifiedFace in results: if len(identifiedFace["candidates"]) > 0: print(f"Person is identified for face ID {identifiedFace['faceId']} in image, with a confidence of " f"{identifiedFace['candidates'][0]['confidence']}.") # Get topmost confidence score # Verify faces response = requests.post( ENDPOINT + f"/face/v1.0/verify", headers=HEADERS, json={"faceId": identifiedFace["faceId"], "personId": identifiedFace["candidates"][0]["personId"], "largePersonGroupId": LARGE_PERSON_GROUP_ID}) response.raise_for_status() verify_result = response.json() print(f"verification result: {verify_result['isIdentical']}. confidence: {verify_result['confidence']}") else: print(f"No person identified for face ID {identifiedFace['faceId']} in image.") print() # Delete the large person group response = requests.delete(ENDPOINT + f"/face/v1.0/largepersongroups/{LARGE_PERSON_GROUP_ID}", headers=HEADERS) response.raise_for_status() print(f"The person group {LARGE_PERSON_GROUP_ID} is deleted.") print() print("End of quickstart.")
python
コマンドを使用して、アプリケーション ディレクトリから顔認識アプリを実行します。python quickstart-file.py
ヒント
Face API は、本質的に静的な一連の事前構築済みモデルで実行されます (サービスの実行中にモデルのパフォーマンスが低下したり改善されたりすることはありません)。 Microsoft により、まったく新しいモデル バージョンに移行することなくモデルのバックエンドが更新されると、モデルによって生成される結果が変わる可能性があります。 より新しいバージョンのモデルを利用するには、同じ登録画像でより新しいモデルをパラメーターとして指定し、PersonGroup を再トレーニングすることができます。
出力
Person group: ad12b2db-d892-48ec-837a-0e7168c18224
face 335a2cb1-5211-4c29-9c45-776dd014b2af added to person 9ee65510-81a5-47e5-9e50-66727f719465
face df57eb50-4a13-4f93-b804-cd108327ad5a added to person 9ee65510-81a5-47e5-9e50-66727f719465
face d8b7b8b8-3ca6-4309-b76e-eeed84f7738a added to person 00651036-4236-4004-88b9-11466c251548
face dffbb141-f40b-4392-8785-b6c434fa534e added to person 00651036-4236-4004-88b9-11466c251548
face 9cdac36e-5455-447b-a68d-eb1f5e2ec27d added to person 23614724-b132-407a-aaa0-67003987ce93
face d8208412-92b7-4b8d-a2f8-3926c839c87e added to person 23614724-b132-407a-aaa0-67003987ce93
Train the person group ad12b2db-d892-48ec-837a-0e7168c18224
The person group ad12b2db-d892-48ec-837a-0e7168c18224 is trained successfully.
Pausing for 60 seconds to avoid triggering rate limit on free account...
Identifying faces in image
Person is identified for face ID bc52405a-5d83-4500-9218-557468ccdf99 in image, with a confidence of 0.96726.
verification result: True. confidence: 0.96726
Person is identified for face ID dfcc3fc8-6252-4f3a-8205-71466f39d1a7 in image, with a confidence of 0.96925.
verification result: True. confidence: 0.96925
No person identified for face ID 401c581b-a178-45ed-8205-7692f6eede88 in image.
Person is identified for face ID 8809d9c7-e362-4727-8c95-e1e44f5c2e8a in image, with a confidence of 0.92898.
verification result: True. confidence: 0.92898
The person group ad12b2db-d892-48ec-837a-0e7168c18224 is deleted.
End of quickstart.
リソースをクリーンアップする
Azure AI サービス サブスクリプションをクリーンアップして削除したい場合は、リソースまたはリソース グループを削除することができます。 リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。
次のステップ
このクイックスタートでは、Python 用の Face クライアント ライブラリを使用して基本的な顔識別を行う方法について学習しました。 次に、さまざまな顔検出モデルと、ユース ケースに適したモデルを指定する方法について学習します。
- Face サービスとは
- より広範なサンプル コードが GitHub にあります。
Java 用の Face クライアント ライブラリを使用して顔認識を開始します。 以下の手順に従って、パッケージをインストールし、基本タスクのコード例を試してみましょう。 Face サービスは、画像内の人間の顔を検出および認識するための高度なアルゴリズムへのアクセスを提供します。 以下の手順に従って、パッケージをインストールし、リモート画像を使用した基本的な顔識別のためのコード例を試してみましょう。
リファレンスのドキュメント | ライブラリのソース コード | パッケージ (Maven) | サンプル
前提条件
- Azure サブスクリプション - 無料アカウントを作成します
- 最新バージョンの Java Development Kit (JDK)
- Apache Maven がインストールされています。 Linux では、ディストリビューション リポジトリ (使用可能な場合) からインストールします。
- Azure サブスクリプションを入手したら、Azure portal で Face リソースを作成し、キーとエンドポイントを取得します。 デプロイされたら、 [リソースに移動] を選択します。
- 対象のアプリケーションを Face API に接続するには、作成したリソースのキーとエンドポイントが必要です。
- Free 価格レベル (
F0
) を使用してサービスを試用し、後から運用環境用の有料レベルにアップグレードすることができます。
環境変数を作成する
この例では、アプリケーションを実行しているローカル コンピューター上の環境変数に資格情報を書き込みます。
Azure portal に移動します。 「前提条件」 セクションで作成したリソースが正常にデプロイされた場合、[次の手順] の下にある [リソースに移動] を選択します。 キーとエンドポイントは、[キーとエンドポイント] ページの [リソース管理] にあります。 リソース キーは Azure サブスクリプション ID と同じではありません。
キーとエンドポイントの環境変数を設定するには、コンソール ウィンドウを開き、オペレーティング システムと開発環境の指示に従います。
FACE_APIKEY
環境変数を設定するには、<your_key>
をリソースのキーの 1 つに置き換えます。FACE_ENDPOINT
環境変数を設定するには、<your_endpoint>
をリソースのエンドポイントに置き換えます。
重要
API キーを使用する場合は、それを Azure Key Vault などの別の場所に安全に保存します。 API キーは、コード内に直接含めないようにし、絶対に公開しないでください。
AI サービスのセキュリティの詳細については、「Azure AI サービスに対する要求の認証」を参照してください。
setx FACE_APIKEY <your_key>
setx FACE_ENDPOINT <your_endpoint>
実行中のプログラムのうち、環境変数の読み取りを必要とするプログラム (コンソール ウィンドウを含む) については、環境変数を読み込む再起動が必要となる場合があります。
顔を識別して検証する
クライアント ライブラリをインストールする
コンソール ウィンドウを開き、クイックスタート アプリケーション用の新しいフォルダーを作成します。 新しいファイルに次の内容をコピーします。 プロジェクト ディレクトリにファイルを
pom.xml
として保存します。<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>my-application-name</artifactId> <version>1.0.0</version> <dependencies> <!-- https://mvnrepository.com/artifact/com.azure/azure-ai-vision-face --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-ai-vision-face</artifactId> <version>1.0.0-beta.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> </dependency> </dependencies> </project>
プロジェクト ディレクトリで次を実行して、SDK と依存関係をインストールします:
mvn clean dependency:copy-dependencies
新しい Java アプリケーションを作成する
Quickstart.java
という名前のファイルを作成し、テキスト エディターで開き、次のコードを貼り付けます。Note
取り込みフォームを使用して Face サービスへのアクセスを受け取っていない場合、これらの関数の一部は機能しません。
import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.UUID; import com.azure.ai.vision.face.FaceClient; import com.azure.ai.vision.face.FaceClientBuilder; import com.azure.ai.vision.face.models.DetectOptions; import com.azure.ai.vision.face.models.FaceAttributeType; import com.azure.ai.vision.face.models.FaceDetectionModel; import com.azure.ai.vision.face.models.FaceDetectionResult; import com.azure.ai.vision.face.models.FaceRecognitionModel; import com.azure.ai.vision.face.models.QualityForRecognition; import com.azure.core.credential.KeyCredential; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.apache.http.HttpHeaders; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; public class Quickstart { // LARGE_PERSON_GROUP_ID should be all lowercase and alphanumeric. For example, 'mygroupname' (dashes are OK). private static final String LARGE_PERSON_GROUP_ID = UUID.randomUUID().toString(); // URL path for the images. private static final String IMAGE_BASE_URL = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/"; // From your Face subscription in the Azure portal, get your subscription key and endpoint. private static final String SUBSCRIPTION_KEY = System.getenv("FACE_APIKEY"); private static final String ENDPOINT = System.getenv("FACE_ENDPOINT"); public static void main(String[] args) throws Exception { // 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. FaceRecognitionModel RECOGNITION_MODEL4 = FaceRecognitionModel.RECOGNITION_04; // Authenticate. FaceClient client = authenticate(ENDPOINT, SUBSCRIPTION_KEY); // Identify - recognize a face(s) in a large person group (a large person group is created in this example). identifyInLargePersonGroup(client, IMAGE_BASE_URL, RECOGNITION_MODEL4); System.out.println("End of quickstart."); } /* * AUTHENTICATE * Uses subscription key and region to create a client. */ public static FaceClient authenticate(String endpoint, String key) { return new FaceClientBuilder().endpoint(endpoint).credential(new KeyCredential(key)).buildClient(); } // Detect faces from image url for recognition purposes. This is a helper method for other functions in this quickstart. // Parameter `returnFaceId` of `DetectOptions` must be set to `true` (by default) for recognition purposes. // Parameter `returnFaceAttributes` is set to include the QualityForRecognition attribute. // Recognition model must be set to recognition_03 or recognition_04 as a result. // Result faces with insufficient quality for recognition are filtered out. // The field `faceId` in returned `DetectedFace`s will be used in Verify and Identify. // It will expire 24 hours after the detection call. private static List<FaceDetectionResult> detectFaceRecognize(FaceClient faceClient, String url, FaceRecognitionModel recognitionModel) { // Detect faces from image URL. DetectOptions options = new DetectOptions(FaceDetectionModel.DETECTION_03, recognitionModel, true).setReturnFaceAttributes(Arrays.asList(FaceAttributeType.QUALITY_FOR_RECOGNITION)); List<FaceDetectionResult> detectedFaces = faceClient.detect(url, options); List<FaceDetectionResult> sufficientQualityFaces = detectedFaces.stream().filter(f -> f.getFaceAttributes().getQualityForRecognition() != QualityForRecognition.LOW).collect(Collectors.toList()); System.out.println(detectedFaces.size() + " face(s) with " + sufficientQualityFaces.size() + " having sufficient quality for recognition."); return sufficientQualityFaces; } /* * IDENTIFY FACES * To identify faces, you need to create and define a large person group. * The Identify operation takes one or several face IDs from DetectedFace or PersistedFace and a LargePersonGroup and returns * a list of Person objects that each face might belong to. Returned Person objects are wrapped as Candidate objects, * which have a prediction confidence value. */ public static void identifyInLargePersonGroup(FaceClient client, String url, FaceRecognitionModel recognitionModel) throws Exception { System.out.println("========IDENTIFY FACES========"); System.out.println(); // Create a dictionary for all your images, grouping similar ones under the same key. Map<String, String[]> personDictionary = new LinkedHashMap<String, String[]>(); personDictionary.put("Family1-Dad", new String[]{"Family1-Dad1.jpg", "Family1-Dad2.jpg"}); personDictionary.put("Family1-Mom", new String[]{"Family1-Mom1.jpg", "Family1-Mom2.jpg"}); personDictionary.put("Family1-Son", new String[]{"Family1-Son1.jpg", "Family1-Son2.jpg"}); // A group photo that includes some of the persons you seek to identify from your dictionary. String sourceImageFileName = "identification1.jpg"; // Create a large person group. System.out.println("Create a person group (" + LARGE_PERSON_GROUP_ID + ")."); List<BasicHeader> headers = Arrays.asList(new BasicHeader("Ocp-Apim-Subscription-Key", SUBSCRIPTION_KEY), new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json")); HttpClient httpClient = HttpClients.custom().setDefaultHeaders(headers).build(); createLargePersonGroup(httpClient, recognitionModel); // The similar faces will be grouped into a single large person group person. for (String groupedFace : personDictionary.keySet()) { // Limit TPS Thread.sleep(250); String personId = createLargePersonGroupPerson(httpClient, groupedFace); System.out.println("Create a person group person '" + groupedFace + "'."); // Add face to the large person group person. for (String similarImage : personDictionary.get(groupedFace)) { System.out.println("Check whether image is of sufficient quality for recognition"); DetectOptions options = new DetectOptions(FaceDetectionModel.DETECTION_03, recognitionModel, false).setReturnFaceAttributes(Arrays.asList(FaceAttributeType.QUALITY_FOR_RECOGNITION)); List<FaceDetectionResult> detectedFaces1 = client.detect(url + similarImage, options); if (detectedFaces1.stream().anyMatch(f -> f.getFaceAttributes().getQualityForRecognition() != QualityForRecognition.HIGH)) { continue; } if (detectedFaces1.size() != 1) { continue; } // add face to the large person group System.out.println("Add face to the person group person(" + groupedFace + ") from image `" + similarImage + "`"); addFaceToLargePersonGroup(httpClient, personId, url + similarImage); } } // Start to train the large person group. System.out.println(); System.out.println("Train person group " + LARGE_PERSON_GROUP_ID + "."); trainLargePersonGroup(httpClient); // Wait until the training is completed. while (true) { Thread.sleep(1000); String trainingStatus = getLargePersonGroupTrainingStatus(httpClient); System.out.println("Training status: " + trainingStatus + "."); if ("succeeded".equals(trainingStatus)) { break; } } System.out.println(); System.out.println("Pausing for 60 seconds to avoid triggering rate limit on free account..."); Thread.sleep(60000); // Detect faces from source image url. List<FaceDetectionResult> detectedFaces = detectFaceRecognize(client, url + sourceImageFileName, recognitionModel); // Add detected faceId to sourceFaceIds. List<String> sourceFaceIds = detectedFaces.stream().map(FaceDetectionResult::getFaceId).collect(Collectors.toList()); // Identify the faces in a large person group. List<Map<String, Object>> identifyResults = identifyFacesInLargePersonGroup(httpClient, sourceFaceIds); for (Map<String, Object> identifyResult : identifyResults) { String faceId = identifyResult.get("faceId").toString(); List<Map<String, Object>> candidates = new Gson().fromJson(new Gson().toJson(identifyResult.get("candidates")), new TypeToken<List<Map<String, Object>>>(){}); if (candidates.isEmpty()) { System.out.println("No person is identified for the face in: " + sourceImageFileName + " - " + faceId + "."); continue; } Map<String, Object> candidate = candidates.stream().findFirst().orElseThrow(); String personName = getLargePersonGroupPersonName(httpClient, candidate.get("personId").toString()); System.out.println("Person '" + personName + "' is identified for the face in: " + sourceImageFileName + " - " + faceId + ", confidence: " + candidate.get("confidence") + "."); Map<String, Object> verifyResult = verifyFaceWithLargePersonGroupPerson(httpClient, faceId, candidate.get("personId").toString()); System.out.println("Verification result: is a match? " + verifyResult.get("isIdentical") + ". confidence: " + verifyResult.get("confidence")); } System.out.println(); // Delete large person group. System.out.println("========DELETE PERSON GROUP========"); System.out.println(); deleteLargePersonGroup(httpClient); System.out.println("Deleted the person group " + LARGE_PERSON_GROUP_ID + "."); System.out.println(); } private static void createLargePersonGroup(HttpClient httpClient, FaceRecognitionModel recognitionModel) throws Exception { HttpPut request = new HttpPut(new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID).build()); request.setEntity(new StringEntity(new Gson().toJson(Map.of("name", LARGE_PERSON_GROUP_ID, "recognitionModel", recognitionModel.toString())))); httpClient.execute(request); request.releaseConnection(); } private static String createLargePersonGroupPerson(HttpClient httpClient, String name) throws Exception { HttpPost request = new HttpPost(new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID + "/persons").build()); request.setEntity(new StringEntity(new Gson().toJson(Map.of("name", name)))); String response = EntityUtils.toString(httpClient.execute(request).getEntity()); request.releaseConnection(); return new Gson().fromJson(response, new TypeToken<Map<String, Object>>(){}).get("personId").toString(); } private static void addFaceToLargePersonGroup(HttpClient httpClient, String personId, String url) throws Exception { URIBuilder builder = new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID + "/persons/" + personId + "/persistedfaces"); builder.setParameter("detectionModel", "detection_03"); HttpPost request = new HttpPost(builder.build()); request.setEntity(new StringEntity(new Gson().toJson(Map.of("url", url)))); httpClient.execute(request); request.releaseConnection(); } private static void trainLargePersonGroup(HttpClient httpClient) throws Exception { HttpPost request = new HttpPost(new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID + "/train").build()); httpClient.execute(request); request.releaseConnection(); } private static String getLargePersonGroupTrainingStatus(HttpClient httpClient) throws Exception { HttpGet request = new HttpGet(new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID + "/training").build()); String response = EntityUtils.toString(httpClient.execute(request).getEntity()); request.releaseConnection(); return new Gson().fromJson(response, new TypeToken<Map<String, Object>>(){}).get("status").toString(); } private static List<Map<String, Object>> identifyFacesInLargePersonGroup(HttpClient httpClient, List<String> sourceFaceIds) throws Exception { HttpPost request = new HttpPost(new URIBuilder(ENDPOINT + "/face/v1.0/identify").build()); request.setEntity(new StringEntity(new Gson().toJson(Map.of("faceIds", sourceFaceIds, "largePersonGroupId", LARGE_PERSON_GROUP_ID)))); String response = EntityUtils.toString(httpClient.execute(request).getEntity()); request.releaseConnection(); return new Gson().fromJson(response, new TypeToken<List<Map<String, Object>>>(){}); } private static String getLargePersonGroupPersonName(HttpClient httpClient, String personId) throws Exception { HttpGet request = new HttpGet(new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID + "/persons/" + personId).build()); String response = EntityUtils.toString(httpClient.execute(request).getEntity()); request.releaseConnection(); return new Gson().fromJson(response, new TypeToken<Map<String, Object>>(){}).get("name").toString(); } private static Map<String, Object> verifyFaceWithLargePersonGroupPerson(HttpClient httpClient, String faceId, String personId) throws Exception { HttpPost request = new HttpPost(new URIBuilder(ENDPOINT + "/face/v1.0/verify").build()); request.setEntity(new StringEntity(new Gson().toJson(Map.of("faceId", faceId, "personId", personId, "largePersonGroupId", LARGE_PERSON_GROUP_ID)))); String response = EntityUtils.toString(httpClient.execute(request).getEntity()); request.releaseConnection(); return new Gson().fromJson(response, new TypeToken<Map<String, Object>>(){}); } private static void deleteLargePersonGroup(HttpClient httpClient) throws Exception { HttpDelete request = new HttpDelete(new URIBuilder(ENDPOINT + "/face/v1.0/largepersongroups/" + LARGE_PERSON_GROUP_ID).build()); httpClient.execute(request); request.releaseConnection(); } }
javac
コマンドとjava
コマンドを使用して、アプリケーション ディレクトリから顔認識アプリを実行します。
出力
========IDENTIFY FACES========
Create a person group (3761e61a-16b2-4503-ad29-ed34c58ba676).
Create a person group person 'Family1-Dad'.
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Dad) from image `Family1-Dad1.jpg`
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Dad) from image `Family1-Dad2.jpg`
Create a person group person 'Family1-Mom'.
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Mom) from image `Family1-Mom1.jpg`
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Mom) from image `Family1-Mom2.jpg`
Create a person group person 'Family1-Son'.
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Son) from image `Family1-Son1.jpg`
Check whether image is of sufficient quality for recognition
Add face to the person group person(Family1-Son) from image `Family1-Son2.jpg`
Train person group 3761e61a-16b2-4503-ad29-ed34c58ba676.
Training status: succeeded.
Pausing for 60 seconds to avoid triggering rate limit on free account...
4 face(s) with 4 having sufficient quality for recognition.
Person 'Family1-Dad' is identified for the face in: identification1.jpg - d7995b34-1b72-47fe-82b6-e9877ed2578d, confidence: 0.96807.
Verification result: is a match? true. confidence: 0.96807
Person 'Family1-Mom' is identified for the face in: identification1.jpg - 844da0ed-4890-4bbf-a531-e638797f96fc, confidence: 0.96902.
Verification result: is a match? true. confidence: 0.96902
No person is identified for the face in: identification1.jpg - c543159a-57f3-4872-83ce-2d4a733d71c9.
Person 'Family1-Son' is identified for the face in: identification1.jpg - 414fac6c-7381-4dba-9c8b-fd26d52e879b, confidence: 0.9281.
Verification result: is a match? true. confidence: 0.9281
========DELETE PERSON GROUP========
Deleted the person group 3761e61a-16b2-4503-ad29-ed34c58ba676.
End of quickstart.
リソースをクリーンアップする
Azure AI サービス サブスクリプションをクリーンアップして削除したい場合は、リソースまたはリソース グループを削除することができます。 リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。
次のステップ
このクイックスタートでは、Java 用の Face クライアント ライブラリを使用して基本的な顔識別を行う方法について学習しました。 次に、さまざまな顔検出モデルと、ユース ケースに適したモデルを指定する方法について学習します。
- Face サービスとは
- より広範なサンプル コードが GitHub にあります。
JavaScript 用 Face クライアント ライブラリを使用して顔認識を開始します。 以下の手順に従って、パッケージをインストールし、基本タスクのコード例を試してみましょう。 Face サービスは、画像内の人間の顔を検出および認識するための高度なアルゴリズムへのアクセスを提供します。 以下の手順に従って、パッケージをインストールし、リモート画像を使用した基本的な顔識別のためのコード例を試してみましょう。
リファレンスのドキュメント | ライブラリのソース コード | パッケージ (npm) | サンプル
前提条件
- Azure サブスクリプション - 無料アカウントを作成します
- 最新バージョンの Node.js
- Azure サブスクリプションを入手したら、Azure portal で Face リソースを作成して、キーとエンドポイントを取得します。 デプロイされたら、 [リソースに移動] を選択します。
- 対象のアプリケーションを Face API に接続するには、作成したリソースのキーとエンドポイントが必要です。
- Free 価格レベル (
F0
) を使用してサービスを試用し、後から運用環境用の有料レベルにアップグレードすることができます。
環境変数を作成する
この例では、アプリケーションを実行しているローカル コンピューター上の環境変数に資格情報を書き込みます。
Azure portal に移動します。 「前提条件」 セクションで作成したリソースが正常にデプロイされた場合、[次の手順] の下にある [リソースに移動] を選択します。 キーとエンドポイントは、[キーとエンドポイント] ページの [リソース管理] にあります。 リソース キーは Azure サブスクリプション ID と同じではありません。
キーとエンドポイントの環境変数を設定するには、コンソール ウィンドウを開き、オペレーティング システムと開発環境の指示に従います。
FACE_APIKEY
環境変数を設定するには、<your_key>
をリソースのキーの 1 つに置き換えます。FACE_ENDPOINT
環境変数を設定するには、<your_endpoint>
をリソースのエンドポイントに置き換えます。
重要
API キーを使用する場合は、それを Azure Key Vault などの別の場所に安全に保存します。 API キーは、コード内に直接含めないようにし、絶対に公開しないでください。
AI サービスのセキュリティの詳細については、「Azure AI サービスに対する要求の認証」を参照してください。
setx FACE_APIKEY <your_key>
setx FACE_ENDPOINT <your_endpoint>
実行中のプログラムのうち、環境変数の読み取りを必要とするプログラム (コンソール ウィンドウを含む) については、環境変数を読み込む再起動が必要となる場合があります。
顔を識別して検証する
新しい Node.js アプリケーションを作成する
コンソール ウィンドウ (cmd、PowerShell、Bash など) で、ご利用のアプリ用に新しいディレクトリを作成し、そこに移動します。
mkdir myapp && cd myapp
npm init
コマンドを実行し、package.json
ファイルを使用して node アプリケーションを作成します。npm init
@azure-rest/ai-vision-face
npm パッケージをインストールします。npm install @azure-rest/ai-vision-face
アプリの
package.json
ファイルが依存関係によって更新されます。index.js
という名前のファイルを作成し、テキスト エディターで開き、次のコードを貼り付けます。Note
取り込みフォームを使用して Face サービスへのアクセスを受け取っていない場合、これらの関数の一部は機能しません。
const { randomUUID } = require("crypto"); const { AzureKeyCredential } = require("@azure/core-auth"); const createFaceClient = require("@azure-rest/ai-vision-face").default, { getLongRunningPoller } = require("@azure-rest/ai-vision-face"); const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const main = async () => { const endpoint = process.env["FACE_ENDPOINT"] ?? "<endpoint>"; const apikey = process.env["FACE_APIKEY"] ?? "<apikey>"; const credential = new AzureKeyCredential(apikey); const client = createFaceClient(endpoint, credential); const imageBaseUrl = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/"; const largePersonGroupId = randomUUID(); console.log("========IDENTIFY FACES========"); console.log(); // Create a dictionary for all your images, grouping similar ones under the same key. const personDictionary = { "Family1-Dad": ["Family1-Dad1.jpg", "Family1-Dad2.jpg"], "Family1-Mom": ["Family1-Mom1.jpg", "Family1-Mom2.jpg"], "Family1-Son": ["Family1-Son1.jpg", "Family1-Son2.jpg"], }; // A group photo that includes some of the persons you seek to identify from your dictionary. const sourceImageFileName = "identification1.jpg"; // Create a large person group. console.log(`Creating a person group with ID: ${largePersonGroupId}`); await client.path("/largepersongroups/{largePersonGroupId}", largePersonGroupId).put({ body: { name: largePersonGroupId, recognitionModel: "recognition_04", }, }); // The similar faces will be grouped into a single large person group person. console.log("Adding faces to person group..."); await Promise.all( Object.keys(personDictionary).map(async (name) => { console.log(`Create a persongroup person: ${name}`); const createLargePersonGroupPersonResponse = await client .path("/largepersongroups/{largePersonGroupId}/persons", largePersonGroupId) .post({ body: { name }, }); const { personId } = createLargePersonGroupPersonResponse.body; await Promise.all( personDictionary[name].map(async (similarImage) => { // Check if the image is of sufficent quality for recognition. const detectResponse = await client.path("/detect").post({ contentType: "application/json", queryParameters: { detectionModel: "detection_03", recognitionModel: "recognition_04", returnFaceId: false, returnFaceAttributes: ["qualityForRecognition"], }, body: { url: `${imageBaseUrl}${similarImage}` }, }); const sufficientQuality = detectResponse.body.every( (face) => face.faceAttributes?.qualityForRecognition === "high", ); if (!sufficientQuality) { return; } if (detectResponse.body.length != 1) { return; } // Quality is sufficent, add to group. console.log( `Add face to the person group person: (${name}) from image: (${similarImage})`, ); await client .path( "/largepersongroups/{largePersonGroupId}/persons/{personId}/persistedfaces", largePersonGroupId, personId, ) .post({ queryParameters: { detectionModel: "detection_03" }, body: { url: `${imageBaseUrl}${similarImage}` }, }); }), ); }), ); console.log("Done adding faces to person group."); // Start to train the large person group. console.log(); console.log(`Training person group: ${largePersonGroupId}`); const trainResponse = await client .path("/largepersongroups/{largePersonGroupId}/train", largePersonGroupId) .post(); const poller = await getLongRunningPoller(client, trainResponse); await poller.pollUntilDone(); console.log(`Training status: ${poller.getOperationState().status}`); if (poller.getOperationState().status !== "succeeded") { return; } console.log("Pausing for 60 seconds to avoid triggering rate limit on free account..."); await sleep(60000); // Detect faces from source image url and only take those with sufficient quality for recognition. const detectResponse = await client.path("/detect").post({ contentType: "application/json", queryParameters: { detectionModel: "detection_03", recognitionModel: "recognition_04", returnFaceId: true, returnFaceAttributes: ["qualityForRecognition"], }, body: { url: `${imageBaseUrl}${sourceImageFileName}` }, }); const faceIds = detectResponse.body.filter((face) => face.faceAttributes?.qualityForRecognition !== "low").map((face) => face.faceId); // Identify the faces in a large person group. const identifyResponse = await client.path("/identify").post({ body: { faceIds, largePersonGroupId: largePersonGroupId }, }); await Promise.all( identifyResponse.body.map(async (result) => { try { const getLargePersonGroupPersonResponse = await client .path( "/largepersongroups/{largePersonGroupId}/persons/{personId}", largePersonGroupId, result.candidates[0].personId, ) .get(); const person = getLargePersonGroupPersonResponse.body; console.log( `Person: ${person.name} is identified for face in: ${sourceImageFileName} with ID: ${result.faceId}. Confidence: ${result.candidates[0].confidence}`, ); // Verification: const verifyResponse = await client.path("/verify").post({ body: { faceId: result.faceId, largePersonGroupId: largePersonGroupId, personId: person.personId, }, }); console.log( `Verification result between face ${result.faceId} and person ${person.personId}: ${verifyResponse.body.isIdentical} with confidence: ${verifyResponse.body.confidence}`, ); } catch (error) { console.log(`No persons identified for face with ID ${result.faceId}`); } }), ); console.log(); // Delete large person group. console.log(`Deleting person group: ${largePersonGroupId}`); await client.path("/largepersongroups/{largePersonGroupId}", largePersonGroupId).delete(); console.log(); console.log("Done."); }; main().catch(console.error);
クイック スタート ファイルで
node
コマンドを使用して、アプリケーションを実行します。node index.js
出力
========IDENTIFY FACES========
Creating a person group with ID: a230ac8b-09b2-4fa0-ae04-d76356d88d9f
Adding faces to person group...
Create a persongroup person: Family1-Dad
Create a persongroup person: Family1-Mom
Create a persongroup person: Family1-Son
Add face to the person group person: (Family1-Dad) from image: (Family1-Dad1.jpg)
Add face to the person group person: (Family1-Mom) from image: (Family1-Mom1.jpg)
Add face to the person group person: (Family1-Son) from image: (Family1-Son1.jpg)
Add face to the person group person: (Family1-Dad) from image: (Family1-Dad2.jpg)
Add face to the person group person: (Family1-Mom) from image: (Family1-Mom2.jpg)
Add face to the person group person: (Family1-Son) from image: (Family1-Son2.jpg)
Done adding faces to person group.
Training person group: a230ac8b-09b2-4fa0-ae04-d76356d88d9f
Training status: succeeded
Pausing for 60 seconds to avoid triggering rate limit on free account...
No persons identified for face with ID 56380623-8bf0-414a-b9d9-c2373386b7be
Person: Family1-Dad is identified for face in: identification1.jpg with ID: c45052eb-a910-4fd3-b1c3-f91ccccc316a. Confidence: 0.96807
Person: Family1-Son is identified for face in: identification1.jpg with ID: 8dce9b50-513f-4fe2-9e19-352acfd622b3. Confidence: 0.9281
Person: Family1-Mom is identified for face in: identification1.jpg with ID: 75868da3-66f6-4b5f-a172-0b619f4d74c1. Confidence: 0.96902
Verification result between face c45052eb-a910-4fd3-b1c3-f91ccccc316a and person 35a58d14-fd58-4146-9669-82ed664da357: true with confidence: 0.96807
Verification result between face 8dce9b50-513f-4fe2-9e19-352acfd622b3 and person 2d4d196c-5349-431c-bf0c-f1d7aaa180ba: true with confidence: 0.9281
Verification result between face 75868da3-66f6-4b5f-a172-0b619f4d74c1 and person 35d5de9e-5f92-4552-8907-0d0aac889c3e: true with confidence: 0.96902
Deleting person group: a230ac8b-09b2-4fa0-ae04-d76356d88d9f
Done.
リソースをクリーンアップする
Azure AI サービス サブスクリプションをクリーンアップして削除したい場合は、リソースまたはリソース グループを削除することができます。 リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。
次のステップ
このクイックスタートでは、JavaScript 用の Face クライアント ライブラリを使用して基本的な顔識別を行う方法について学習しました。 次に、さまざまな顔検出モデルと、ユース ケースに適したモデルを指定する方法について学習します。
- Face サービスとは
- より広範なサンプル コードが GitHub にあります。
Face REST API を使用して顔認識を開始します。 Face サービスは、画像内の人間の顔を検出および認識するための高度なアルゴリズムへのアクセスを提供します。
Note
このクイックスタートでは、cURL コマンドを使用して REST API を呼び出します。 また、プログラミング言語を使用して REST API を呼び出すこともできます。 顔識別などの複雑なシナリオは、言語 SDK を使用して実装する方が簡単です。 GitHub のサンプルを参照して、
前提条件
- Azure サブスクリプション - 無料アカウントを作成します
- Azure サブスクリプションを入手したら、Azure portal で Face リソースを作成し、キーとエンドポイントを取得します。 デプロイされたら、 [リソースに移動] を選択します。
- 対象のアプリケーションを Face API に接続するには、作成したリソースのキーとエンドポイントが必要です。 このクイックスタートで後に示すコードに、自分のキーとエンドポイントを貼り付けます。
- Free 価格レベル (
F0
) を使用してサービスを試用し、後から運用環境用の有料レベルにアップグレードすることができます。
- PowerShell バージョン 6.0 以降、または同様のコマンド ライン アプリケーション。
- インストールされた cURL。
顔を識別して検証する
Note
取り込みフォームを使用して Face サービスへのアクセスを受け取っていない場合、これらの関数の一部は機能しません。
まず、ソースの顔の検出 API を呼び出します。 これは、より大きなグループから識別しようとする顔です。 次のコマンドをテキスト エディターにコピーし、独自のキーとエンドポイントを挿入してから、シェル ウィンドウにコピーして実行します。
curl.exe -v -X POST "https://{resource endpoint}/face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&recognitionModel=recognition_04&returnRecognitionModel=false&detectionModel=detection_03&faceIdTimeToLive=86400" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{""url"":""https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/identification1.jpg""}"
返された顔 ID 文字列を一時的な場所に保存します。 これは最後にもう一度使用します。
次に、LargePersonGroup を作成し、正規表現パターン
^[a-z0-9-_]+$
に一致する任意の ID を指定する必要があります。 このオブジェクトには、複数の人物の集計された顔データが格納されます。 次のコマンドを実行し、独自のキーを挿入します。 必要に応じて、要求本文のグループの名前とメタデータを変更します。curl.exe -v -X PUT "https://{resource endpoint}/face/v1.0/largepersongroups/{largePersonGroupId}" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{ ""name"": ""large-person-group-name"", ""userData"": ""User-provided data attached to the large person group."", ""recognitionModel"": ""recognition_04"" }"
作成されたグループの指定された ID を一時的な場所に保存します。
次に、グループに属する Person オブジェクトを作成します。 次のコマンドを実行し、独自のキーと、前の手順の LargePersonGroup の ID を挿入します。 このコマンドによって、"Family1-Dad" という名前の Person が作成されます。
curl.exe -v -X POST "https://{resource endpoint}/face/v1.0/largepersongroups/{largePersonGroupId}/persons" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{ ""name"": ""Family1-Dad"", ""userData"": ""User-provided data attached to the person."" }"
このコマンドを実行した後、別の入力データを使用してもう一度実行して、"Family1-Mom"、"Family1-Son"、"Family1-Daughter"、"Family2-Lady"、"Family2-Man" などの Person オブジェクトをさらに作成します。
作成した各 Person の ID を保存します。どの個人名がどの ID を持つのかを追跡することが重要です。
次に、新しい顔を検出し、それらを存在する Person オブジェクトに関連付ける必要があります。 次のコマンドは、画像 Family1-Dad1.jpg から顔を検出し、対応する人物に追加します。 "Family1-Dad" Person オブジェクトを作成したときに返された ID として
personId
を指定する必要があります。 画像名は、作成された Person.の名前に対応します。 また、LargePersonGroup ID とキーを適切なフィールドに入力します。curl.exe -v -X POST "https://{resource endpoint}/face/v1.0/largepersongroups/{largePersonGroupId}/persons/{personId}/persistedfaces?detectionModel=detection_03" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{""url"":""https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/Face/images/Family1-Dad1.jpg""}"
次に、別のソース イメージとターゲットの Person を使用して、上記のコマンドをもう一度実行します。 使用可能な画像は、Family1-Dad1.jpg、Family1-Dad2.jpg、Family1-Mom1.jpg、Family1-Mom2.jpg、Family1-Son1.jpg、Family1-Son2.jpg、Family1-Daughter1.jpg、Family1-Daughter2.jpg、Family2-Lady1.jpg、Family2-Lady2.jpg、Family2-Man1.jpg、Family2-Man2.jpg です。 API 呼び出しで指定した ID を持つ Person が、要求本文のイメージ ファイルの名前と一致していることを確認します。
この手順の最後に、指定された画像から直接検出された 1 つ以上の対応する顔を持つ複数の Person オブジェクトが必要です。
次に、現在の顔データを使用して LargePersonGroup をトレーニングします。 トレーニング操作では、複数のソース画像から集計された場合もある顔の特徴を単一の人物に関連付ける方法をモデルに指示します。 コマンドを実行する前に、LargePersonGroup ID とキーを挿入します。
トレーニングの状態が成功したかどうかを確認します。 そうでない場合は、しばらく待ってから、もう一度クエリを実行します。
これで、最初の手順のソースの顔 ID と LargePersonGroup ID を使用して、Identify API を呼び出す準備ができました。 これらの値を要求本文の適切なフィールドに挿入し、キーを挿入します。
curl.exe -v -X POST "https://{resource endpoint}/face/v1.0/identify" -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key: {subscription key}" --data-ascii "{ ""largePersonGroupId"": ""INSERT_PERSONGROUP_ID"", ""faceIds"": [ ""INSERT_SOURCE_FACE_ID"" ], ""maxNumOfCandidatesReturned"": 1, ""confidenceThreshold"": 0.5 }"
応答では、ソースの顔で識別された人物を示す Person ID が提供されるはずです。 これは、"Family1-Dad" の人物に対応する ID であるはずです。これは、ソースの顔はその人のものであるためです
顔検証を行うには、前の手順で返された人物 ID、LargePersonGroup ID を使用し、ソースの顔 ID も使用します。 これらの値を要求本文のフィールドに挿入し、自分のキーを挿入します。
curl.exe -v -X POST "https://{resource endpoint}/face/v1.0/verify" ` -H "Content-Type: application/json" ` -H "Ocp-Apim-Subscription-Key: {subscription key}" ` --data-ascii "{ ""faceId"": ""INSERT_SOURCE_FACE_ID"", ""personId"": ""INSERT_PERSON_ID"", ""largePersonGroupId"": ""INSERT_PERSONGROUP_ID"" }"
応答では、信頼度値と共に、ブール値の検証結果が返されます。
リソースをクリーンアップする
この演習で作成した LargePersonGroup を削除するには、LargePersonGroup - Delete 呼び出しを実行します。
curl.exe -v -X DELETE "https://{resource endpoint}/face/v1.0/largepersongroups/{largePersonGroupId}" -H "Ocp-Apim-Subscription-Key: {subscription key}"
Azure AI サービス サブスクリプションをクリーンアップして削除したい場合は、リソースまたはリソース グループを削除することができます。 リソース グループを削除すると、それに関連付けられている他のリソースも削除されます。
次のステップ
このクイックスタートでは、Face REST API を使用して基本的な顔認識タスクを行う方法について学習しました。 次に、さまざまな顔検出モデルと、ユース ケースに適したモデルを指定する方法について学習します。