
어떤 프로젝트였나
AI 영양제 관리 플랫폼을 개발하면서 YOLO11 모델을 직접 학습시켜 영양제를 인식하는 기능을 구현했다. 이 과정에 모델을 학습시키는 것에서 생기는 문제를 마주쳤고, 그 과정을 기록한다.
문제 1. 학습은 잘 됐는데 실제 서비스에서 인식을 못 한다?
가장 오래 헤맸던 문제다.
모델 학습은 분명히 잘 됐는데, 실제로 핸드폰으로 찍은 사진을 넣으면 인식을 제대로 못 하는 상황이 반복됐다.
원인은 해상도 차이였다.
학습할 때 사용한 이미지는 1000×1000 이내로 맞춰서 넣었는데, 실제 서비스에서는 핸드폰으로 찍은 원본 이미지를 그대로 모델에 박아버렸던 것이다. 최신 스마트폰 사진은 3000×4000을 훌쩍 넘는다.
모델 입장에서는 학습 때 본 적 없는 크기의 이미지가 들어오니 특징을 제대로 추출하지 못한 거였다.
해결책: 비율 유지 리사이징
# 가로 또는 세로가 1000px 초과 시 비율 유지하며 리사이징
img.thumbnail((1000, 1000))
가로세로 비율을 유지하면서 1000×1000 박스 안에 들어오도록 줄여주면 인식률이 확 올라갔다.
만약 학습데이터가 적을경우 학습한 데이터의 종류도 확실히 파악하고 처리를하자
문제 2. 리사이징 했는데도 가끔 인식을 못 한다?
리사이징을 적용했는데도 여전히 인식이 안 되는 케이스가 있었다. 그런데 이상하게 수동으로 편집한 이미지는 잘 됐다.
원인은 EXIF 회전 정보였다.
스마트폰은 사진을 찍을 때 픽셀 데이터는 항상 센서 기준(가로 방향)으로 저장하고, "이 사진은 90도 돌려서 봐야 해"라는 정보를 EXIF 메타데이터에 따로 저장한다. 갤러리 앱이나 브라우저는 이걸 읽어서 자동으로 돌려서 보여주니까 우리 눈엔 항상 정방향으로 보이는 것이다.
문제는 PIL 같은 라이브러리가 이 EXIF 정보를 기본적으로 무시한다는 것. 그래서 모델한테는 영양제가 옆으로 누운 이미지가 그대로 들어가버린다.
해결책: exif_transpose() 적용
from PIL import Image, ImageOps
img = Image.open("photo.jpg")
img = ImageOps.exif_transpose(img) # EXIF 회전 정보를 실제 픽셀에 반영
exif_transpose()는 Pillow에서 공식으로 제공하는 함수로, EXIF의 회전 정보를 읽어서 픽셀 데이터를 실제로 돌려준다. 이걸 리사이징 전에 먼저 적용해야 한다.
문제 3. 인식은 됐는데 바운딩 박스 위치가 이상하다?
리사이징한 이미지로 분석하면 좌표도 리사이징된 이미지 기준으로 나온다. 그런데 프론트엔드에서는 원본 고해상도 이미지 위에 바운딩 박스를 그려야 했다.
해결책: 좌표 역스케일링
원본 좌표 = 리사이즈 좌표 × (원본 크기 / 리사이즈 크기)
리사이즈 비율만큼 다시 곱해주면 원본 이미지 기준 좌표로 복원할 수 있다.
정리
| 문제 | 원인 | 해결 |
|---|---|---|
| 원본 이미지 인식 불가 | 학습 해상도와 입력 해상도 차이 | 1000px 이내로 비율 유지 리사이징 |
| 리사이징 후에도 인식 실패 | EXIF 회전 정보 미처리 | exif_transpose() 선적용 |
| 바운딩 박스 위치 틀림 | 리사이즈 좌표 그대로 사용 | 역스케일링으로 원본 좌표 복원 |
AI 서비스에서 이미지를 다룰 때는 해상도 정규화와 메타데이터 처리 두 가지를 반드시 챙겨야 한다.
결과
![]() |
![]() |
![]() |
![]() |




