

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 取得映像方向與週框方塊座標
<a name="images-orientation"></a>

使用 Amazon Rekognition Image 的應用程式通常需要顯示 Amazon Rekognition Image 操作偵測到的映像，並在偵測到的人臉周圍顯示方塊。若要在您的應用程式中正確顯示映像，您需要了解映像的方向。您可能需要更正此方向。對於某些 .jpg 檔案，映像的方向會包含在映像的可交換映像檔案格式 (Exif) 中繼資料內。

若要在臉部周圍顯示方塊，您需要臉部週框方塊的座標。如果方塊的方向不正確，您可能需要調整這些座標。Amazon Rekognition Image 人臉偵測操作會針對每個偵測到的人臉傳回邊界框座標，但不會估計沒有 Exif 中繼資料的 .jpg 檔案的座標。

下列範例顯示如何獲得映像中偵測到之人臉的週框方塊座標。

請使用此範例中的資訊來確保您的映像方向正確，以及確保週框方塊在您應用程式中顯示的位置正確。

由於用來旋轉及顯示映像與週框方塊的程式碼取決於您所使用的語言和環境，因此我們不會說明如何在您的程式碼中顯示映像與週框方塊，也不會說明如何從 Exif 中繼資料取得方向資訊。



## 找出映像的方向
<a name="images-discovering-image-orientation"></a>

若要在您的應用程式中正確顯示映像，您可能需要加以旋轉。下列映像旋轉為 0 度並正確顯示。

![\[代表使用者帳戶或設定檔映像的一般設定檔圖示。\]](http://docs.aws.amazon.com/zh_tw/rekognition/latest/dg/images/00face.png)


不過，下列映像卻逆時針旋轉 90 度。若要正確顯示，您需要找出映像的方向，並在您的程式碼中使用該資訊將映像旋轉為 0 度。

![\[一般設定檔圖示代表使用者帳戶或設定檔影像，逆時針旋轉 90 度。\]](http://docs.aws.amazon.com/zh_tw/rekognition/latest/dg/images/90face.png)


某些 .jpg 格式的映像在 Exif 中繼資料內含有方向資訊。如果可用，映像的 Exif 中繼資料會包含方向。在 Exif 中繼資料內，您可以在 `orientation` 欄位中找到映像的方向。雖然 Amazon Rekognition Image 會識別 Exif 中繼資料內具有映像方向資訊，但並不提供該資訊的存取權。若要存取映像中的 Exif 中繼資料，請使用第三方程式庫或自行撰寫程式碼。如需詳細資訊，請參閱[可交換映像檔案格式版本 2.32](http://cipa.jp/std/documents/download_e.html?DC-008-Translation-2019-E)。

 



當您知道映像的方向後，就可以撰寫程式碼加以旋轉並正確顯示。

## 顯示週框方塊
<a name="images-bounding-boxes"></a>

分析映像中人臉的 Amazon Rekognition Image 操作也會傳回人臉周圍的週框方塊座標。如需詳細資訊，請參閱 [BoundingBox](https://docs.aws.amazon.com/rekognition/latest/APIReference/API_BoundingBox.html)。

若要在您的應用程式中於人臉周圍顯示週框方塊 (類似下圖所示的方塊)，請在您的程式碼中使用週框方塊座標。操作傳回的週框方塊座標會反映映像的方向。如果您必須旋轉映像才能將其正確顯示，可能需要移動週框方塊座標。



![\[設定檔圖示，臉部以紅色方形反白顯示。\]](http://docs.aws.amazon.com/zh_tw/rekognition/latest/dg/images/00facebounding.png)




### 在 Exif 中繼資料內有方向資訊時顯示週框方塊
<a name="images-exif-metadata"></a>

如果 Exif 中繼資料包含映像的方向，Amazon Rekognition Image 操作會執行下列操作：
+ 在操作回應的方向修正欄位中傳回 null。若要旋轉映像，請在您的程式碼中使用 Exif 中繼資料提供的方向。
+ 傳回已旋轉為 0 度的週框方塊座標。若要在正確位置顯示週框方塊，請使用傳回的座標。您不需要移動該座標。

## 範例：取得映像方向與映像的週框方塊座標
<a name="images-correcting-image-orientation-java"></a>

下列範例示範如何使用適用於 AWS SDK 來取得 Exif 映像的方向資料，並透过 `RecognizeCelebrities` 操作偵測到之名人的週框方塊座標。

**注意**  
自 2021 年 8 月起，已停止使用該 `OrientationCorrection` 欄位估算映像方向的支援。API 回應中包含之此欄位的任何傳回值將永遠為零。

------
#### [ 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/枕狀映像程式庫來取得映像寬度和高度。如需詳細資訊，請參閱[枕狀](https://pillow.readthedocs.io/en/stable/)。此範例會保留 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 文件開發套件範例 GitHub 儲存庫。請參閱[此處](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/javav2/example_code/rekognition/src/main/java/com/example/rekognition/RotateImage.java)的完整範例。

```
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_WEST_2;
        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()));
    }
}
```

------