イメージの向きおよび境界ボックス座標の取得 - Amazon Rekognition

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

イメージの向きおよび境界ボックス座標の取得

Amazon Rekognition Image を一般的に使用するアプリケーションは、Amazon Rekognition Image オペレーションによって検出されたイメージと、検出された顔の周囲のボックスを表示する必要があります。アプリケーションで正しくイメージを表示するには、イメージの向きを知り、必要に応じて修正する必要があります。この向きを修正することが必要な場合があります。一部の .jpg ファイルでは、イメージの向きは、イメージの Exchangeable イメージファイル形式 (Exif) メタデータに含まれています。

顔の周りにボックスを表示するには、顔の境界ボックスの座標が必要です。ボックスの向きが正しくない場合は、座標の調整が必要になることがあります。Amazon Rekognition イメージの顔検出オペレーションでは、検出された顔ごとに境界ボックスが返されます。しかし Exif メタデータがない.jpg ファイルの座標は推定されません。

下記の例は、イメージで検出された顔の境界ボックスの座標を示す際の例です。

この例の情報を使用して、イメージの向きが正しく、境界ボックスがアプリケーションで正しい位置に表示されるようにします。

イメージと境界ボックスを回転および表示するためのコードは、使用する言語と環境に依存するため、イメージと境界ボックスをコードで表示する方法や、Exif メタデータから向きの情報を取得する方法については説明しません。

イメージの向きの検索

アプリケーションで正しくイメージを表示するには、回転が必要になる場合があります。次のイメージの向きは 0 度で、正しく表示されています。

ユーザーアカウントまたはプロファイルイメージを表す汎用プロファイルアイコン。

ただし、次のイメージは反時計回りに 90 度回転しています。これを正しく表示するには、イメージの向きを見つけ、その情報をコードで使用してイメージを 0 度に回転する必要があります。

ユーザーアカウントまたはプロファイルイメージを表す汎用プロファイルアイコン。反時計回りに 90 度回転しました。

.jpg 形式の一部のイメージには、Exif メタデータに向きの情報が含まれています。使用可能な場合、イメージの Exif メタデータには向きが含まれています。Exif メタデータで、イメージの向きは orientation フィールドで見つかります。Amazon Rekognition は Exif メタデータ内のイメージの向きの情報の存在を認識しますが、その情報へのアクセスは提供しません。イメージで Exif メタデータにアクセスするには、サードパーティーのライブラリを使用するか、独自のコードを記述します。詳細については、「Exif バージョン 2.32」を参照してください。

イメージの向きがわかっている場合は、コードを記述して回転し、正しく表示できます。

境界ボックスの表示

イメージの顔を分析する Amazon Rekognition Image オペレーションも、顔を囲む境界ボックスの座標を返します。詳細については、「」を参照してくださいBoundingBox

アプリケーションの次のイメージに示すボックスに類似した境界ボックスを顔の周囲に表示するには、コードで境界ボックスの座標を使用します。オペレーションで返される境界ボックスの座標は、イメージの向きを反映しています。イメージを回転して正しく表示する必要がある場合は、境界ボックスの座標の変換が必要になる場合があります。

顔が赤い四角で強調表示されたプロファイルアイコン。

向きの情報が Exif メタデータに存在するときに境界ボックスを表示する

イメージの向きが Exif メタデータに含まれている場合、Amazon Rekognition Image オペレーションで以下が実行されます。

  • オペレーションのレスポンスの向き修正フィールドで null が返されます。イメージを回転するには、コードの Exif メタデータに含まれている向きを使用します。

  • すでに向きが設定されている境界ボックスの座標を 0 度に戻します。正しい位置に境界ボックスを表示するには、返された座標を使用します。それらを変換する必要はありません。

例: イメージの向きおよびイメージの境界ボックス座標の取得

以下の例では、AWS SDK を使用して Exif イメージの推定された向きを取得し、RecognizeCelebrities オペレーションで検出された有名人の境界ボックス座標を変換する方法を示します。

注記

OrientationCorrection フィールドを使用した画像方向の見積もりは、2021 年 8 月をもってサポートを終了しています。API レスポンスに含まれるこのフィールドの戻り値は、常に NULL になります。

Java

この例では、ローカルファイルシステムからイメージをロードし、RecognizeCelebrities オペレーションを呼び出して、イメージの高さと幅を判断してから、回転したイメージの顔の境界ボックスの座標を計算します。この例では、Exif メタデータに保存される向きの情報を処理する方法は示しません。

関数 main で、photo の値は、ローカルに保存されているイメージ (.png または .jpg 形式) の名前とパスに置き換えます。

//Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. //PDX-License-Identifier: MIT-0 (For details, see https://github.com/awsdocs/amazon-rekognition-developer-guide/blob/master/LICENSE-SAMPLECODE.) package com.amazonaws.samples; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.nio.ByteBuffer; import java.util.List; import javax.imageio.ImageIO; import com.amazonaws.services.rekognition.AmazonRekognition; import com.amazonaws.services.rekognition.AmazonRekognitionClientBuilder; import com.amazonaws.services.rekognition.model.Image; import com.amazonaws.services.rekognition.model.RecognizeCelebritiesRequest; import com.amazonaws.services.rekognition.model.RecognizeCelebritiesResult; import com.amazonaws.util.IOUtils; import com.amazonaws.services.rekognition.model.AmazonRekognitionException; import com.amazonaws.services.rekognition.model.BoundingBox; import com.amazonaws.services.rekognition.model.Celebrity; import com.amazonaws.services.rekognition.model.ComparedFace; public class RotateImage { public static void main(String[] args) throws Exception { String photo = "photo.png"; //Get Rekognition client AmazonRekognition amazonRekognition = AmazonRekognitionClientBuilder.defaultClient(); // Load image ByteBuffer imageBytes=null; BufferedImage image = null; try (InputStream inputStream = new FileInputStream(new File(photo))) { imageBytes = ByteBuffer.wrap(IOUtils.toByteArray(inputStream)); } catch(Exception e) { System.out.println("Failed to load file " + photo); System.exit(1); } //Get image width and height InputStream imageBytesStream; imageBytesStream = new ByteArrayInputStream(imageBytes.array()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); image=ImageIO.read(imageBytesStream); ImageIO.write(image, "jpg", baos); int height = image.getHeight(); int width = image.getWidth(); System.out.println("Image Information:"); System.out.println(photo); System.out.println("Image Height: " + Integer.toString(height)); System.out.println("Image Width: " + Integer.toString(width)); //Call GetCelebrities try{ RecognizeCelebritiesRequest request = new RecognizeCelebritiesRequest() .withImage(new Image() .withBytes((imageBytes))); RecognizeCelebritiesResult result = amazonRekognition.recognizeCelebrities(request); // The returned value of OrientationCorrection will always be null System.out.println("Orientation: " + result.getOrientationCorrection() + "\n"); List <Celebrity> celebs = result.getCelebrityFaces(); for (Celebrity celebrity: celebs) { System.out.println("Celebrity recognized: " + celebrity.getName()); System.out.println("Celebrity ID: " + celebrity.getId()); ComparedFace face = celebrity.getFace() ; ShowBoundingBoxPositions(height, width, face.getBoundingBox(), result.getOrientationCorrection()); System.out.println(); } } catch (AmazonRekognitionException e) { e.printStackTrace(); } } public static void ShowBoundingBoxPositions(int imageHeight, int imageWidth, BoundingBox box, String rotation) { float left = 0; float top = 0; if(rotation==null){ System.out.println("No estimated estimated orientation. Check Exif data."); return; } //Calculate face position based on image orientation. switch (rotation) { case "ROTATE_0": left = imageWidth * box.getLeft(); top = imageHeight * box.getTop(); break; case "ROTATE_90": left = imageHeight * (1 - (box.getTop() + box.getHeight())); top = imageWidth * box.getLeft(); break; case "ROTATE_180": left = imageWidth - (imageWidth * (box.getLeft() + box.getWidth())); top = imageHeight * (1 - (box.getTop() + box.getHeight())); break; case "ROTATE_270": left = imageHeight * box.getTop(); top = imageWidth * (1 - box.getLeft() - box.getWidth()); break; default: System.out.println("No estimated orientation information. Check Exif data."); return; } //Display face location information. System.out.println("Left: " + String.valueOf((int) left)); System.out.println("Top: " + String.valueOf((int) top)); System.out.println("Face Width: " + String.valueOf((int)(imageWidth * box.getWidth()))); System.out.println("Face Height: " + String.valueOf((int)(imageHeight * box.getHeight()))); } }
Python

この例では、PIL/Pillow イメージライブラリを使用してイメージの幅と高さを取得します。詳細については、「Pillow」を参照してください。この例では、exif メタデータを保存し、アプリケーションの他の場所で利用できるようにします。

関数 main で、photo の値は、ローカルに保存されているイメージ (.png または .jpg 形式) の名前とパスに置き換えます。

#Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. #PDX-License-Identifier: MIT-0 (For details, see https://github.com/awsdocs/amazon-rekognition-developer-guide/blob/master/LICENSE-SAMPLECODE.) import boto3 import io from PIL import Image # Calculate positions from from estimated rotation def show_bounding_box_positions(imageHeight, imageWidth, box): left = 0 top = 0 print('Left: ' + '{0:.0f}'.format(left)) print('Top: ' + '{0:.0f}'.format(top)) print('Face Width: ' + "{0:.0f}".format(imageWidth * box['Width'])) print('Face Height: ' + "{0:.0f}".format(imageHeight * box['Height'])) def celebrity_image_information(photo): client = boto3.client('rekognition') # Get image width and height image = Image.open(open(photo, 'rb')) width, height = image.size print('Image information: ') print(photo) print('Image Height: ' + str(height)) print('Image Width: ' + str(width)) # call detect faces and show face age and placement # if found, preserve exif info stream = io.BytesIO() if 'exif' in image.info: exif = image.info['exif'] image.save(stream, format=image.format, exif=exif) else: image.save(stream, format=image.format) image_binary = stream.getvalue() response = client.recognize_celebrities(Image={'Bytes': image_binary}) print() print('Detected celebrities for ' + photo) for celebrity in response['CelebrityFaces']: print('Name: ' + celebrity['Name']) print('Id: ' + celebrity['Id']) # Value of "orientation correction" will always be null if 'OrientationCorrection' in response: show_bounding_box_positions(height, width, celebrity['Face']['BoundingBox']) print() return len(response['CelebrityFaces']) def main(): photo = 'photo' celebrity_count = celebrity_image_information(photo) print("celebrities detected: " + str(celebrity_count)) if __name__ == "__main__": main()
Java V2

このコードは AWS Documentation SDK サンプル GitHub リポジトリから取得されます。詳しい事例はこちらです。

import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.rekognition.RekognitionClient; import software.amazon.awssdk.services.rekognition.model.RecognizeCelebritiesRequest; import software.amazon.awssdk.services.rekognition.model.Image; import software.amazon.awssdk.services.rekognition.model.RecognizeCelebritiesResponse; import software.amazon.awssdk.services.rekognition.model.Celebrity; import software.amazon.awssdk.services.rekognition.model.ComparedFace; import software.amazon.awssdk.services.rekognition.model.RekognitionException; import software.amazon.awssdk.services.rekognition.model.BoundingBox; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.util.List; /** * Before running this Java V2 code example, set up your development * environment, including your credentials. * * For more information, see the following documentation topic: * * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class RotateImage { public static void main(String[] args) { final String usage = """ Usage: <sourceImage> Where: sourceImage - The path to the image (for example, C:\\AWS\\pic1.png).\s """; if (args.length != 1) { System.out.println(usage); System.exit(1); } String sourceImage = args[0]; Region region = Region.US_EAST_1; RekognitionClient rekClient = RekognitionClient.builder() .region(region) .build(); System.out.println("Locating celebrities in " + sourceImage); recognizeAllCelebrities(rekClient, sourceImage); rekClient.close(); } public static void recognizeAllCelebrities(RekognitionClient rekClient, String sourceImage) { try { BufferedImage image; InputStream sourceStream = new FileInputStream(sourceImage); SdkBytes sourceBytes = SdkBytes.fromInputStream(sourceStream); image = ImageIO.read(sourceBytes.asInputStream()); int height = image.getHeight(); int width = image.getWidth(); Image souImage = Image.builder() .bytes(sourceBytes) .build(); RecognizeCelebritiesRequest request = RecognizeCelebritiesRequest.builder() .image(souImage) .build(); RecognizeCelebritiesResponse result = rekClient.recognizeCelebrities(request); List<Celebrity> celebs = result.celebrityFaces(); System.out.println(celebs.size() + " celebrity(s) were recognized.\n"); for (Celebrity celebrity : celebs) { System.out.println("Celebrity recognized: " + celebrity.name()); System.out.println("Celebrity ID: " + celebrity.id()); ComparedFace face = celebrity.face(); ShowBoundingBoxPositions(height, width, face.boundingBox(), result.orientationCorrectionAsString()); } } catch (RekognitionException | FileNotFoundException e) { System.out.println(e.getMessage()); System.exit(1); } catch (IOException e) { e.printStackTrace(); } } public static void ShowBoundingBoxPositions(int imageHeight, int imageWidth, BoundingBox box, String rotation) { float left; float top; if (rotation == null) { System.out.println("No estimated estimated orientation."); return; } // Calculate face position based on the image orientation. switch (rotation) { case "ROTATE_0" -> { left = imageWidth * box.left(); top = imageHeight * box.top(); } case "ROTATE_90" -> { left = imageHeight * (1 - (box.top() + box.height())); top = imageWidth * box.left(); } case "ROTATE_180" -> { left = imageWidth - (imageWidth * (box.left() + box.width())); top = imageHeight * (1 - (box.top() + box.height())); } case "ROTATE_270" -> { left = imageHeight * box.top(); top = imageWidth * (1 - box.left() - box.width()); } default -> { System.out.println("No estimated orientation information. Check Exif data."); return; } } System.out.println("Left: " + (int) left); System.out.println("Top: " + (int) top); System.out.println("Face Width: " + (int) (imageWidth * box.width())); System.out.println("Face Height: " + (int) (imageHeight * box.height())); } }