API 개발/AWS S3 & Rekognition API 파일 업로드

AWS rekognition : AWS rekognition 활용한 얼굴 비교 API

신강희 2024. 6. 25. 10:46
728x90

< AWS rekognition 활용한 얼굴 비교 API >

 

# 이번엔 이전 게시글에 이어서 얼굴 비교 API를 구현해 보자

 

# facematch.py 파일을 생성하여 클래스 작성

- 이미지의 유효성을 검사하고, 이미지에 얼굴 감지 결과를 시각적으로 표시하기 위해서 Pillow 라이브러리 사용!

- 우선 CMD 창에서 install 필요!

pip install Pillow
 
from io import BytesIO
from urllib import response
from PIL import Image, ImageDraw
from flask import request
from flask_restful import Resource
import boto3
from config import Config

class FaceMatchResource(Resource):

    # 얼굴 비교 분석 API
        def post(self):
            # 포스트맨에서 Body를 form-data로 받아온다.
            sourceFile = request.files.get("sourceFile")
            targetFile = request.files.get("targetFile")

            if sourceFile is None or targetFile is None:
                return {"error": "파일 두개를 올려주세요."}, 400

            # 이미지 유효성 검사
            if not self.is_valid_image(sourceFile) or not self.is_valid_image(targetFile):
                return {"error": "유효하지 않은 이미지 파일입니다."}, 400

            # compare_faces 메서드를 호출하여 결과를 FaceMatches로 초기화한다.
            FaceMatches = self.compare_faces(sourceFile, targetFile)
       
            return {"result": "success", "FaceMatches": FaceMatches}, 200
   
        def is_valid_image(self, file):
            try:
                image = Image.open(file)
                image.verify()
                file.seek(0)  # verify()를 호출한 후 파일 포인터를 재설정합니다.
                return True
            except (IOError, SyntaxError) as e:
                print(f'유효하지 않은 이미지 파일: {e}')
                return False

        def compare_faces(self, sourceFile, targetFile):
            # boto3의 client를 사용하여 AWS Rekognition 클라이언트를 생성
            client = boto3.client(
                'rekognition',
                region_name='ap-northeast-2',                                
                aws_access_key_id=Config.AWS_ACCESS_KEY,
                aws_secret_access_key=Config.AWS_SECRET_ACCESS_KEY
            )

            # 포스트맨에서 가져온 이미지파일을 Bytes 형식으로 변경한다
            # Bytes 형식으로 바꾸는 이유는 API 서버 개발 시 request 방식 가이드를 따라야 하기 때문
            imageSource = BytesIO(sourceFile.read())
            imageTarget = BytesIO(targetFile.read())

            # AWS Rekognition 서비스의 compare_faces 얼굴을 비교하는 함수 작성
            response = client.compare_faces(
                SimilarityThreshold=0,
                SourceImage={'Bytes': imageSource.getvalue()},
                TargetImage={'Bytes': imageTarget.getvalue()}
            )

            # 이미지를 열어 얼굴 좌표를 불러오기, 이미지 다시 불러오기
            imageTarget.seek(0)
            # 객체로 생성
            target_image = Image.open(imageTarget)
            # draw 객체를 생성해 이미지에 도형 등을 그릴 수 있게 만든다
            draw = ImageDraw.Draw(target_image)

            # 빈 리스트를 생성
            similarity_list = []
            for faceMatch in response['FaceMatches']:
                # 얼굴의 BoundingBox 값을 가져와 얼굴의 위치와 크기 값을 가져옵니다.
                position = faceMatch['Face']['BoundingBox']
                # 얼굴의 일치정보를 문자열로 저장합니다
                similarity = str(faceMatch['Similarity'])
                # 각 얼굴의 일치 확률을 similarity_list에 추가합니다.
                similarity_list.append(similarity)

                # 얼굴 좌표를 픽셀 단위로 변환
                # 이미지의 가로, 세로 값을 셋팅
                imgWidth, imgHeight = target_image.size
                # 가로, 세로 값을 기반으로 좌표를 셋팅
                left = imgWidth * position['Left']
                top = imgHeight * position['Top']
                width = imgWidth * position['Width']
                height = imgHeight * position['Height']
               
                # 얼굴의 상하좌우의 꼭지점을 만든다
                points = (
                    (left, top),
                    (left + width, top),
                    (left + width, top + height),
                    (left, top + height),
                    (left, top)
                )
                # 꼭지점을 기반으로 도형으로 얼굴을 감싼다
                draw.line(points, fill='#ff0000', width=2)
               
                # 일치 확률을 이미지에 표시, 소수점 3자리에서 반올림
                similarity = round(float(similarity), 3)
                # 수정한 확률값을 이미지에 표시
                draw.text((left + width + 5, top), f"similarity: {similarity}%", fill='#ff0000')      

            # 수정한 이미지를 보여준다
            target_image.show()
            imageSource.close()
            imageTarget.close()
            print(response['FaceMatches'])
            return similarity_list
 

 

# app.py 파일에도 연결 경로 작성

 
from flask import Flask
from flask_restful import Api

from resources.facematch import FaceMatchResource
from resources.image import FileUploadResource
from resources.rekognition import ObjectDetectionResource
from resources.facedetection import FaceDetectionResource

app = Flask(__name__)

api = Api(app)

# 경로와 리소스를 연결하는 코드 작성
api.add_resource( FileUploadResource , '/upload' )
api.add_resource( ObjectDetectionResource , '/object_detection' )
api.add_resource( FaceDetectionResource , '/face_detection' )
api.add_resource( FaceMatchResource , '/face_match' )

if __name__ == '__main__':
    app.run()
 

 

# 이제 포스트맨 에서 API 설계 후 테스트해 보자

 

# 실행 후 결과 출력 화면은 VScode에서 확인해 볼수 있다.

- 개인 사진 두장으로 우선 확인

- 99% 일치율 확인

 

# 다음은 개인과 단체사진 비교!

- 일치하는 멤버만 잘 구분하는것을 확인해 볼수 있다.

 

# 다른 인물을 넣을경우 일치하지 않게잘 구분하는것도 확인

 

다음 게시글로 계속~!

 

반응형