외부 IP에서 FastAPI 서버에 이미지 파일 보내기

조하운·2023년 4월 13일
0

들어가며

저번 포스팅에서는 python의 웹 서버 프레임워크인 fastAPI 를 작동해보는 튜토리얼을 진행했었다. 그 때 fastAPI 서버에 접근하기 위해서는 'http://localhost:8000' 로 브라우저에서 접속할 수 있었는데, 이는 로컬 환경에서만 접속할 수 있으므로 이번 포스팅에서는 외부 ip에서 접근하는 방법을 알아보았다.


1. fastAPI POST 함수 작성하기

먼저, 서버에서 파일 형식인 데이터를 받아올 수 있도록 POST 요청을 받을 때 매개변수를 UploadFile 타입으로 지정한다.


from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse


app = FastAPI()

@app.post("/files/")
async def create_file(file : UploadFile):
    content = await file.read()
    
    return JSONResponse({"filename" : file.filename})

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port = 8000)
  1. file이라는 이름의 변수는 UploadFile이라는 데이터타입의 매개변수만 받을 수 있고, 요청이 들어오게 될 때까지 기다렸다가 요청이 오면 content 변수에 저장한다.

  2. 요청을 정상적으로 처리하면 파일 이름에 해당하는 내용을 JSON 형식으로 응답을 return하도록 했다.

  3. uvicorn 앱을 실행할 때, host='0.0.0.0' port = 8000 을 추가해서 모든 IP주소 상에서 접근할 수 있도록 해준다.

우분투 환경의 경우, 포트 8000번에 대한 접근을 허용하기 위해 방화벽 설정에 포트 8000번을 허용으로 추가해줘야 한다. 따라서 필요한 경우 아래 명령어를 터미널에 입력한다.
$ ufw allow 8000


2. Request 구조 작성하기


  1. requests 패키지를 설치

$pip install requests


  1. fastAPI 서버의 ip 주소와 전송할 이미지 파일 경로 작성
import ImageFromCam
import ImageFromVideo
import requests

url =  "http://서버 ip 주소:8000/files/"
filename = "images/2023_04_12_191946.jpg"

  1. request 코드 작성
with open(filename, "rb") as f:
    contents = f.read()

files = {"file" : (filename, contents, "image/jpg")}

response = requests.post(url, files = files)
print(response.json())

post 요청을 보내기 위해서는 requests.post() 메서드를 사용해야 한다. 여기서 file을 전송하기 위해 넘겨주는 매개변수 형식이 UploadFile이라는 데이터 타입이기 때문에
Json 형식인 files = {"file" : (filename, contents, "image/jpg")} 로 초기화하여 보내야 한다.

마지막으로 응답을 확인해야 하니 리턴으로 돌아오는 json응답을 print하도록 하자.

3. Yolov7, CLIP 분류 모델과 합치기

현재 내가 진행하는 프로젝트에서는 결국 이미지 파일을 받아서 이미지 객체로 변환하고 Yolov7 과 CLIP 모델에 검출 코드를 작동해야 한다. 그런데, Yolov7 detect() 함수는 이미지 파일 경로만을 매개변수로 받는다.

그래서 yolov7의 detect() 함수를 수정해서 cv2 이미지 객체도 받을 수 있도록 했다.

결과적으로 이러한 API 코드의 prototype이 완성되었다.

자세한 내용에 대해서는 추후 포스팅에서 설명하도록 하겠다.

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse
import cv2
import numpy as np
import torch
import time
import os

from data import ImageFromVideo
from data import ImageFromCam
from modules.detect import Detector
from modules.classify import Classifier
from modules.crop import crop_image

import torch


app = FastAPI()

@app.post("/files/")
async def create_file(file : UploadFile):
    content = await file.read()
    human_detector = Detector()
    dumping_classifier = Classifier()
    nparr = np.frombuffer(content, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
    with torch.no_grad():
        det = human_detector.detect(img)
    for i, (*xyxy, conf, cls) in enumerate(reversed(det)):
        # xyxy -> (left_bottom_x, left_bottom_y, right_top_x, right_top_y)
        # if cls == 0: # only save an image of person
        #     crropedImage = crop_image(img_path, tuple(map(float, xyxy)))
        #     pred = dumping_classifier.classify(crropedImage)
        #     print(pred)
        #     if pred == "Dumping":
        #         print(img_path)
        print()
    return JSONResponse({"filename" : file.filename})

@app.get("/")
async def root():
    return {"message" : "hello world"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port = 8000)
profile
| 컴퓨터 비전 | 딥 러닝 | 자율주행 |

0개의 댓글