OpenCV Fashion Similarity Search

과제로 만든 패션 유사도 검색, 종강 뒤에도 고치는 중

디지털영상처리 수업의 개인 과제는 기술을 복잡하게 쌓는 것보다, 영상처리를 이용해 실제로 쓸 만한 결과물을 만드는 것이 중요했다. 주제를 고민하던 중 당시 여자친구와 패션 이야기를 나누다가 “사진 속 옷과 비슷한 상품을 바로 찾을 수 있으면 어떨까”라는 생각이 나왔다.

이미지로 상품을 찾는 쇼핑몰이라면 OpenCV를 억지로 끼워 넣지 않아도 됐다. 사진에서 옷이 있는 부분을 찾아내고, 그 영역을 기준으로 비슷한 상품을 비교하는 과정 자체가 디지털영상처리와 맞닿아 있었다. 과제에서 요구한 실용성도 만족해 보였다.

이미지를 업로드해 유사한 패션 상품을 검색하는 서비스 시연
현재 패션 유사도 검색 화면. 이미지를 입력하면 의류 영역을 전처리하고, 벡터가 가까운 상품을 검색한다.

사진만 비슷하게 찾으면 끝나는 일이 아니었다

처음 떠올린 모습은 간단했다. 사용자가 옷 사진을 올리면 쿠팡이나 무신사에서 비슷한 상품을 보여주는 서비스였다. 그런데 검색 결과에 상품 페이지를 연결하려면 비교 대상 이미지와 쇼핑몰 URL을 함께 관리해야 했다.

쿠팡이나 무신사의 상품을 기준 데이터로 삼으면 페이지 변화를 계속 확인하며 이미지를 수집해야 한다. 새 상품이 생기거나 기존 상품이 내려갈 때마다 다시 가져와 특징 벡터로 변환하는 작업도 필요했다. 과제용 개인 프로젝트에서 특정 쇼핑몰의 페이지 구조를 계속 따라가는 방식은 유지하기 어려웠다.

그래서 네이버 쇼핑 API를 선택했다. API 검색 결과에서 상품명, 이미지, 가격, 판매처와 상품 URL을 함께 받고, 이를 검색 데이터로 만드는 프로그램을 작성했다. 이미지는 의류 영역을 확인한 뒤 FashionCLIP 임베딩으로 변환하고, 벡터와 상품 정보를 Qdrant에 함께 저장했다. 덕분에 유사한 이미지를 찾은 다음 실제 상품 페이지까지 이어지는 흐름을 만들 수 있었다.

OpenCV는 무엇을 비교할지 정했다

전신 착용 사진을 그대로 벡터화하면 옷만 비교되지 않는다. 얼굴, 포즈, 배경, 조명과 주변 사물까지 이미지의 특징에 섞일 수 있다. 이 프로젝트에서 OpenCV가 맡은 일은 사진 전체를 검색 모델에 넘기기 전에, 비교할 의류 영역을 정리하는 것이었다.

입력 이미지는 PIL의 RGB 이미지에서 NumPy 배열로 바꾸고, OpenCV가 사용하는 BGR 채널 순서로 변환했다. 의류 탐지 모델을 우선 사용하되 모델을 사용할 수 없을 때는 Cascade나 HOG 탐지 방식으로 대체할 수 있게 했다. 탐지한 바운딩 박스는 소매나 밑단이 잘리지 않도록 여백을 더하고, 좌표가 이미지 밖으로 나가지 않게 보정한 뒤 잘라냈다.

네이버 쇼핑 상품을 Qdrant에 넣을 때도 같은 문제가 있었다. 자동으로 제안된 영역이 정확하지 않으면 사람이 직접 박스를 조정하거나 다시 선택할 수 있게 했다. 사용자 사진과 기준 상품 이미지가 모두 의류 중심으로 정리돼야 벡터 비교의 기준도 일관될 수 있기 때문이다.

사용자 이미지
  → OpenCV·YOLO 의류 영역 추출
  → FashionCLIP 임베딩 생성
  → Qdrant 코사인 유사도 검색
  → 상품 정보와 쇼핑몰 URL 반환

