본문 바로가기
AWS/S3, Rekognition

[aws] s3를 활용한 이미지 Storage 저장, 이미지 분석 방법

by 코끼리똥11 2024. 5. 28.

 

Amazon S3(Simple Storage Service)는 Amazon Web Services(AWS)에서 제공하는 객체 스토리지 서비스이다. S3는 웹 규모의 컴퓨팅 용량을 제공하며, 인터넷을 통해 데이터를 저장하고 검색할 수 있는 매우 확장 가능하고 안전한 솔루션이다.

 

 

 

 

 

S3 설정이 끝나면 serverless 를 사용해 파이썬 파일을 만든다.

파이썬에서 aws 기능 사용 가능하게하는 boto3 라이브러리 설치한 후 코드를 작성한다.

 

s3 파일 업로드

 

from flask import request
from flask_restful import Resource
from datetime import datetime
import boto3

from config import Config
class FileUploadResource(Resource):
    def post(self):
        #1. 클라이언트로부터 데이터를 받아온다.
        # 파일은 request.files 안에 있고,
        # 텍스트는 request.form 안에 있다.
        if 'photo' not in request.files:
            return{'result' : 'fail',
                   'error' : '파일을 업로드 하세요,'},400
        if 'content' not in request.form:
            return{'result' : 'fail',
                   'error' : '내용을 업로드 하세요,'},400
        
        file=request.files['photo']
        print(file)
        
        if 'image' not in file.content_type:
            return {'result':'fail', 'error':'이미지 파일만 업로드 가능합니다.'}, 400

        content = request.form['content']
        print(content)

        # 파일을 s3에 업로드 하는데,
        # 먼저, 파일명은 유니크 해야 한다.
        # 따라서 유니크한 파일명으로 바꿔서 업로드 한다.

        # 현재시간과 유저아이디등을 조합해서 만든다.
        current_time=datetime.now()
        file_name=current_time.isoformat().replace(':','_') + '.'+file.content_type.split('/')[-1]
        print(file_name)

        # 유저가 업로드한 파일명을, 내가 만든 파일명으로 바꾼다.
        file.filename = file_name
        # S3 에 파일을 업로드한다.
        # aws의 서비스들을 파이썬 코드로 작성할 수 있는 boto3 라이브러리를 이용해서 코드를 작성한다.

        client = boto3.client('s3',
                     aws_access_key_id=Config.AWS_ACCESS_KEY,
                     aws_secret_access_key=Config.AWS_SECREY_ACCESS_KEY)
        try:
            client.upload_fileobj(file,Config.S3_BUCKET,file_name,ExtraArgs={'ACL':'public-read','ContentType':file.content_type})
        except Exception as e:
            return {'result':'fail','error':str(e)}, 500

        return {'result':'success','Url':Config.S3_URL + file_name}

 

 

이 코드는 Flask와 Flask-RESTful을 사용하여 파일을 S3에 업로드하는 RESTful API를 구현합니다. 클라이언트로부터 이미지를 업로드받아 S3 버킷에 저장하고, 저장된 이미지의 URL을 반환한다. 코드의 주요 부분을 해석해보겠다:

  1. 필요한 모듈을 임포트한다. Config 모듈은 AWS 자격 증명 및 버킷 이름을 포함한 설정 정보를 가져온다.
  2. FileUploadResource 클래스는 Resource 클래스를 상속받아 정의되며, post 메서드를 오버라이드한다. 이 메서드는 HTTP POST 요청을 처리한다.
  3. 클라이언트로부터 데이터를 받아온다. 파일은 request.files에서, 텍스트는 request.form에서 가져온다. 만약 photo가 request.files에 없다면, "파일을 업로드 하세요"라는 에러 메시지를 반한니다. content가 request.form에 없다면, "내용을 업로드 하세요"라는 에러 메시지를 반환한다.
  4. 파일의 MIME 타입을 검사한다. 만약 파일의 content_type에 'image'가 포함되어 있지 않다면, "이미지 파일만 업로드 가능합니다."라는 에러 메시지를 반환한다.
  5. 현재 시간과 유저 ID를 조합하여 유니크한 파일명을 생성한다. 파일명을 현재 시간의 ISO 형식 문자열로 바꾸고, 콜론을 언더스코어로 대체한 후, 파일의 확장자를 붙인다.
  6. 유저가 업로드한 파일명을 새로 생성한 유니크한 파일명으로 바꾼다.
  7. Boto3 라이브러리를 사용하여 S3에 파일을 업로드한다. S3 클라이언트를 생성할 때 AWS 접근 키와 비밀 접근 키를 사용한다. client.upload_fileobj 메서드를 사용하여 파일을 S3에 업로드하고, 업로드된 파일은 퍼블릭 읽기 권한을 갖는다.
  8. 파일 업로드 중에 예외가 발생하면, "fail"과 함께 에러 메시지를 반환한다.
  9. 파일이 성공적으로 업로드되면, "success"와 함께 업로드된 파일의 URL을 반환한다.

