단순 이미지 인식을 넘어: GPT‑4o와 Segment Anything (SAM)으로 정밀 AI 영양사 만들기
Source: Dev.to
우리는 모두 그런 경험을 해봤습니다: 일반적인 칼로리 추적 앱으로 점심 사진을 찍으면, 500그램짜리 라자냐가 “중간 크기의 케이크 조각”이라고 표시되는 경우죠. 🤦♂️ AI 영양 추적의 어려움은 단순히 음식을 식별하는 것에 그치지 않고, 부피, 서빙 크기, 복잡한 요리 속에 숨겨진 재료들을 이해하는 공간 인식에 있습니다.
이번 튜토리얼에서는 한 단계 끌어올립니다. 우리는 정교한 Visual RAG (Retrieval‑Augmented Generation) 파이프라인을 구축합니다. GPT‑4o Vision의 의미론적 파워와 Meta의 **Segment Anything Model (SAM)**의 정밀한 분할 능력을 결합함으로써 개별 재료를 분리하고, 이를 영양 데이터베이스와 교차 검증하여 전문가 수준의 칼로리 및 다량 영양소 감사를 제공할 수 있습니다. AI 비전 시스템을 위한 프로덕션 준비 패턴을 찾고 있다면, 고성능 AI 아키텍처를 탐구하는 WellAlly Tech Blog에서 심층 분석을 확인해 보세요.
🏗️ 아키텍처: 정밀 비전 파이프라인
표준 비전 모델은 종종 이미지를 단일 “픽셀 가방”으로 취급합니다. 우리의 파이프라인은 이를 구조화된 장면으로 다룹니다. 우리는 SAM을 사용하여 정밀한 마스크를 생성하고, 음식 항목의 상대적 면적을 계산한 뒤, 이러한 고‑컨텍스트 크롭을 GPT‑4o에 전달하여 최종 추론을 수행합니다.
graph TD
A[User Uploads Meal Photo] --> B{SAM Engine}
B -->|Segment| C[Isolated Food Masks]
B -->|Calculate| D[Relative Volume/Area]
C --> E[GPT‑4o Vision Analysis]
D --> E
E --> F[Semantic Food Tags]
F --> G[PostgreSQL Nutrition DB]
G --> H[Final Nutrient Report]
H --> I[User Feedback Loop]
🛠️ 기술 스택
- GPT‑4o – 복잡한 음식 종류와 질감을 식별하기 위한 우리의 “추론 엔진”.
- SAM (Segment Anything Model) – 하나의 음식 항목이 끝나고 다른 항목이 시작되는 지점을 정확히 구분합니다.
- FastAPI – 고성능 비동기 API 레이어.
- PostgreSQL – RAG를 위한 실제 영양 데이터 저장소.
👨💻 Step 1: 구조화된 출력 정의
우리 파이프라인의 신뢰성을 보장하기 위해 GPT‑4o가 구조화된 데이터를 반환하도록 해야 합니다. 우리는 Pydantic을 사용하여 “식사 분석”(Meal Analysis)이 어떻게 보이는지 정의할 것입니다.
from pydantic import BaseModel, Field
from typing import List
class FoodItem(BaseModel):
name: str = Field(..., description="Name of the food item")
estimated_weight_grams: float = Field(..., description="Estimated weight based on volume")
confidence: float = Field(..., ge=0, le=1)
ingredients: List[str]
class MealReport(BaseModel):
items: List[FoodItem]
total_calories: int
macros: dict = Field(default_factory=lambda: {"protein": 0, "carbs": 0, "fat": 0})
🧠 단계 2: SAM + GPT‑4o 시너지
마법은 단순히 원본 사진만 보내는 것이 아니라, SAM이 생성한 좌표/마스크와 함께 사진을 보낼 때 일어납니다. 이렇게 하면 GPT‑4o가 특정 영역에 “집중”하도록 도와줍니다.
import openai
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post("/analyze-meal")
async def analyze_meal(file: UploadFile):
# 1. Process image with SAM (Pseudo-code for the segmentation step)
# masks, scores = sam_model.predict(image)
# 2. Extract metadata and prepare for GPT‑4o
image_bytes = await file.read()
response = openai.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": "You are a professional nutritionist. Analyze the image and segmented areas to provide a precise nutrient breakdown."
},
{
"role": "user",
"content": [
{"type": "text", "text": "Analyze this meal. Note that I have segmented the main protein from the side carbs."},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{encode_image(image_bytes)}"}}
]
}
],
response_format={"type": "json_object"}
)
return response.choices[0].message.content
🥗 단계 3: Visual RAG로 정확도 향상
영양 AI에서 가장 어려운 부분은 “환각”이다. GPT‑4o는 소스가 실제로는 고칼로리 칠리 오일인데 토마토 기반이라고 생각할 수 있다. Visual RAG 패턴을 구현함으로써 GPT‑4o가 식별한 라벨을 사용해 우리의 PostgreSQL 데이터베이스에서 검증된 영양 프로필을 조회한다.
멀티모달 환경에서 RAG의 보다 고급 구현을 위해서는 wellally.tech/blog의 기술 가이드를 강력히 추천한다. 여기서는 시각적 특징에 대한 벡터 임베딩을 최적화하는 방법을 다루며, 이 특정 사용 사례에 큰 변화를 가져온다. 🥑
SQL 쿼리 전략
-- Querying verified nutrients based on AI tags
SELECT name, calories_per_100g, protein, carbs, fat
FROM nutrition_db
WHERE food_tag % ANY(ARRAY['grilled_chicken', 'quinoa', 'broccoli'])
ORDER BY similarity DESC;
🚀 결론: 정밀 건강의 미래
**Segment Anything (SAM)**와 GPT‑4o를 결합함으로써 “추측”에서 “계산”으로 전환합니다. 이 파이프라인을 통해 다음을 수행할 수 있습니다:
- 중첩 음식 감지 – 위에 올려진 밥과 카레를 구분합니다.
- 부피 추정 – 마스크 영역을 식사량의 대용량으로 사용합니다.
- 감사 가능성 – 사용자는 이미지의 어느 부분이 식별되었는지, 그리고 그것이 최종 영양 보고서에 어떻게 기여했는지 정확히 확인할 수 있습니다.
이러한 컴퓨터 비전 칼로리 추정 도구를 구축하는 것은 시작에 불과합니다. 멀티모달 모델이 더 빠르고 효율적으로 발전함에 따라 이러한 파이프라인이 직접 엣지 디바이스로 이동하는 모습을 보게 될 것입니다.
다음은?
- 100 % 정확한 부피 계산을 위해 깊이 감지 카메라(LiDAR)를 통합해 보세요.
- 사용자가 AI를 수정하여 로컬 임베딩을 미세 조정할 수 있는 피드백 루프를 추가하세요.
이 튜토리얼이 마음에 들었다면 아래에 댓글을 남겨 어떤 프로젝트를 만들고 있는지 알려 주세요! 그리고 최신 AI 개발 콘텐츠를 보려면 WellAlly Tech를 방문하는 것을 잊지 마세요. 즐거운 코딩 되세요! 💻🔥