데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      음식 사진 한 장으로 내가 딱 원하던 맛집을 찾는 AI, 어떻게 만들었을까

      dracomalfoy 25.07.18
      3,808 10 2
      DEVOTEE 요약
      이 프로젝트는 음식 사진을 통해 사용자가 주변에서 비슷한 음식을 판매하는 맛집을 찾을 수 있는 AI 시스템을 구축한 사례입니다. OpenAI의 CLIP 모델을 활용하여 음식 이미지를 임베딩 벡터로 변환한 뒤, FAISS 라이브러리로 고속 유사도 검색을 수행했으며, 위치 기반 반경 제한 및 음식 카테고리 필터링을 통해 보다 정확하고 현실적인 추천 결과를 제공했습니다. 향후 음식/비음식 이미지 필터링 강화, 사용자 취향을 반영한 맛 기반 임베딩 개선 등을 통해 시스템을 더욱 정교화할 계획입니다.
      DEVOTEE 추천 블로그

      목차

      • 개요

      • 핵심 기술은? CLIP을 통한 이미지 임베딩

      • 어떻게 만들었을까요?

      • 문제 해결 과정 (Troubleshooting)

      • 예시 결과를 살펴볼까요?

      • 향후 고도화 방안


      개요

      안녕하세요! 검색서비스팀에서 최근에 개발 중인 프로젝트를 소개하려고 합니다. 바로 “음식 사진을 넣으면 유사한 맛집 사진을 찾아주는 AI 시스템” 입니다.

      요즘 맛집을 찾을 때 사진 검색이 꽤 중요하다는 사실, 공감하실 겁니다. 그런데 먹고 싶은 음식은 있는데 어디서 파는지 모를 때는 어떨까요?

      예를 들어, “이 음식 진짜 맛있어 보이는데, 어디서 먹을 수 있지?” 라는 생각이 드는 순간, 그 사진을 넣기만 하면 비슷한 메뉴를 파는 식당을 추천해주는 AI가 있다면 정말 편리하겠죠.

      이런 니즈에서 출발해, 음식 사진 기반 맛집 검색 시스템을 개발하게 되었습니다.

      실제 사용 시나리오는 다음과 같습니다.

      1. 사용자가 음식 사진 한 장을 업로드합니다.

      2. 시스템이 유사한 맛집 이미지들을 찾아서 보여줍니다.

      3. 사용자는 이미지 결과를 보고, “오! 내가 딱 원하던게 여기에 파네! 여기 가야겠다” 하고 결정할 수 있습니다.


      핵심 기술은? CLIP을 통한 이미지 임베딩

      CLIP이란 무엇인가요?

      • CLIP(Contrastive Language–Image Pretraining)은 OpenAI에서 발표한 모델로, 이미지와 텍스트를 동일한 임베딩 공간에 매핑할 수 있는 강력한 특성을 가지고 있습니다.

        이 특성 덕분에 CLIP은 "이미지 검색", "텍스트-이미지 매칭", "멀티모달 분류" 등 다양한 작업에 활용됩니다.

      CLIP의 구조는 아래와 같습니다.

      • 이미지 인코더: 주로 Vision Transformer (ViT) 또는 ResNet이 사용됩니다.

      • 텍스트 인코더: Transformer 기반의 텍스트 인코더

      CLIP은 다음과 같은 방식으로 학습됩니다.

      1. 대규모 웹 데이터 수집: 인터넷에서 수집된 수억 개의 (이미지, 캡션) 쌍을 학습 데이터로 사용합니다.

      2. 쌍별 유사도 학습 (Contrastive Learning): 이미지와 텍스트를 각각 임베딩한 후, 정답 쌍은 서로 유사하게, 나머지는 멀리 떨어지도록 학습합니다.

      3. 멀티모달 임베딩 공간 매핑: 학습을 통해 이미지와 텍스트가 같은 의미를 공유할 경우, 두 임베딩이 가까운 위치에 오도록 매핑됩니다.

      이 시스템에서는 CLIP의 이미지 임베딩 기능만 사용했습니다.

      즉, 텍스트는 사용하지 않고, 다음과 같은 흐름으로 진행했습니다

      1. 음식 이미지와 맛집 이미지 모두 CLIP의 이미지 인코더를 통과시켜 임베딩 벡터로 변환합니다.

      2. 벡터 공간상에서 사용자 이미지와 가장 가까운 맛집 이미지를 코사인 유사도 기준으로 검색합니다.

      3. 유사 이미지에 연결된 맛집 정보를 기반으로 사용자에게 식당을 추천합니다.

      CLIP은 학습 과정에서 이미지의 "의미"를 추상화해서 인코딩하기 때문에, 단순한 픽셀 유사도보다 훨씬 더 의미론적 유사도(semantic similarity) 를 잘 포착할 수 있습니다.

      예를 들어, 두 라멘 사진이 촬영 각도나 조명은 다르지만 “빨간 국물 + 파 토핑”이라는 시각적 패턴이 비슷하다면, CLIP은 이를 높은 유사도로 인식해줍니다.

      이처럼 CLIP은 단순한 이미지 분류기와는 달리, 이미지 간 의미적 관계까지도 이해하고 비교할 수 있는 강력한 멀티모달 모델입니다.

      이번 프로젝트에서도 그런 특성이 유사한 음식 사진을 정확하게 찾아주는 데 큰 역할을 했습니다.


      어떻게 만들었을까요?

      대략적인 구조는 다음과 같습니다. 음식 이미지와 위치 정보를 바탕으로, 사전 임베딩된 데이터에서 시각적으로 유사하면서도 반경 내에 위치한 음식 이미지를 검색한 뒤,

      해당 이미지에 연결된 메타데이터를 활용해 실제 식당 정보를 추천합니다.


      1. 데이터 수집

      서비스의 기반이 되는 데이터는 내부적으로 보유한 맛집 데이터셋입니다. 맛집에 매칭되는 음식 이미지에 다음과 같은 정교한 메타데이터를 함께 연결해 저장했습니다

      • 이미지 URL

      • 이미지가 소속된 식당의 고유 ID

      • 음식 카테고리

      • 음식점의 위도 및 경도 좌표

      2. 이미지 임베딩 생성

      음식 이미지를 이해하고 비교하기 위해 OpenAI의 CLIP-ViT-B/16 모델을 사용했습니다.

      이 모델은 이미지 하나를 입력받으면 512차원의 벡터(임베딩)으로 변환해주며, 이 벡터는 그 이미지의 시각적 특징을 압축해 표현하고 있습니다.

      예를 들어, 김치찌개 사진을 넣으면 [0.043, -0.112, 0.201, ..., -0.038] 처럼 변환되고 이 벡터는 김치찌개의 비주얼적인 특징인 붉은 국물색, 고기와 채소의 배치등을 담고 있습니다.

      이러한 방식으로 openai/clip-vit-base-patch16 모델을 사용해, 내부적으로 보유한 모든 음식 이미지에 대해 사전에 임베딩 벡터를 생성해두었습니다.

      3. 전체 음식 이미지에 대해 임베딩 사전 생성 및 FAISS 색인

      사용자가 이미지를 업로드할 때마다 보유한 모든 음식 이미지와 하나씩 비교하는 방식은 계산량이 선형적으로 증가하기 때문에, 데이터가 많아질수록 성능 저하가 급격하게 발생합니다.

      예를 들어, 10,000장의 음식 이미지가 있다면 단 한 장의 쿼리 이미지를 비교하기 위해도 10,000회의 유사도 계산이 필요합니다.

      이를 해결하기 위해 사전에 모든 이미지에 대해 임베딩을 생성한 뒤, 고속 유사도 검색을 지원하는 FAISS 라이브러리를 사용해 다음과 같이 모든 음식점 이미지에 대해 색인하는 과정을 거쳤습니다.

      1. 사전 수집된 음식 이미지 데이터셋의 각 이미지를 CLIP 모델에 입력합니다.

      2. 각 이미지에 대해 512차원 임베딩 벡터를 생성합니다. (이 벡터는 이미지의 시각적 특징을 압축 표현한 것으로, 다른 이미지와의 유사도를 계산할 수 있는 기준이 됩니다.)

      3. 모든 임베딩 벡터를 FAISS의 인덱스 객체에 추가하여, 벡터 검색 인덱스를 구성합니다.

      이렇게 구축된 인덱스를 통해, 사용자는 쿼리 이미지 한 장만 업로드해도 수천~수만 개의 음식 이미지 중에서 가장 유사한 후보를 빠르게 검색할 수 있게 됩니다.

      4. 반경 제한 (위치 기반 필터링)

      이미지 임베딩과 FAISS를 이용해 시각적으로 유사한 음식 이미지를 검색할 수 있게 되었지만, 한 가지 문제가 남아 있었습니다. 바로 지역과 관계없는 음식이 추천될 수 있다는 점입니다.

      예를 들어 사용자가 서울 강남에 있으면서 마라탕 사진을 업로드했는데, 부산에 있는 마라탕 집이 추천 결과에 포함되는 일이 실제로 발생할 수 있습니다.

      이를 해결하기 위해 우리는 사용자의 현재 위치(위도, 경도)를 중심으로 일정 반경(km) 이내에 있는 식당만 검색 대상이 되도록 설계했습니다.

      즉, “서울에 있는 사용자”라면, 서울 근방의 식당 음식 이미지 중에서만 유사도를 비교하게 되는 것입니다.

      • 예시:

        • 사용자 현재 위치: [37.4979, 127.0276] (강남역)

        • 반경 설정: 5km

        • 검색 대상: 강남역 반경 5km 이내의 음식 이미지들

          구체적으로는 다음과 같은 방식을 적용했습니다. 위치 필터링은 위도/경도 좌표를 2차원 공간상의 점으로 보고, KDTree 알고리즘을 이용해 반경 내 식당을 빠르게 탐색하는 방식으로 구현했습니다.

      1. 먼저, 모든 식당의 위도/경도 좌표를 라디안 단위로 변환한 후, KDTree를 구성합니다.

      2. 사용자의 위치 역시 라디안으로 변환해, 지정된 반경(km)을 만족하는 식당 인덱스만 추출합니다.

      3. 이후 이 인덱스를 기준으로 FAISS의 서브 인덱스(sub-index)를 구성하고, 유사도 검색은 이 위치 조건을 만족하는 이미지에 한해서만 수행합니다.

      이와 같은 위치 기반 필터링을 통해 단순히 시각적으로 유사한 음식뿐만 아니라, 현실적으로 접근 가능한 식당을 추천할 수 있게 되었습니다.

      5. 결과출력

      이미지 임베딩과 위치 기반 필터링을 거친 뒤, 시스템은 사용자가 업로드한 음식 사진과 시각적으로 가장 유사하면서도 반경 내에 위치한 음식 이미지들을 최종 후보로 추출합니다.

      하지만 여기서 중요한 것은 단순히 비슷한 이미지를 보여주는 것이 아니라, 그 이미지가 실제 어느 식당에서 촬영된 것인지까지 정확하게 연결해주는 것입니다.

      검색 결과는 기본적으로 이미지의 URL과 유사도 점수만 포함되어 있지만, 우리는 각 이미지에 대해 사전에 다음과 같은 메타데이터를 함께 저장해두었습니다:

      • 음식 ID (내부 식별자)

      • 음식 카테고리 (예: 파스타, 김치찌개, 초밥 등)

      • 해당 이미지가 속한 식당의 위도·경도 좌표

      이 정보를 바탕으로 검색된 이미지가 실제 어느 식당의 음식인지 역추적이 가능하며,

      이를 통해 사용자는 단순히 "이 사진이 비슷하다"는 결과를 넘어 "이 음식은 강남역 인근의 OO식당에서 판매되고 있습니다"와 같이 명확하고 구체적인 추천 정보를 전달받을 수 있습니다.


      문제 해결 과정 (Troubleshooting)

      이미지 유사도만 믿으면 생기는 문제

      아래 이미지는 이 문제를 겪었던 실제 테스트 결과입니다.

      • 사용자 입력 이미지:

      • 검색 결과 이미지:

      위 검색 결과를 쭉 보면서 “어? 뭔가 좀 이상한데…” 하셨다면, 정답입니다.

      처음엔 분명 토마토소스 스파게티 이미지였는데, 4번째 사진쯤부터 갑자기 아구찜이 슬쩍 끼어들었죠. 색감은 비슷하지만, 이건 완전히 다른 음식입니다.

      해결 방법

      이 문제를 해결하기 위해, 검색 결과를 음식 카테고리 단위로 제한하는 전략을 도입했습니다.

      1. 사용자가 업로드한 이미지와 가장 유사한 맛집 이미지 Top-1 결과의 카테고리를 추출합니다.

        예를 들어, Top-1이 “파스타”라면 이를 기준으로 판단합니다.

      2. 이후 검색 대상은 동일한 카테고리(파스타류) 로 한정하여 다시 유사도 검색을 수행합니다.

      3. 이렇게 하면, 유사한 색감이나 형태를 가진 다른 종류의 음식(예: 아구찜, 짬뽕 등)은 자연스럽게 제외됩니다.

      이 방식으로 검색된 결과는 사용자 기대와 의미적으로 더 잘 맞는 음식들로 구성되었습니다.


      예시 결과를 살펴볼까요?

      다음은 을지로 T타워를 기준으로 반경 5km 이내에서 다음과 같은 이미지와 유사한 맛집을 찾아본 결과입니다.

      • 사용자 입력 이미지 A :


      • 해당 추천 맛집 Top 5 :



      • 사용자 입력 이미지 B :


      • 해당 추천 맛집 Top 5 :

      어떤가요? 사용자가 만족할 만한 식당이 나온 것 같지 않나요?

      단순히 이미지 임베딩 기반 유사도만 사용하는 것이 아니라, 위치 기반 반경 제한 + 음식 카테고리 필터링을 함께 적용하면서 실제 사용 환경에서도 높은 정확도를 확보할 수 있었습니다.


      향후 고도화 방안

      이번 프로젝트에서는 음식 사진 한 장만으로, 사용자 주변에서 해당 음식과 유사한 메뉴를 판매하는 식당을 찾아주는 시스템을 구축했습니다.

      이를 위해 사전학습된 CLIP 모델을 활용하여 이미지의 시각적 특징을 임베딩으로 변환하고, 고속 벡터 검색 라이브러리인 FAISS를 이용해 유사한 음식 이미지를 빠르게 탐색할 수 있도록 구성했습니다.

      여기에 사용자의 위치 정보를 결합한 반경 제한 필터링을 적용함으로써, 단순히 비슷한 이미지를 찾는 것을 넘어 현실적으로 접근 가능한 식당 추천이 가능하도록 설계했습니다.

      또한, 시각적으로는 유사하지만 전혀 다른 음식 카테고리로 연결되는 오류를 방지하기 위해, 카테고리 기반 필터링을 도입했습니다.

      이를 통해 검색 결과 중에서도 사용자의 음식 이미지와 동일한 카테고리에 속한 결과만 추려내며,

      추가로 각 이미지에 연결된 음식 ID, 카테고리, 식당 위치 등의 메타데이터를 활용해 실제 식당 정보를 역추적하여, 사용자에게 직관적이고 신뢰도 높은 추천 결과를 제공하는 파이프라인을 완성했습니다.

      향후에는 사용자 경험의 정확성과 만족도를 더욱 높이기 위해 다음과 같은 방향으로 고도화를 계획하고 있습니다.


      1. 음식 이미지 필터링 정밀화 (Non-food 이미지 제거)

      현재 시스템은 입력 이미지가 음식이 아닐 경우에도 검색을 시도하지만, 추후에는 다음과 같은 방식으로 음식이 아닌 이미지를 사전에 필터링할 예정입니다.

      • CLIP 임베딩 기반 cosine distance를 활용하여 "a photo of food" 같은 프롬프트 텍스트와의 거리 계산

      • 일정 임계값(threshold)을 초과하는 경우 비음식 이미지로 간주하여 검색을 중단

      • CLIP 모델 자체를 음식/비음식 분류 task로 파인튜닝 하여 임베딩 간 간극을 더 명확히 유도할 예정

      이를 통해 음식이 아닌 이미지로 인해 발생하는 검색 오류를 최소화 할 방안입니다.


      2. 음식 카테고리 분류 → 맛 기반 임베딩 확장

      현재는 가장 유사한 음식의 카테고리(category)를 추론해, 같은 카테고리에 속하지 않은 후보는 필터링하는 방식으로 정확도를 높이고 있습니다.

      하지만 카테고리라는 정보로만 음식을 구분하는 것에는 한계가 있습니다. 이를 해결하기 위해 좀 더 미묘한 ‘맛의 유사성’까지 반영한 임베딩 구조로 진화시킬 계획입니다.

      구체적으로는:

      • CLIP 모델의 텍스트 인풋 구성을 재설계하여, 기존에는 "a photo of pork cutlet" 수준이었지만,

        앞으로는 "a photo of crispy, deep-fried pork cutlet served with sweet brown sauce and shredded cabbage salad"처럼

        조리 방식(튀김), 식감(바삭함), 소스 특징, 곁들임 등 음식의 풍미와 맥락을 함께 인코딩하는 실험을 진행할 예정입니다.

      궁극적으로 사용자가 그 순간 가장 먹고 싶은 음식을 정확히 찾아낼 수 있도록 앞으로도 사용자의 니즈를 더 깊이 이해하고, 그에 정교하게 반응할 수 있는 다양한 시도를 지속해 나갈 예정입니다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      dracomalfoy 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기