Getting Image Orientation and Bounding Box Coordinates - Amazon Rekognition

英語の翻訳が提供されている場合で、内容が矛盾する場合には、英語版がオリジナルとして取り扱われます。翻訳は機械翻訳により提供されています。

Getting Image Orientation and Bounding Box Coordinates

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

顔の周りにボックスを表示するには、顔の境界ボックスの座標が必要です。ボックスの向きが正しくない場合は、座標の調整が必要になることがあります。Amazon Rekognition Image の顔検出オペレーションでは、検出された顔ごとに境界ボックスが返されます。

以下の Amazon Rekognition Image オペレーションは、イメージの向きと境界ボックスの座標に関する情報を返します。

この例は、コードの以下の情報を取得する方法を示しています。

  • The estimated orientation of an image (if there is no orientation information in Exif metadata)

  • The bounding box coordinates for the faces detected in an image

  • Translated bounding box coordinates for bounding boxes that are affected by estimated image orientation

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

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

Finding an Image's Orientation

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

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

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

.png 形式のイメージには Exif メタデータがありません。Exif メタデータのない .jpg イメージ、およびすべての .png イメージの場合、Amazon Rekognition Image オペレーションは OrientationCorrection フィールドでイメージの推定された向きを返します。推定された向きは、90 度単位で反時計回りに測定されます。たとえば Amazon Rekognition Image は、向きが 0 度のイメージでは ROTATE_0 を返し、反時計回りに 90 度回転されたイメージでは ROTATE_90 を返します。

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

Displaying Bounding Boxes

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

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

Displaying Bounding Boxes When Orientation Information Is Not Present in Exif Metadata

イメージに Exif メタデータがない場合、または Exif メタデータの orientation フィールドが設定されていない場合、Amazon Rekognition Image オペレーションは以下の情報を返します。

  • An estimated orientation for the image

  • The bounding box coordinates oriented to the estimated orientation

イメージを回転して正しく表示する必要がある場合は、境界ボックスの回転も必要になる場合があります。

たとえば、次のイメージは反時計回りの 90 度の向きであり、顔の周囲に境界ボックスが表示されます。境界ボックスは、Amazon Rekognition Image オペレーションから返された、推定された向きの座標を使用して表示されます。

イメージを 0 度の向きに回転するときは、境界ボックスの座標を変換して、境界ボックスを回転しなければならない場合があります。たとえば、次のイメージは反時計回りに 90 度回転されています。境界ボックスの座標はまだ変換されていないため、境界ボックスは正しくない位置に表示されます。

向きが Exif メタデータに存在しないときに境界ボックスを回転および表示するには

  1. Amazon Rekognition Image オペレーションを呼び出して、少なくとも 1 つの顔を含み、Exif メタデータの向きを含まない入力イメージを取得します。例については、「イメージ内の顔の検出」を参照してください。

  2. レスポンスの OrientationCorrection フィールドで返される、予測された向きを書き留めます。

  3. ステップ 2 で書き留めた、予測された向きをコードで使用して、イメージを 0 度の向きに回転します。

  4. 上部および左の境界ボックスの座標を 0 度の向きに変換し、コードでイメージ上のピクセルポイントに変換します。次のリストで、ステップ 2 で書き留めた、予測された向きに一致する式を使用します。

    以下の定義に注意してください。

    • ROTATE_(n) is the estimated image orientation returned by an Amazon Rekognition Image operation.

    • <face> represents information about the face that is returned by an Amazon Rekognition Image operation. For example, the ComparedFace data type that the RecognizeCelebrities operation returns contains bounding box information for faces detected in the source image.

    • image.width and image.height are pixel values for the width and height of the source image.

    • The bounding box coordinates are a value between 0 and 1 relative to the image size. For example, for an image with 0-degree orientation, a BoundingBox.left value of 0.9 puts the left coordinate close to the right side of the image. To display the box, translate the bounding box coordinate values to pixel points on the image and rotate them to 0 degrees, as shown in each of the following formulas. For more information, see BoundingBox.

    ROTATE_0

    left = image.width*BoundingBox.Left

    top = image.height*BoundingBox.Top

    ROTATE_90

    left = image.height * (1 - (<face>.BoundingBox.Top + <face>.BoundingBox.Height))

    top = image.width * <face>.BoundingBox.Left

    ROTATE_180

    left = image.width - (image.width*(<face>.BoundingBox.Left+<face>.BoundingBox.Width))

    top = image.height * (1 - (<face>.BoundingBox.Top + <face>.BoundingBox.Height))

    ROTATE_270

    left = image.height * BoundingBox.top

    top = image.width * (1 - BoundingBox.Left - BoundingBox.Width)

  5. 次の式を使用して、コードで境界ボックスの幅と高さをイメージ上のピクセル範囲として計算します。

    境界ボックスの幅と高さが、BoundingBox.Width および BoundingBox.Height フィールドで返されます。幅と高さの値は、画像サイズに対して 0 と 1 の間です。image.width および image.height は、ソースイメージの幅と高さのピクセル値です。

    box width = image.width * (<face>.BoundingBox.Width)

    box height = image.height * (<face>.BoundingBox.Height)

  6. ステップ 4 と 5 で計算された値を使用して、回転したイメージ上に境界ボックスを表示します。

Displaying Bounding Boxes When Orientation Information is Present in Exif Metadata

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

  • Return null in the orientation correction field in the operation's response. To rotate the image, use the orientation provided in the Exif metadata in your code.

  • Return bounding box coordinates already oriented to 0 degrees. To show the bounding box in the correct position, use the coordinates that were returned. You do not need to translate them.

Example: Getting Image Orientation and Bounding Box Coordinates For an Image

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

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

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

Java
//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); 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 メタデータを保存し、アプリケーションの他の場所で利用できるようにします。exif メタデータを保存しないことを選択すると、RecognizeCelebrities への呼び出しから向きの予測が返されます。

#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, rotation): left = 0 top = 0 if rotation == 'ROTATE_0': left = imageWidth * box['Left'] top = imageHeight * box['Top'] if rotation == 'ROTATE_90': left = imageHeight * (1 - (box['Top'] + box['Height'])) top = imageWidth * box['Left'] if rotation == 'ROTATE_180': left = imageWidth - (imageWidth * (box['Left'] + box['Width'])) top = imageHeight * (1 - (box['Top'] + box['Height'])) if rotation == 'ROTATE_270': left = imageHeight * box['Top'] top = imageWidth * (1- box['Left'] - box['Width'] ) 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}) if 'OrientationCorrection' in response: print('Orientation: ' + response['OrientationCorrection']) else: print('No estimated orientation. Check Exif') print() print('Detected celebrities for ' + photo) for celebrity in response['CelebrityFaces']: print ('Name: ' + celebrity['Name']) print ('Id: ' + celebrity['Id']) if 'OrientationCorrection' in response: show_bounding_box_positions(height, width, celebrity['Face']['BoundingBox'], response['OrientationCorrection']) print() return len(response['CelebrityFaces']) def main(): photo='photo.png' celebrity_count=celebrity_image_information(photo) print("celebrities detected: " + str(celebrity_count)) if __name__ == "__main__": main()