[Elasticsearch] Similar image search by image or natural language(1)

Elasticsearch(이하 ES)에서 자연어나 이미지로 유사한 이미지를 검색하는 방법에 대해서 알아보자.

유사한 이미지를 찾기 위해서는 먼저 이미지들 간의 유사도를 측정할 방법이 필요하고, 유사도를 측정하기 위해서 Vector를 사용할 수 있다. 이미지를 Embedding을 통해서 Vector로 변환하고, Vector 간의 유사도(Cosine similarity)를 계산해서 유사한 이미지를 찾을 수 있다.

그러면, 이미지를 Vector embedding하는 방법은 무엇이 있을까?

이미지를 vector embedding하는 방법과 이를 만들어주는 ML 모델들은 이미 많이 공개 되어 있다. ResNet, VGGNet, Inception 등 많은 모델들이 있다. 모델들의 성능을 잘 비교해서 알맞은 모델을 사용하면 된다.

여기에서는 OpenAI에서 공개한 CLIP model를 사용할 것이다.

CLIP을 사용해서 검색할 이미지들을 vector embedding해보자.
(사용할 이미지가 없다면 아래 첨부된 이미지를 사용해보자.)

from sentence_transformers import SentenceTransformer
from PIL import Image

img_model = SentenceTransformer('clip-ViT-B-32', device='cpu')

def vectorize(file_path):
    image = Image.open(file_path)
    embedding = img_model.encode(image)
    del image

    return embedding.tolist()

vectorize('./image/apple.jpg')

위 코드를 실행해보면 이미지가 vector embedding되어 512 차원의 vector를 반환하는 것을 확인 할 수 있다. 검색 대상의 이미지들을 모두 embedding 하면 된다.

vector embedding된 값들을 생성했다면, 이제 vector들을 ES에 올려서 유사 이미지 검색을 해보자.

먼저, ES에서 Vector를 담을 index를 생성한다.

PUT image_vector
{
  "mappings": {
    "properties": {
      "image_name": {
        "type": "keyword"
      },
      "vector": {
        "type": "dense_vector",
        "dims": 512,
        "index": true,
        "similarity": "cosine"
      }
    }
  }
}

생성한 인덱스에 만든 Vector 값들을 넣어준다.

from elasticsearch import Elasticsearch

def index(image_name, vector):
    es = Elasticsearch(cloud_id='elastic_cloud_id',
                       basic_auth=('elastic', 'elastic_secret'))
    doc = {     
        'image_name': image_name,
        'vector': vector
    }

    es.index(index='image_vector', body=doc)

index('apple.jpg', vector)

여기까지 하면 유사한 이미지를 검색하기 위한 준비는 끝난다.

원하는 이미지를 하나 골라서 검색을 해보자

GET image_vector/_search
{
  "knn": {
    "field": "vector",
    "k": 5,
    "num_candidates": 10,
    "query_vector": [
      0.5978590846061707,
      0.5926558375358582,
      -0.1243332028388977,
      0.11083680391311646,
      -0.6588778495788574,
     ... 생략 ...
      0.37319913506507874
    ]
  },
  "fields": [
    "image_name"
  ],
  "_source": false
}

왼쪽 끝의 사과 이미지와 위 예제 파일안에서 유사한 이미지 4개를 찾은 것을 확인 할 수 있다.

Next: Similar image search by image or natural language(2)

글쓴이

thenewth

AI Research Engineer & Cloud Platform Developer

“[Elasticsearch] Similar image search by image or natural language(1)” 글에 관한 1개의 생각

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

This site uses Akismet to reduce spam. Learn how your comment data is processed.