๊ด€๋ฆฌ ๋ฉ”๋‰ด

ruriruriya

[AWS]Rekognition - Flask Restful Api๋กœ ์•ˆ๋ฉด ๋น„๊ต ๊ธฐ๋Šฅ(๋‘ ์–ผ๊ตด ์œ ์‚ฌ๋„) ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ๋ณธ๋ฌธ

๐Ÿ–ฅ๏ธAWS/Rekognition

[AWS]Rekognition - Flask Restful Api๋กœ ์•ˆ๋ฉด ๋น„๊ต ๊ธฐ๋Šฅ(๋‘ ์–ผ๊ตด ์œ ์‚ฌ๋„) ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

๋ฃจ๋ฆฌ์•ผใ…‘ 2024. 1. 22. 09:28
๋ฐ˜์‘ํ˜•

AWS Rekognition์„ ํ™œ์šฉํ•˜๋ฉด ์•ˆ๋ฉด์„ ์‰ฝ๊ฒŒ ์ธ์‹ํ•˜๊ณ  ๋‘ ์–ผ๊ตด์„ ๋น„๊ตํ•˜์—ฌ ์œ ์‚ฌ๋„๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

VS code์—์„œ Flask ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ด์šฉํ•˜์—ฌ api๋ฅผ ์„ค๊ณ„ํ•œ๋‹ค.

 

1. ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ›์€ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ Bytes ํ˜•์‹์œผ๋กœ ๋ณ€๊ฒฝ.

def post(self) :
        # ํฌ์ŠคํŠธ๋งจ์—์„œ Body๋ฅผ from-data๋กœ ๋ฐ›์•„์˜จ๋‹ค.
        sourceFile = request.files.get("sourceFile")
        targetFile = request.files.get("targetFile")

        if sourceFile is None or targetFile is None :
            return {"error" : "ํŒŒ์ผ ๋‘๊ฐœ๋ฅผ ์˜ฌ๋ ค์ฃผ์„ธ์š”."}, 400
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_ID,                                aws_secret_access_key=Config.AWS_SECRET_ACCESS_KEY)     

        #ํฌ์ŠคํŠธ๋งจ์—์„œ ๊ฐ€์ ธ์˜จ ์ด๋ฏธ์ง€ํŒŒ์ผ์„ Bytesํ˜•์‹์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค
        imageSource = BytesIO(sourceFile.read())
        imageTarget = BytesIO(targetFile.read())

 

2. ์–ผ๊ตด ๋น„๊ต compare_faces() ํ•จ์ˆ˜ ์ž‘์„ฑ

#AWS Rekognition ์„œ๋น„์Šค์˜ compare_faces ์–ผ๊ตด์„ ๋น„๊ตํ•˜๋Š” ํ•จ์ˆ˜ ์ž‘์„ฑ
        response = client.compare_faces(SimilarityThreshold=0, SourceImage={'Bytes': imageSource.read()}, TargetImage={'Bytes': imageTarget.read()})
        # ์ด๋ฏธ์ง€๋ฅผ ์—ด์–ด ์–ผ๊ตด ์ขŒํ‘œ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ, ์ด๋ฏธ์ง€ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
        imageTarget.seek(0)
        # ๊ฐ์ฒด๋กœ ์ƒ์„ฑ
        target_image = Image.open(imageTarget)
        # draw๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ด๋ฏธ์ง€์— ๋„ํ˜•๋“ฑ์„ ๊ทธ๋ฆด์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ ๋‹ค
        draw = ImageDraw.Draw(target_image)

 

[๋ฐ”์ดํŠธ ํ˜•์‹์œผ๋กœ ๋ฐ”๊พธ๋Š” ์ด์œ ]

API ์„œ๋ฒ„ ๊ฐœ๋ฐœ ์‹œ request ๋ฐฉ์‹ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ผ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์•„๋ž˜๋Š” AWS ์š”์ฒญ ๋ฐฉ์‹ ๊ฐ€์ด๋“œ

{
    "SourceImage": {
        "Bytes": "/9j/4AAQSk2Q==..."
    },
    "TargetImage": {
        "Bytes": "/9j/4O1Q==..."
    },
    "SimilarityThreshold": 70
}

 

3. ์–ผ๊ตด BoundingBox๋กœ ์–ผ๊ตด ์œ„์น˜์™€ ํฌ๊ธฐ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ

#๋นˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑ
        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

 

4. ๊ฒฐ๊ณผ๊ฐ’ ๊ฐ€์ ธ์˜ค๋Š” ์ฝ”๋“œ ์ž‘์„ฑ

def post(self) :
        # ํฌ์ŠคํŠธ๋งจ์—์„œ Body๋ฅผ from-data๋กœ ๋ฐ›์•„์˜จ๋‹ค.
        sourceFile = request.files.get("sourceFile")
        targetFile = request.files.get("targetFile")

        if sourceFile is None or targetFile is None :
            return {"error" : "ํŒŒ์ผ ๋‘๊ฐœ๋ฅผ ์˜ฌ๋ ค์ฃผ์„ธ์š”."}, 400

# compare_faces๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ FaceMatches๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
        FaceMatches = self.compare_faces(sourceFile, targetFile)
       
        return {"result" : "success", "FaceMatches" : FaceMatches}, 200

 

5. ์‹คํ–‰ ๊ฒฐ๊ณผ

๋ฐ˜์‘ํ˜•