본문 바로가기
AWS

AWS API를 이용한 lambda S3 mysql flask boto3 postman 업로드한 사진 오브젝트 디텍팅

by leopard4 2023. 1. 13.

사전배경지식은 생략하였음.

 

photo밑이 가려서 ..

 

이런 API를 S3에 업로드하고 DB에 저장할것임

 

유저가 이미지와 텍스트를 request 했을때 S3에 url을 저장하고 DB에 저장하는 VSC

from flask import request # 클라이언트가 보낸 데이터를 받기 위한 라이브러리
from flask_restful import Resource # API를 만들기 위한 라이브러리
from mysql.connector import Error # DB에 연결할 때, 에러가 발생할 수 있으므로, 에러처리를 위한 라이브러리
from flask_jwt_extended import jwt_required, get_jwt_identity # JWT를 사용하기 위한 라이브러리
from mysql_connection import get_connection
from config import Config
from datetime import datetime # 현재 시간을 가져오기 위한 라이브러리
import boto3


class PostingResource(Resource):
   
    def post(self):
        # 1.클라이언트가 보낸 데이터를 받는다.
        # form-data
        # photo : file
        # content : text

        # 사진과 내용은 필수항목이다!! (세이프코드)
        if 'photo' not in request.files or 'content' not in request.form :
            return {'error': '데이터를 정확히 보내세요'}, 400
       
        file = request.files['photo']
        content = request.form['content']
       
        # 사진인지 아닌지 확인
        if file.content_type.split('/')[0] != 'image' :
            return {'error' : '이미지 파일만 업로드 가능합니다.'}, 400

       
        # 파일명을 어떻게 할 것인가?
        # 현재 시간을 가져온다. 합친다.
        current_time = datetime.now()
       
     
        # 파일이 이미지인지 pdf인지 확인하여 확장자를 붙여준다.
        new_file_name = current_time.isoformat().replace(':', '').replace('_', '')+ '.' + file.content_type.split('/')[1]

        print(new_file_name)
        print("콘텐츠 타입은:", file.content_type)

        file.filename = new_file_name

      
        # tip.순서는 러프(대충)하게 작성하고, 세세한 부분은 나중에 작성한다.
        # 2. 사진을 먼저 S3에 업로드한다.
        # 2-1. S3에 접속한다.
        client = boto3.client('s3',
            aws_access_key_id=Config.ACCESS_KEY,
            aws_secret_access_key=Config.SECRET_ACCESS
        )

        # 2-2. S3에 파일을 업로드한다.
       

        try :
            client.upload_fileobj( file , # 파일을 업로드한다.
                        Config.BUCKET_NAME ,
                        new_file_name,
                        ExtraArgs={'ACL':'public-read',
                        'ContentType' : file.content_type})  # ExtraArgs={'ACL':'public-read'} : 파일을 업로드할 때, 권한을 설정한다.
                   
        except Error as e :
            return {'error' : str(e)}, 500
       

        # 3. 저장된 사진의 imgUrl을 만든다.
        imgUrl = Config.S3_LOCATION + new_file_name
       
        # 4. DB에 저장한다
        try :
            connection = get_connection()
            query = '''insert into posting
                        (content, imageUrl)
                        values
                        (%s, %s);'''
            record = (content, imgUrl)
            cursor = connection.cursor()
            cursor.execute(query,record)
            connection.commit()
            cursor.close()
            connection.close()
           
        except Error as e :
            print(e)
            cursor.close()
            connection.close()
            return {'error' : str(e)}, 500

        return {'result' : 'success'}, 200

       

 

테이블설계

 

 

 

 

오브젝트 디텍팅 ( aws의 ai 객체인식 api를 이용할것)

 

postman

 

vsc

from flask import request
from flask_restful import Resource
from mysql.connector import Error
from config import Config
import boto3
from datetime import datetime

