[일단 박죠] O2O Object Detection 서버 기획 및 Flask 서버 구축

jeyong·2023년 12월 28일
1

공부 / 생각 정리  

목록 보기
88/120
post-custom-banner

1. 시스템 구성도 그리기

앞에 데모 프로젝트를 통해서 인공지능 모델을 돌리기에는 클라우드 타입의 성능으로는 부족하다는 것을 알게되었다. 해당 내용을 반영해서 시스템 구성도를 그려보았다.

데모 프로젝트를 통해 알게 된 바로는, 클라우드 서비스의 성능만으로는 인공지능 모델을 운영하기에 부족함을 확인했다. 이에 따라, YOLO 모델은 성능이 더 뛰어난 아마존 서버에 배치하고, 상대적으로 가벼운 Spring과 MariaDB는 각각 애플리케이션 서버 및 데이터베이스 서버로 구분하여 클라우드에 배포하는 구성을 선택했다. 이러한 구성은 비용 효율성과 성능을 동시에 고려한 결과이다.

2. MariaDB 서버 배포

MariaDB 서버를 클라우드에 배포했다. 초기에는 로컬 환경에서 서버를 구축하고 테스트를 진행한 후에 배포하는 방식을 고려했다. 하지만 클라우드 서비스의 무료 이용 범위와 로컬 환경 대비 효율성을 고려하여, 바로 클라우드에 배포하고 이를 로컬처럼 사용하기로 결정했다.

3. Flask 서버 구축

from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename
from ultralytics import YOLO
import cv2
import os
import numpy as np
from PIL import Image, ImageFont, ImageDraw
import json

app = Flask(__name__)
with open('config.json') as config_file:
    config = json.load(config_file)

def load_model():
    return YOLO(config['yolo_model_path'])

def compare_ftdetect(img, folder_path):    
    template_paths = []
    for root, _, files in os.walk(folder_path):
        for file in files:
            img_path = os.path.join(root, file)
            template_paths.append(img_path)
    similarity_scores = {}

    for template_path in template_paths:
        sift = cv2.SIFT_create()

        img2 = imread(template_path)
        img2 = cv2.resize(img2, (640, 640))
        kp1, des1 = sift.detectAndCompute(img, None) 
        kp2, des2 = sift.detectAndCompute(img2, None)
        matcher = cv2.BFMatcher() 

        matches = matcher.knnMatch(des1, des2, 2)
        
        good_matches = [] 
        for m in matches: 
            if m[0].distance / m[1].distance <0.7:
                good_matches.append(m[0]) 
        similarity_scores[template_path] = sum(match.distance for match in good_matches)
    most_similar_template = max(similarity_scores, key=similarity_scores.get)
    most_similar_folder = os.path.dirname(most_similar_template)
    predictName = os.path.basename(most_similar_folder)

    return predictName

def imread(filename, flags=cv2.IMREAD_COLOR, dtype=np.uint8): 
    try: 
        n = np.fromfile(filename, dtype) 
        img = cv2.imdecode(n, flags) 
        return img 
    except Exception as e: 
        print(e) 
        return None

@app.route('/test', methods=['GET'])
def test():
    text = "This is Flask Server Test"
    return text

@app.route('/detect', methods=['POST'])
def detect():
    if 'images' not in request.files:
        return 'No images part in the request', 400

    model = load_model()
    name_folder = config['name_folder']
    images = request.files.getlist('images')
    results = []

    for image_file in images:
        filename = secure_filename(image_file.filename)
        img = cv2.imdecode(np.frombuffer(image_file.read(), np.uint8), cv2.IMREAD_UNCHANGED)

        detection_results = model.predict(img)
        detection_json = detection_results[0].tojson()
        detection_dict = json.loads(detection_json)

        for detection in detection_dict:
            x1, y1, x2, y2 = map(int, [detection['box'][key] for key in ['x1', 'y1', 'x2', 'y2']])
            cropped_img = img[y1:y2, x1:x2]
            predictName = compare_ftdetect(cropped_img, name_folder)

            results.append({
                'filename': filename,
                'object_name': predictName,
                'position': {'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2}
            })

    return jsonify(results)


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

Python과 Flask를 이용해 YOLO 기반의 상점 물품 객체 인식 모델 API 서버를 구축했다. 이 서버는 이미지 데이터를 받아 물품의 위치와 종류 정보를 반환한다. 서버 구성은 다음과 같다.

  • load_model(): 학습된 YOLO 모델을 불러온다.
  • compare_ftdetect(): 이미지 내 물체를 인식하고, 해당 물체의 유사도를 평가한다.
  • imread(): 이미지 파일을 읽어온다.
  • detect(): 이미지 파일을 받아 물품의 위치와 종류를 식별하고 결과를 반환한다.

4. Flask 서버 테스트

API 서버를 테스트한 결과, 이미지 파일을 서버에 전송했을 때, 해당 물품의 종류와 좌표값을 성공적으로 반환하는 것을 확인할 수 있었다. 다음 단계는 Spring 서버를 구축하여 MariaDB와 연동하고, 이를 통해 사용자에게 물품 정보를 제공하는 애플리케이션 서버를 완성하는 것이다.

profile
노를 젓다 보면 언젠가는 물이 들어오겠지.
post-custom-banner

0개의 댓글