이미지 방향 및 경계 상자 좌표 가져오기 - Amazon Rekognition

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

이미지 방향 및 경계 상자 좌표 가져오기

Amazon Rekognition Image를 사용하는 애플리케이션은 일반적으로 Amazon Rekognition Image 작업으로 감지된 이미지 및 감지된 얼굴 주위의 상자를 표시해야 합니다. 애플리케이션에서 이미지를 올바르게 표시하려면 이미지의 방향을 알아야 합니다. 이 방향을 수정해야 할 수도 있습니다. 일부 .jpg 파일의 경우 이미지의 교환 이미지 파일 형식(Exif) 메타데이터에 이미지의 방향이 포함됩니다.

얼굴 주위에 상자를 표시하려면 얼굴의 경계 상자에 대한 좌표가 필요합니다. 상자 방향이 올바르지 않으면 해당 좌표를 조정해야 할 수 있습니다. Amazon Rekognition Image의 얼굴 감지 작업은 감지된 각 얼굴에 대한 경계 상자 좌표를 반환하지만 Exif 메타데이터가 없는.jpg 파일의 좌표는 추정하지 않습니다.

다음 예제는 이미지에서 감지된 얼굴의 경계 상자 좌표를 가져오는 방법을 보여줍니다.

이 예제의 정보를 사용하여 이미지의 방향이 올바른지, 경계 상자가 애플리케이션의 올바른 위치에 표시되는지 확인하십시오.

이미지와 경계 상자를 회전하고 표시하는 데 사용되는 코드는 사용하는 언어와 환경에 따라 다르므로 코드에 이미지와 경계 상자를 표시하는 방법이나 Exif 메타데이터에서 방향 정보를 가져오는 방법을 설명하지 않습니다.

이미지의 방향 찾기

애플리케이션에서 이미지를 올바르게 표시하려면 이미지를 회전해야 할 수 있습니다. 다음 이미지의 방향은 0도이며 올바르게 표시되어 있습니다.

사용자 계정 또는 프로필 이미지를 나타내는 일반 프로필 아이콘.

그러나 다음 이미지는 시계 반대 방향으로 90도 회전된 상태입니다. 올바르게 표시하려면 이미지의 방향을 찾고 코드에서 해당 정보를 사용하여 이미지를 0도로 회전해야 합니다.

사용자 계정 또는 프로필 이미지를 나타내는 일반 프로필 아이콘으로, 시계 반대 방향으로 90도 회전했습니다.

.jpg 형식의 일부 이미지는 Exif 메타데이터에 방향 정보를 포함합니다. 가능한 경우 이미지의 Exif 메타데이터에는 방향이 포함됩니다. Exif 메타데이터의 orientation 필드에서 이미지의 방향을 찾을 수 있습니다. Amazon Rekognition Image는 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 문서 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())); } }