LLM멀티모달 AI강의 5개 중 2번째난이도 중급

이미지 이해 — Vision LLM 활용

발행 읽는 시간 약 1 분

  • LLM
  • Vision
  • 이미지분석
  • GPT-4o
  • OCR
  • 구조화

강의 소개

GPT-4o와 Claude로 이미지를 분석하고, 영수증·문서·차트에서 구조화된 데이터를 추출하는 방법을 배웁니다. base64 인코딩과 로컬 이미지 처리도 익힙니다.

이미지 전송 방식#

Python
import base64
from openai import OpenAI
from pathlib import Path

client = OpenAI()

# 방법 1: URL로 전송
def analyze_image_url(image_url: str, prompt: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": [
                {"type": "text", "text": prompt},
                {"type": "image_url", "image_url": {"url": image_url}},
            ]
        }],
        max_tokens=1000,
    )
    return response.choices[0].message.content

# 방법 2: base64로 로컬 파일 전송
def analyze_local_image(image_path: str, prompt: str) -> str:
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")

    # MIME 타입 감지
    suffix = Path(image_path).suffix.lower()
    mime_type = {"jpg": "jpeg", "jpeg": "jpeg", "png": "png", "gif": "gif", "webp": "webp"}.get(suffix[1:], "jpeg")

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": [
                {"type": "text", "text": prompt},
                {"type": "image_url", "image_url": {
                    "url": f"data:image/{mime_type};base64,{image_data}"
                }},
            ]
        }],
    )
    return response.choices[0].message.content

영수증/문서 구조화#

Python
from pydantic import BaseModel
from typing import Optional

class ReceiptItem(BaseModel):
    name: str
    quantity: int
    unit_price: int
    total: int

class Receipt(BaseModel):
    store_name: str
    date: str
    items: list[ReceiptItem]
    subtotal: int
    tax: Optional[int] = None
    total: int

def extract_receipt(image_path: str) -> Receipt:
    with open(image_path, "rb") as f:
        image_data = base64.b64encode(f.read()).decode("utf-8")

    response = client.beta.chat.completions.parse(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": [
                {"type": "text", "text": "이 영수증에서 정보를 추출해주세요."},
                {"type": "image_url", "image_url": {
                    "url": f"data:image/jpeg;base64,{image_data}"
                }},
            ]
        }],
        response_format=Receipt,
    )
    return response.choices[0].message.parsed

# 사용
receipt = extract_receipt("receipt.jpg")
print(f"가게: {receipt.store_name}")
print(f"합계: {receipt.total:,}원")
for item in receipt.items:
    print(f"  - {item.name}: {item.unit_price:,}원 × {item.quantity}")

차트/그래프 분석#

Python
def analyze_chart(image_path: str) -> dict:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": """이 차트를 분석해주세요:
1. 차트 종류와 제목
2. X축, Y축 의미
3. 주요 데이터 포인트나 트렌드
4. 핵심 인사이트 (2~3가지)

JSON 형식으로 응답해주세요."""
                },
                {"type": "image_url", "image_url": {
                    "url": f"data:image/png;base64,{encode_image(image_path)}"
                }},
            ]
        }],
        response_format={"type": "json_object"},
    )
    return json.loads(response.choices[0].message.content)

여러 이미지 비교#

Python
def compare_images(image_paths: list[str], question: str) -> str:
    content = [{"type": "text", "text": question}]

    for i, path in enumerate(image_paths):
        content.append({
            "type": "text",
            "text": f"이미지 {i+1}:"
        })
        content.append({
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{encode_image(path)}"}
        })

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": content}],
    )
    return response.choices[0].message.content

# 사용: 제품 이미지 A/B 비교
result = compare_images(
    ["product_v1.jpg", "product_v2.jpg"],
    "두 제품 디자인의 차이점을 분석하고, 어느 것이 더 사용자 친화적인지 평가해주세요."
)

Claude로 이미지 분석#

Python
import anthropic
import httpx

client = anthropic.Anthropic()

# URL에서 바이트로 다운로드
def analyze_with_claude(image_url: str, prompt: str) -> str:
    image_data = base64.standard_b64encode(
        httpx.get(image_url).content
    ).decode("utf-8")

    message = client.messages.create(
        model="claude-opus-4-7",
        max_tokens=1024,
        messages=[{
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": image_data,
                    },
                },
                {"type": "text", "text": prompt}
            ],
        }],
    )
    return message.content[0].text

정리#

방식장점단점
URL 전송간단외부 접근 가능해야 함
base64로컬 파일 가능요청 크기 증가
Structured Output타입 안전복잡한 구조

다음 편에서는 이미지 생성 — DALL-E 3와 Stable Diffusion으로 이미지를 생성하는 방법을 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.