이 코드는 클라이언트가 이미지를 업로드하면 S3에 저장하고, 저장된 이미지의 URL을 반환하여 사용자가 업로드된 이미지를 접근할 수 있도록 한다.

 

app.py라는 메인 flask.py 라는 파일에 아래 코드를 작성한다. 

 

from flask import Flask
from flask_restful import Api

from resources.image import FileUploadResource
from resources.rekognition import ObjectDetectionResource


app=Flask(__name__)


api=Api(app)

#경로와 리소스를 연결한다.
api.add_resource(FileUploadResource,'/upload')
if __name__ == "__name__":
    app.run()

 

경로를 설정해준후, postman에 파일을 업로드하면

s3 버킷에 이미지 업로드가 가능하다.

 

 

 

s3에 업로드한 파일 분석

파일을 업로드하기위해서는 detect_labels 가 필요하다.

detect_labels는 Amazon Rekognition의 기능 중 하나로, 이미지나 비디오 파일에서 객체, 사람, 텍스트 및 활동을 감지하고 식별하는 데 사용된다. 이 기능을 사용하면 이미지에서 특정 라벨(예: "사람", "자동차", "동물" 등)을 자동으로 탐지할 수 있다.

https://docs.aws.amazon.com/ko_kr/rekognition/latest/dg/labels-detect-labels-image.html

 

이미지에서 레이블 감지 - Amazon Rekognition

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다. 이미지에서 레이블 감지 이 DetectLabels작업을 사용하여 이미지에서 레이블 (

docs.aws.amazon.com

aws에서 제공하는 방법을 이용해서 detect_labels 를 사용하겠다.

 

aws IAM에서 AmazonRekohnition을 권한 추가해준다.

 

다시 코드를작성해준다. 

from flask import request
from flask_restful import Resource
from datetime import datetime
import boto3

from config import Config

class ObjectDetectionResource(Resource):
    def post(self):
        
        if 'photo' not in request.files:
            return{'result' :'fail',
                   'error' :'사진은 필수입니다.'}
        
        file = request.files['photo']
        if 'image' not in file.content_type :
            return{'result':'fail',
                   'error':'이미지 파일을 업로드하세요.'},400
        
        current_time = datetime.now()
        file_name = current_time.isoformat().replace(':','_')+'.jpg'
        file.filename = file_name

        #rekognotion 서비스를 이용하려면, 먼저 S3에 이미지 파일을 업로드 해놔야 한다.
        client=boto3.client('s3',
                     aws_access_key_id =Config.AWS_ACCESS_KEY,
                     aws_secret_access_key = Config.AWS_SECREY_ACCESS_KEY)
        
        try:
            client.upload_fileobj(file,Config.S3_BUCKET,file_name,ExtraArgs={'ACL':'public-read','ContentType':'image/jpeg'})

        except Exception as e:
            return {'result':'fail','error':str(e)}, 500
        
        
        #리코그니션을 이용한다.
        lable_list = self.detect_labels(file_name,Config.S3_BUCKET)

        return {"result":"seccess",
                "labels":lable_list}        
    






    def detect_labels(self, photo, bucket):
        
        client = boto3.client('rekognition','ap-northeast-2',aws_access_key_id =Config.AWS_ACCESS_KEY,
                     aws_secret_access_key = Config.AWS_SECREY_ACCESS_KEY)

        response = client.detect_labels(Image={'S3Object':{'Bucket':bucket,'Name':photo}},
        MaxLabels=10,
        # Uncomment to use image properties and filtration settings
        #Features=["GENERAL_LABELS", "IMAGE_PROPERTIES"],
        #Settings={"GeneralLabels": {"LabelInclusionFilters":["Cat"]},
        # "ImageProperties": {"MaxDominantColors":10}}
        )

        print('Detected labels for ' + photo)
        print()
        print(response['Labels'])
        label_list=[]
        for label in response['Labels']:
            print("Label: " + label['Name'])
            label_list.append(label['Name'])
            
            
        return label_list
  • detect_labels 메서드: Amazon Rekognition을 사용하여 S3에 업로드된 이미지에서 객체를 감지합니다.
  • boto3 클라이언트를 사용하여 Amazon Rekognition 서비스와 상호작용합니다.
  • detect_labels 메서드를 호출하여 이미지에서 라벨을 감지하고, 최대 10개의 라벨을 반환합니다.
  • 감지된 라벨을 리스트에 추가하여 반환합니다

 

aws에서 제공하는 코드는

이처럼 긴데, 우리가 필요한 정보인 이미지에 label값만 추출하기위해 피필요없는 코드를 지웠다.

이 후 app.py 파일에 class 이름이 바꼇음으로 class 이름에 맞는 경로를 추가해준다.

 

 

postman에 

이 사진을

업로드하고 send 하면 

 

이미지를 분석할 수 있다.