AWS Lambda와 API Gateway를 통해 입력 받은 이미지 처리하기
- 목차
0. 목적
s3에 저장되어 있는 이미지가 아닌 외부 이미지를 받아서 SageMaker의 딥러닝 모델 엔드포인트로 다루고자 함(public API)
1. lambda 함수 작성
- `pillow`, `numpy`, `requests-toolbelt` 라이브러리 필요
- 라이브러리 설치 방법:
from PIL import Image
import numpy as np
import boto3
import io
import json
import base64
from requests_toolbelt.multipart import decoder
from urllib.parse import parse_qs
s3_client = boto3.client('s3')
runtime = boto3.client("sagemaker-runtime")
ep = 'ep' # sagemaker endpoint
def lambda_handler(event, context):
# 첨부된 이미지 파일 open
if 'body' in event:
body = base64.b64decode(event['body'])
else:
body = base64.b64decode(event['body-json'])
if 'content-type' in event['params']['header']:
content_type = event['params']['header']['content-type']
else:
content_type = event['params']['header']['Content-Type']
decode = decoder.MultipartDecoder(body, content_type)
for part in decode.parts:
content = part.content
headers = part.headers
disposition = headers[b'Content-Disposition'].decode()
lst = list(map(lambda x:x.strip(), disposition.replace('form-data;','').split(';')))
key = list(filter(lambda x:'name' in x, list(map(lambda x:parse_qs(x), lst))))[0]['name'][0].strip('"')
if key == 'image':
img = content
elif key == 'key1':
key1 = int(content.decode())
elif key == 'key2':
key2 = str(content.decode())
img = Image.open(io.BytesIO(content))
img = img.resize((256, 256))
img = np.array(img).astype('uint8')
# 추론
isfail = True
round_num = 5
while (isfail) and (round_num >= 0):
try:
img_input = (img / 255.).astype('float32').round(round_num)
payload = json.dumps([img_input.tolist()])
response = runtime.invoke_endpoint(
EndpointName=ep1, ContentType="application/json", Body=payload
)
isfail = False
except:
round_num -= 1
result = json.loads(response['Body'].read().decode())
return result
코드 설명
- 17~20: base64로 암호화 되어있는 이미지 파일(body 혹은 body-json)을 복호화
- `decode = decoder.MultipartDecoder(body, content_type)`: content-type과 body를 multipartDecoder를 통해 복호화(이미지 파일)
- 30~32: content와 headers로 나누는 과정
- 34~43: API에서 여러 key를 넘겨줄 경우, 이런 방식을 통해 나눠주어야 함
- `img = Image.open(io.BytesIO(content))`: content를 python에서 다룰 수 있도록 `pillow` 패키지를 이용하여 이미지 열기
- 50~: sagemaker endpoint에 넣기 위한 전처리 과정
- 소수점 아래로 숫자가 너무 많으면 input 용량이 너무 크다는 오류가 발생한다. (AWS 설명=최대 5MB; Getting error while invoking sagemaker endpoint · Issue #245 · aws/amazon-sagemaker-examples)
`[ERROR] ValidationError: An error occurred (ValidationError) when calling the InvokeEndpoint operation: Request ~~~~~ has oversize body.`
이를 해결하기 위해 소수점 아래 n자리까지 반올림하는 과정을 거치며 될 때까지 반복 (또는 serverless가 아닌 async 사용을 권장)
2. API Gateway 설정
2-1. Lambda와 연결
- REST API 구축
- API 생성
- 작업-리소스 생성-리소스 이름 입력
- 작업-메서드 생성(POST)-Lambda 함수를 지정
2-2. 받는 데이터 형식 지정
- 설정에서 이진 미디어 형식에 `multipart/form-data` 추가
- 위에서 만든 메서드의 통합 요청 설정 (리소스-POST 클릭)
2-3. API 키 생성(보안)
vpc로 감싸진 내부용 API가 아닌 외부에서도 쓸 수 있도록 만든 API이기 때문에, 보안을 위해 API 키 발급
- 메서드 요청에서 API 키가 필요함을 `true`로 설정
- API 키에서 API 생성(이름: `x-api-key`), API 키가 유출되지 않도록 주의
- 사용량 계획 생성
- API 사용량 할당(사용량, 유저수 등을 고려)
2-4. API 배포
- 리소스에서 POST 메서드 선택 후 API 배포
- 호출 API 생성
- 앞서 생성한 리소스를 주소 끝에 붙여줘야함(`https://~~~.amazonaws.com/v1/{resource_name}`)
3. API 테스트
- Postman 환경에서 테스트
- 주소 입력
- API 키 설정
- Body에서 form-data로 설정 후 파일 첨부
- 요청 결과 확인
'AWS' 카테고리의 다른 글
[AWS Summit Seoul 2024] LLM의 프롬프트 엔지니어링 (1) | 2024.06.03 |
---|---|
AWS Lambda만을 이용해서 날씨알림봇 만들기 (0) | 2024.04.22 |
AWS Lambda, API Gateway로 대화형 질답봇 만들기 (Feat. 야구) (0) | 2024.04.02 |
AWS Lambda와 selenium을 이용해서 날씨알림봇 만들기 (0) | 2024.03.07 |
AWS Cloud9과 ECR을 이용하여 Lambda Container 배포하기 (0) | 2024.02.23 |