class ObjectDetectionResource(Resource) :

    # S3에 저장된 이미지를 분석하여 객체를 탐지하는 API
    def get(self) :
       
        # 1. 클라이언트로부터 파일명을 받아온다.
        filename = request.args.get('filename')

        # 2. 위의 파일은 이미 S3에 저장되어 있다고 가정한다.
        # 따라서 aws의 rekognition 서비스를 이용하여
        # object detection을 수행한다.

        # rekognition 서비스를 사용하기 위해서는
        # iam 의 유저 권한을 확인하고, 설정해준다.
        client = boto3.client( 'rekognition',
                            'ap-northeast-2',
                            aws_access_key_id=Config.ACCESS_KEY,
                            aws_secret_access_key=Config.SECRET_ACCESS )

        response = client.detect_labels( Image = { 'S3Object' : { 'Bucket' : Config.BUCKET_NAME, 'Name' : filename } } ,
                            MaxLabels = 10 )
       
        print("response:  ", response)

        for label in response['Labels']:
            print ("Label: " + label['Name'])
            print ("Confidence: " + str(label['Confidence']))
            print ("Instances:")
            for instance in label['Instances']:
                print ("  Bounding box")
                print ("    Top: " + str(instance['BoundingBox']['Top']))
                print ("    Left: " + str(instance['BoundingBox']['Left']))
                print ("    Width: " +  str(instance['BoundingBox']['Width']))
                print ("    Height: " +  str(instance['BoundingBox']['Height']))
                print ("  Confidence: " + str(instance['Confidence']))
                print()

            print ("Parents:")
            for parent in label['Parents']:
                print ("   " + parent['Name'])
            print ("----------")
            print ()

        return {'result' : 'success',
                'Labels' : response['Labels'][0]["Name"] }, 200

class PhotoRekognitionResource(Resource) :
   
    def post(self):
       
        # 1. 클라이언트가 보낸 데이터를 받는다.
        # request.files : 클라이언트가 보낸 파일 데이터
        if 'photo' not in request.files :
            return {'message' : 'No file'}, 400

        file = request.files['photo']
     
        # 클라이언트가 보낸 파일의 파일명을
        # 변경시켜서 S3에 올려야, 유니크하게
        # 파일을 관리할 수 있다.
       
        # 파일명을 유니크하게 만드는 방법
        current_time = datetime.now()
        new_file_name = current_time.isoformat().replace(':', '').replace('_', '')+".jpg"

        print(new_file_name)

        # 파일명을, 유니크한 이름으로 변경한다.
        # 클라이언트가 보낸 파일명을 변경한다.
       
        file.filename = new_file_name

        # s3에 파일을 업로드한다.
        # s3에 파일 업로드 하는 라이브러리가 필요하다.
        # 따라서, pip install boto3 라이브러리를 이용해서
        # 업로드한다.

        # AWS S3에 접속한다.
        client = boto3.client( 's3' ,
            aws_access_key_id= Config.ACCESS_KEY ,
            aws_secret_access_key= Config.SECRET_ACCESS )
       
        try :
            client.upload_fileobj( file , # 파일을 업로드한다.
                        Config.BUCKET_NAME ,
                        new_file_name,
                        ExtraArgs={'ACL':'public-read',
                        'ContentType' : file.content_type})  # ExtraArgs={'ACL':'public-read'} : 파일을 업로드할 때, 권한을 설정한다.
                   
        except Error as e :
            return {'error' : str(e)}, 500


        client = boto3.client( 'rekognition',
                            'ap-northeast-2',
                            aws_access_key_id=Config.ACCESS_KEY,
                            aws_secret_access_key=Config.SECRET_ACCESS )

        response = client.detect_labels( Image = { 'S3Object' : { 'Bucket' : Config.BUCKET_NAME, 'Name' : new_file_name } } ,
                            MaxLabels = 10 )
       
        print( response["Labels"])


        #### 위의 response 에서, 필요한 데이터만 가져와서
        #### 클라이언트에게 보내준다!

        # response 구조를파악하고 labels : [ 'Person', 'Human', 'cat' ] 와 같은 형태로 만듬
        # json online editor 를 이용

        name_list = []
        for data in response["Labels"]:
            name_list.append(data["Name"])
       
        return {'result' : 'success', 'Labels' : name_list}, 200


S3 버킷