Build an Image Search Engine

Weaviate is a vector database that allows you to create and query embeddings with pre-trained deep learning models. It integrates with ResNet-50 to vectorize images, making it possible to build an image similarity search engine with relative ease.

Initial Setup

Docker Compose Wizard

To run Weaviate locally, use their wizard to generate a Docker Compose config that supports the image module.

Install the Weaviate Client

Create a new Node.js project and install the Weaviate TS client.

command line
npm init -y
npm i weaviate-ts-client

Image Search Engine App

Image search in a vector database

Image search in a vector database

Initialize the Client

Initialize the client and fetch the schema just to make sure the database is up and running.

file_type_js app.js
import weaviate from 'weaviate-ts-client';

const client = weaviate.client({
    scheme: 'http',
    host: 'localhost:8080',
});

const schemaRes = await client.schema.getter().do();

console.log(schemaRes)

Create a Schema

Create a schema that contains an image property.

file_type_js index.js
const schemaConfig = {
    'class': 'Meme',
    'vectorizer': 'img2vec-neural',
    'vectorIndexType': 'hnsw',
    'moduleConfig': {
        'img2vec-neural': {
            'imageFields': [
                'image'
            ]
        }
    },
    'properties': [
        {
            'name': 'image',
            'dataType': ['blob']
        },
        {
            'name': 'text',
            'dataType': ['string']
        }
    ]
}

await client.schema
    .classCreator()
    .withClass(schemaConfig)
    .do();

Store an Image

Images must first be converted to base64. Once converted, store it to the cooresponding class in the schema. Weaviate will automatically use the neural network in the background to vectorize it and update the embedding.

file_type_js index.js
const img = readFileSync('./img/hi-mom.jpg');

const b64 = Buffer.from(img).toString('base64');

await client.data.creator()
  .withClassName('Meme')
  .withProperties({
    image: b64,
    text: 'matrix meme'
  })
  .do();

Query an Image

After storing a few images, we can provide an image as a query input. The database will use HNSW to quickly find similar looking images.

file_type_js index.js
const test = Buffer.from( readFileSync('./test.jpg') ).toString('base64');

const resImage = await client.graphql.get()
  .withClassName('Meme')
  .withFields(['image'])
  .withNearImage({ image: test })
  .withLimit(1)
  .do();

// Write result to filesystem
const result = resImage.data.Get.Meme[0].image;
writeFileSync('./result.jpg', result, 'base64');

And finally, run it with Node to your search engine in action!

command line
node index.js

Questions? Let's chat

Open Discord