과제지만 검색 화면에서 끝내고 싶지는 않았다

6월 6일 제출 시점에는 이미지 업로드와 OpenCV 전처리뿐 아니라 React 화면, FastAPI 백엔드, YOLO 탐지, FashionCLIP 임베딩, Qdrant 검색과 Gemini 이미지 특징 분석까지 연결했다. JWT 로그인과 MySQL 상품 저장 기능, Docker 기반 실행 환경도 함께 구성했다.

FastAPI는 이미지와 검색 옵션을 받고, 전처리·임베딩·벡터 검색 서비스를 차례로 호출한다. Gemini 분석은 색상이나 소재, 패턴과 같은 설명용 특징을 따로 만들고, 벡터 검색은 외부 AI 호출과 분리했다. 특징 분석에 실패해도 유사 상품 검색 결과 자체는 유지되도록 한 이유다.

검색 결과 중 마음에 드는 상품을 관리자가 저장하거나 지울 수 있게 JWT 인증과 MySQL도 붙였다. 수업 과제의 핵심은 디지털영상처리였지만, 실제로 사용할 수 있는 형태를 만들려면 이미지 한 장을 처리하는 코드 바깥의 흐름도 필요했다.

6월 6일의 커밋은 완성 과정의 마지막 정리였다

GitHub에는 6월 6일 저녁에 정리한 프로젝트 스냅샷과 OpenCV 보강 기록이 남아 있다. 첫 커밋에 프런트엔드와 백엔드, 모델, 데이터 구축 스크립트와 실행 환경이 한꺼번에 포함돼 있어 이 기록을 개발 시작 시점으로 보기는 어렵다. 제출할 프로젝트를 공개 저장소에 정리한 마지막 구간에 가깝다.

프로젝트 스냅샷 정리

React, FastAPI, Qdrant, MySQL과 이미지 검색 모델을 포함한 전체 프로젝트 구조를 공개 저장소에 정리했다.

OpenCV 처리 과정을 코드와 문서에 드러냈다

RGB·BGR 변환부터 탐지기 선택, 바운딩 박스 여백과 좌표 보정까지 전처리 흐름을 정리하고 메타데이터를 남기도록 보강했다.

기준 데이터 구축에도 같은 원칙을 적용했다

네이버 쇼핑 API로 가져온 이미지를 OpenCV로 확인·크롭한 뒤 FashionCLIP 벡터로 만들고 Qdrant에 저장하는 과정을 문서화했다.

교수님의 다음 제안

교수님은 결과물을 만족스럽게 봐주셨고, 2학기 졸업작품으로 전시해 보는 것이 어떻겠냐고 제안하셨다. 과제 제출로 끝날 것이라고 생각했던 프로젝트에 다음 단계가 생긴 순간이었다.

이 서비스가 완성된 상용 쇼핑몰이라는 뜻은 아니다. 수집할 수 있는 상품 범위, 이미지마다 달라지는 크롭 품질, 검색 결과의 일관성처럼 더 확인해야 할 부분이 남아 있다. 그래도 수업에서 요구한 “실제로 쓸 수 있는 영상처리 프로젝트”를 한 번의 시연으로 끝내지 않고, 계속 손볼 이유는 충분해졌다.

종강했지만 프로젝트는 아직 진행 중이다

종강 후인 8월에는 README를 백엔드 요청 흐름 중심으로 다시 쓰고 실제 검색 GIF를 추가했다. OpenCV가 전체 서비스에서 어디에 있고, 전처리 결과가 FashionCLIP과 Qdrant로 어떻게 이어지는지 처음 보는 사람도 확인할 수 있도록 문서를 정리했다.

프로젝트 자체의 보강은 아직 진행 중이다. 지금 시점의 글은 완성 보고서라기보다, 과제로 만든 결과물을 졸업작품 후보로 다시 바라보기 시작한 기록에 가깝다. 처음에는 대화 중에 나온 작은 아이디어였지만, 이제는 이미지 처리와 데이터 구축, 백엔드 구조를 함께 개선해 볼 수 있는 장기 프로젝트가 됐다.

패션 유사도 검색 시연 영상 보기