Image similarity search tool helps you to find similar images in your data set. Unlike other algorithms like image classification, object detection, and semantic/instance segmentation, image similarity search tool does not require either image labeling or model training. You can use the image similarity search tool out of the box!

There are two main options to use image similarity Search online or offline. If you want to use the image similarity search online, you can do it via SentiSight.ai web platform or via our REST API server. If you would like to use the model offline, you will have to download the model and set up a REST API server yourself. Below we will describe all of those options.

There are two types of Image Similarity Search you can perform: 1vN that finds similar images to a single query image and NvN that finds the most similar image pairs in your data set. The query image for the 1vN image similarity search can either be uploaded from your computer or selected from your data set on the SentiSight.ai platform.

Regardless of the type of image similarity search you are planning to use, first, you need to create a project and upload some images that will be used as a data set for your image similarity search queries. You can upload your images using the platform or via API. If you are using the platform, press the red Upload button to upload individual images, or Upload folder or Upload zip buttons to upload large numbers of images. If you are planning to use the API for image upload, read more about it here. Note that for image similarity search image labeling is not necessary.

Note, that every image similarity search performed counts against your monthly prediction limit.

Consider cheking out image similarity search video tutorial.

A common misconception

A common misconception is that Similarity search is an alternative to Google image search. It is not. Similarity search only compares images within your project and does not search for images on the internet.

Using image similarity search tool via SentiSight.ai web platform

To perform the image similarity search, click on the “Image similarity" menu item on the top of the screen and select "Search by similarity”. In the menu that pops up, you can select image similarity search type 1vN or NvN. The 1vN type will find you similar images to the query image that you upload. The NvN type will look for similar image pairs in all of your data set. The result number field will adjust how many top matching images/image pairs are displayed and score threshold will determine what is the minimum similarity score for the matching images/image pairs to be displayed.

sim-search-newsim-search-newf

Note that you can also perform 1vN image similarity search with an existing image in your data set. To do that, just right click on any image and select “Image similarity search” option from a dropdown menu.

1vN Similarity Results

When using similarity search with either an existing or uploaded image, the results window shows individual suggestions, with a score indicating how similar they are to the query image.

NvN Similarity Results

When using NvN similarity search, the results window shows pairs of images that have been deemed most similar to each other. Each pair might consist of unique images, or the same image can appear in several pairs.

Similarity Search and Image Labeling

On the left-hand side of the results page you can see the classification labeling panel. With it you can quickly add or remove labels to similarity search results, allowing you to improve the accuracy of labeling in your project.

You can read more about classification labeling here. Classification labeling on the similarity results page follows the same mechanics as labeling in the main project window.

If you are planning to use Similarity Search labeling to label images newly added to the project, consider using Labeling by similarity - a powerful tool designed specifically for that. You can read more about it here.

Using image similarity search tool via SentiSight.ai REST API

To begin using the image similarity search tool via REST API you will need these details:

  • API token (available in the Wallet drop-down)
  • Project ID (available in project selection drop-down)

For 1vN image similarity search you will also need an image file (either existing in your project or stored in your computer).

In all types of image similarity search you can optionally specify the maximum number of results to be displayed and the similarity score threshold. You can also specify one or more image labels to filter the images in your data set prior to image similarity search, hence, reducing the search space. You can also choose between "and" and "or" operators when filtering images by labels. All of these options can be specified as GET parameters when formatting the URL for the request. For more details see the code samples below.

Please, note that it is also possible to retrieve the images you find via Similarity Search. For more information read here.

1vN image similarity search with an image from your computer

Set the "X-Auth-token" header to your API token string and set "Content-Type" header to "application/octet-stream". Set the body to your image file. See the example code below.

TOKEN="your_token"
PROJECT_ID="your_project_id"
IMAGE_FILENAME="your_image_path" # This is the filepath to the image on your PC
FILTER_LABELS="your labels here" # labels should be separated by spaces
AND_OPERATOR="true" # set to "false" to use "or" operator instead for filtering images by labels
LIMIT=10
THRESHOLD=0


LABEL_OP=''
for LABEL in $FILTER_LABELS ; do
  LABEL_OP+="&labels=$LABEL"
done

curl -H "X-Auth-token: $TOKEN" --data-binary @"$IMAGE_FILENAME" \
  -H "Content-Type: application/octet-stream" \
  -X POST "https://platform.sentisight.ai/api/similarity?project=$PROJECT_ID$LABEL_OP&and=$AND_OPERATOR&limit=$LIMIT&threshold=$THRESHOLD"
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;

public class App {
    public static void main(String[] args) throws IOException {
        String token = "";
        String projectId = "0";
        String imageFilename = "image.jpg";
        String[] labels = {"label1", "label2"};
        int limit = 10;
        double threshold = 0;

        String lstr = "";
        for (String label : labels) {
            lstr += ("&labels=" + label);
        }
        lstr += ("&and=true"); // to use 'or' operator for filtering labels remove this line or change it to '&and=false'
        lstr += ("&limit=" + limit);
        lstr += ("&threshold=" + threshold);

        URL url = new URL("https://platform.sentisight.ai/api/similarity?project=" + projectId + lstr);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Content-Type", "application/octet-stream");
        connection.setRequestProperty("X-Auth-token", token);
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        byte[] bytes = Files.readAllBytes(new File(imageFilename).toPath());
        wr.write(bytes);
        wr.flush();
        wr.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String output;
        while ((output = in.readLine()) != null) {
            System.out.println(output);
        }
        in.close();
    }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Sample</title>
        <script>
            const baseApiURL = 'https://platform.sentisight.ai/api/';
            var token = '';
            var predictionId;
            var projectId;
            var images = [];

            function similaritySearch() {
                document.getElementById('button').disabled = true;
                token = document.getElementById('tokenfield').value;
                projectId = document.getElementById('project').value;
                var input = document.getElementById('upload');
                const file = input.files[0];
                var fr = new FileReader();
                fr.onload = function() {
                    performSimilaritySearch(fr.result);
                }
                if (file) {
                    fr.readAsArrayBuffer(file);
                }
            }

            function performSimilaritySearch(file) {
                var labelText = document.getElementById('labels').value;
                var labels = [];
                if (labelText.length) {
                    labels = labelText.split(',');
                }
                var lstr = '';
                labels.forEach(function(label) {
                    lstr += ('&labels=' + label);
                });
                if (document.getElementById('limit-on').checked) {
                    lstr += ('&limit=' + document.getElementById('limit').value)
                }
                if (document.getElementById('threshold-on').checked) {
                    lstr += ('&threshold=' + document.getElementById('threshold').value)
                }
                if (document.querySelector('input[name="and"]:checked').value == 'true') {
                    lstr += '&and=true';
                }
                var xmlHttp = new XMLHttpRequest();
                xmlHttp.open('POST',  baseApiURL + 'similarity?project=' + projectId + lstr, true);
                xmlHttp.setRequestHeader('Content-Type', 'application/octet-stream');
                xmlHttp.setRequestHeader('X-Auth-token', token);
                xmlHttp.onreadystatechange = function () {
                    if (this.readyState == 4 && this.status == 200) {
                        document.getElementById('button').disabled = false;
                        document.getElementById('results').innerHTML = xmlHttp.responseText;
                    }
                }
                xmlHttp.send(file);
            }

        </script>
    </head>
    <body>
        Token: <input id="tokenfield" type="text">
        <br>
        Project id: <input id="project" type="number">
        <br>
        Labels: <input id="labels" type="text">
        <br>
        <input type="radio" name="and" value="true"> And
        <input type="radio" name="and" value="false" checked> Or
        <br>
        <input id="limit-on" type="checkbox">Result number: <input id="limit" type="number">
        <br>
        <input id="threshold-on" type="checkbox">Score threshold: <input id="threshold" type="number" step="0.001">
        <br>
        Upload image: <input id="upload" type="file">
        <br>
        <button id="button" type="button" onclick="similaritySearch()">Perform similarity search</button>
        <br>
        <table id=results></table>
    </body>
</html>
import requests

token = "your_token"
project_id = "your_project_id"
image_filename = "your_image_path"
labels = ["your", "labels", "here"]
limit = 10  # limits result count to this number
threshold = 0  # only shows results above this threshold (value in percent)

headers = {"X-Auth-token": token, "Content-Type": "application/octet-stream"}

request_url = "https://platform.sentisight.ai/api/similarity?project={}".format(project_id)
for lbl in labels:
    request_url += "&labels={}".format(lbl)

request_url += "&and=true" # to use 'or' operator for filtering labels remove this line or change it to '&and=false'
request_url += "&limit={}".format(limit)
request_url += "&threshold={}".format(threshold)

with open(image_filename, "rb") as handle:
    r = requests.post(request_url, headers=headers, data=handle)

if r.status_code == 200:
    print(r.text)
else:
    print("Error occured with REST API.")
    print("Status code: {}".format(r.status_code))
    print("Error message: " + r.text)
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;

namespace Sample
{
    class Program
    {
        static void Main()
        {
            const string token = "";
            const int projectId = 0;
            const string imageFilename = "";
            string[] labels = {"label1", "label2"};
            const int limit = 10;
            const double threshold = 0;
            
            var labelString = labels.Aggregate("", (current, label) => current + $"&labels={label}");
            // to use 'or' operator for filtering labels remove the next line or change it to 'labelString += ("&and=false");'
            labelString += ("&and=true"); 
            labelString += ("&limit=" + limit);
            labelString += ("&threshold=" + threshold);
            
            var bytes = File.ReadAllBytes(imageFilename);
            var data = new ByteArrayContent(bytes);
            data.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");

            var uri = new Uri($"https://platform.sentisight.ai/api/similarity?project={projectId}{labelString}");
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("X-Auth-token", token);
            
            var response = client.PostAsync(uri, data);
            var result = response.Result.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }
    }
}

1vN image similarity search with an existing image in your data set

Set the "X-Auth-token" header to your API token string and set "Content-Type" header to "application/json". Set the body to a JSON formatted string with a "imageName" parameter specifying your query image name. The query image should be already uploaded to the SentiSight.ai platform. See the example code below.

TOKEN="your_token"
PROJECT_ID="your_project_id"
IMAGE_NAME="your_image_name" # this the name of an image which is already uploaded on platform.sentisight.ai
FILTER_LABELS="your labels here" # labels should be separated by spaces
AND_OPERATOR="true" # set to "false" to use "or" operator instead for filtering images by labels
LIMIT=10
THRESHOLD=0

LABEL_OP=''
for LABEL in $FILTER_LABELS ; do
  LABEL_OP+="&labels=$LABEL"
done
  
curl --location --request POST "https://platform.sentisight.ai/api/similarity?project=$PROJECT_ID$LABEL_OP&and=$AND_OPERATOR&limit=$LIMIT&threshold=$THRESHOLD" \
--header "X-Auth-token: $TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
    "imageName": ""$IMAGE_NAME""
}'
package sentisight.api.sample;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class App {
    public static void main(String[] args) throws IOException {
        String token = "";
        String projectId = "0";
        String imageName = "image.jpg";
        String[] labels = {"label1", "label2"};
        int limit = 10;
        double threshold = 0;

        StringBuilder paramsString = new StringBuilder();
        for (String label : labels) {
            paramsString.append("&labels=").append(label);
        }
        paramsString.append("&and=true"); // to use 'or' operator for filtering labels remove this line or change it to '&and=false'
        paramsString.append("&limit=").append(limit);
        paramsString.append("&threshold=").append(threshold);

        String body = "{\r\n    \"imageName\": \"%s\"\r\n}".formatted(imageName);

        URL url = new URL("https://platform.sentisight.ai/api/similarity?project=" + projectId + paramsString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("X-Auth-token", token);
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.writeBytes(body);
        wr.flush();
        wr.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String output;
        while ((output = in.readLine()) != null) {
            System.out.println(output);
        }
        in.close();
    }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Sample</title>
  <script>
    const baseApiURL = 'https://platform.sentisight.ai/api/';
    let token = '';
    let projectId;

    function similaritySearch() {
      document.getElementById('button').disabled = true;
      token = document.getElementById('tokenfield').value;
      projectId = document.getElementById('project').value;
      const imageName = document.getElementById('image-name').value;
      const labelText = document.getElementById('labels').value;
      let labels = [];
      if (labelText.length) {
        labels = labelText.split(',');
      }
      var lstr = '';
      labels.forEach(function(label) {
        lstr += ('&labels=' + label);
      });
      if (document.getElementById('limit-on').checked) {
        lstr += ('&limit=' + document.getElementById('limit').value)
      }
      if (document.getElementById('threshold-on').checked) {
        lstr += ('&threshold=' + document.getElementById('threshold').value)
      }
      if (document.querySelector('input[name="and"]:checked').value == 'true') {
        lstr += '&and=true';
      }
      var xmlHttp = new XMLHttpRequest();
      xmlHttp.open('POST',  baseApiURL + 'similarity?project=' + projectId + lstr, true);
      xmlHttp.setRequestHeader('Content-Type', 'application/json');
      xmlHttp.setRequestHeader('X-Auth-token', token);
      xmlHttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById('button').disabled = false;
          document.getElementById('results').innerHTML = xmlHttp.responseText;
        }
      }
      const data = JSON.stringify({
        imageName
      });
      xmlHttp.send(data);
    }

  </script>
</head>
<body>
Token: <input id="tokenfield" type="text">
<br>
Project id: <input id="project" type="number">
<br>
Labels: <input id="labels" type="text">
<br>
<input type="radio" name="and" value="true"> And
<input type="radio" name="and" value="false" checked> Or
<br>
<input id="limit-on" type="checkbox">Result number: <input id="limit" type="number">
<br>
<input id="threshold-on" type="checkbox">Score threshold: <input id="threshold" type="number" step="0.001">
<br>
Image name: <input id="image-name" type="text">
<br>
<button id="button" type="button" onclick="similaritySearch()">Perform similarity search</button>
<br>
<table id=results></table>
</body>
</html>
import requests
import json

token = "your_token"
project_id = "your_project_id"
image_name = "your_image_name".encode("utf-8")
labels = ["your", "labels", "here"]
limit = 10  # limits result count to this number
threshold = 0  # only shows results above this threshold  (value in percent)

payload = json.dumps({
    "imageName": image_name
})

headers = {"X-Auth-token": token, "Content-Type": "application/json"}

request_url = "https://platform.sentisight.ai/api/similarity?project={}".format(project_id)
for lbl in labels:
    request_url += "&labels={}".format(lbl)

request_url += "&and=true"  # to use 'or' operator for filtering labels remove this line or change it to '&and=false'
request_url += "&limit={}".format(limit)
request_url += "&threshold={}".format(threshold)

r = requests.post(request_url, headers=headers, data=payload)

if r.status_code == 200:
    print(r.text)
else:
    print("Error occured with REST API.")
    print("Status code: {}".format(r.status_code))
    print("Error message: " + r.text)
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace Sample
{
    class Program
    {
        static void Main()
        {
            const string token = "";
            const int projectId = 0;
            const string imageName = "";
            string[] labels = {"label1", "label2"};
            const int limit = 10;
            const double threshold = 0;
            
            var labelString = labels.Aggregate("", (current, label) => current + $"&labels={label}");
            // to use 'or' operator for filtering labels remove the next line or change it to 'labelString += ("&and=false");'
            labelString += ("&and=true"); 
            labelString += ("&limit=" + limit);
            labelString += ("&threshold=" + threshold);

            using var ms = new MemoryStream();
            using var writer = new Utf8JsonWriter(ms);
            writer.WriteStartObject();
            writer.WriteString("imageName", imageName);
            writer.WriteEndObject();
            writer.Flush();
            var json = Encoding.UTF8.GetString(ms.ToArray());
            
            var data = new StringContent(json, Encoding.Default, "application/json");

            var uri = new Uri($"https://platform.sentisight.ai/api/similarity?project={projectId}{labelString}");
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("X-Auth-token", token);
            
            var response = client.PostAsync(uri, data);
            var result = response.Result.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }
    }
}

1vN image similarity search with an image URL

Performing similarity search by providing an image URL is similar to the previous case of performing similarity with an existing image in your data set. The only difference is that you need to change the JSON parameter name "imageName" to "url".

TOKEN="your_token"
PROJECT_ID="your_project_id"
IMAGE_URL="your_image_url"
FILTER_LABELS="your labels here" # labels should be separated by spaces
AND_OPERATOR="true" # set to "false" to use "or" operator instead for filtering images by labels
LIMIT=10
THRESHOLD=0

LABEL_OP=''
for LABEL in $FILTER_LABELS ; do
  LABEL_OP+="&labels=$LABEL"
done
  
curl --location --request POST "https://platform.sentisight.ai/api/similarity?project=$PROJECT_ID$LABEL_OP&and=$AND_OPERATOR&limit=$LIMIT&threshold=$THRESHOLD" \
--header "X-Auth-token: $TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
    "url": ""$IMAGE_URL""
}'
package sentisight.api.sample;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class App {
    public static void main(String[] args) throws IOException {
        String token = "";
        String projectId = "0";
        String image_url = "";
        String[] labels = {"label1", "label2"};
        int limit = 10;
        double threshold = 0;

        StringBuilder paramsString = new StringBuilder();
        for (String label : labels) {
            paramsString.append("&labels=").append(label);
        }
        paramsString.append("&and=true"); // to use 'or' operator for filtering labels remove this line or change it to '&and=false'
        paramsString.append("&limit=").append(limit);
        paramsString.append("&threshold=").append(threshold);

        String body = "{\r\n    \"url\": \"%s\"\r\n}".formatted(image_url);

        URL url = new URL("https://platform.sentisight.ai/api/similarity?project=" + projectId + paramsString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("X-Auth-token", token);
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.writeBytes(body);
        wr.flush();
        wr.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String output;
        while ((output = in.readLine()) != null) {
            System.out.println(output);
        }
        in.close();
    }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Sample</title>
  <script>
    const baseApiURL = 'https://platform.sentisight.ai/api/';
    let token = '';
    let projectId;

    function similaritySearch() {
      document.getElementById('button').disabled = true;
      token = document.getElementById('tokenfield').value;
      projectId = document.getElementById('project').value;
      const url = document.getElementById('url').value;
      const labelText = document.getElementById('labels').value;
      let labels = [];
      if (labelText.length) {
        labels = labelText.split(',');
      }
      var lstr = '';
      labels.forEach(function(label) {
        lstr += ('&labels=' + label);
      });
      if (document.getElementById('limit-on').checked) {
        lstr += ('&limit=' + document.getElementById('limit').value)
      }
      if (document.getElementById('threshold-on').checked) {
        lstr += ('&threshold=' + document.getElementById('threshold').value)
      }
      if (document.querySelector('input[name="and"]:checked').value == 'true') {
        lstr += '&and=true';
      }
      var xmlHttp = new XMLHttpRequest();
      xmlHttp.open('POST',  baseApiURL + 'similarity?project=' + projectId + lstr, true);
      xmlHttp.setRequestHeader('Content-Type', 'application/json');
      xmlHttp.setRequestHeader('X-Auth-token', token);
      xmlHttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById('button').disabled = false;
          document.getElementById('results').innerHTML = xmlHttp.responseText;
        }
      }
      const data = JSON.stringify({
        url
      });
      xmlHttp.send(data);
    }

  </script>
</head>
<body>
Token: <input id="tokenfield" type="text">
<br>
Project id: <input id="project" type="number">
<br>
Labels: <input id="labels" type="text">
<br>
<input type="radio" name="and" value="true"> And
<input type="radio" name="and" value="false" checked> Or
<br>
<input id="limit-on" type="checkbox">Result number: <input id="limit" type="number">
<br>
<input id="threshold-on" type="checkbox">Score threshold: <input id="threshold" type="number" step="0.001">
<br>
URL: <input id="url" type="text">
<br>
<button id="button" type="button" onclick="similaritySearch()">Perform similarity search</button>
<br>
<table id=results></table>
</body>
</html>
import requests
import json

token = "your_token"
project_id = "your_project_id"
image_url = "http://your-image-url.png"
labels = ["your", "labels", "here"]
limit = 10  # limits result count to this number
threshold = 0  # only shows results above this threshold  (value in percent)

payload = json.dumps({
    "url": image_url
})

headers = {"X-Auth-token": token, "Content-Type": "application/json"}

request_url = "https://platform.sentisight.ai/api/similarity?project={}".format(project_id)
for lbl in labels:
    request_url += "&labels={}".format(lbl)

request_url += "&and=true"  # to use 'or' operator for filtering labels remove this line or change it to '&and=false'
request_url += "&limit={}".format(limit)
request_url += "&threshold={}".format(threshold)

r = requests.post(request_url, headers=headers, data=payload)

if r.status_code == 200:
    print(r.text)
else:
    print("Error occured with REST API.")
    print("Status code: {}".format(r.status_code))
    print("Error message: " + r.text)
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace Sample
{
    class Program
    {
        static void Main()
        {
            const string token = "";
            const int projectId = 0;
            const string imageUrl = "";
            string[] labels = {"label1", "label2"};
            const int limit = 10;
            const double threshold = 0;
            
            var labelString = labels.Aggregate("", (current, label) => current + $"&labels={label}");
            // to use 'or' operator for filtering labels remove the next line or change it to 'labelString += ("&and=false");'
            labelString += ("&and=true"); 
            labelString += ("&limit=" + limit);
            labelString += ("&threshold=" + threshold);

            using var ms = new MemoryStream();
            using var writer = new Utf8JsonWriter(ms);
            writer.WriteStartObject();
            writer.WriteString("url", imageUrl);
            writer.WriteEndObject();
            writer.Flush();
            var json = Encoding.UTF8.GetString(ms.ToArray());
            
            var data = new StringContent(json, Encoding.Default, "application/json");

            var uri = new Uri($"https://platform.sentisight.ai/api/similarity?project={projectId}{labelString}");
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("X-Auth-token", token);
            
            var response = client.PostAsync(uri, data);
            var result = response.Result.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }
    }
}

1vN image similarity search with a Base64 encoded image

Performing similarity search with a Base64 encoded image is similar to the cases of performing similarity search with an existing image in your data set or with an image URL. You only need to change the JSON parameter name "imageName" or "url" to "base64".

PROJECT_ID="your_project_id" IMAGE_B64="" FILTER_LABELS="your labels here" # labels should be separated by spaces AND_OPERATOR="true" # set to "false" to use "or" operator instead for filtering images by labels LIMIT=10 THRESHOLD=0 LABEL_OP='' for LABEL in $FILTER_LABELS ; do LABEL_OP+="&labels=$LABEL" done curl --location --request POST "https://platform.sentisight.ai/api/similarity?project=$PROJECT_ID$LABEL_OP&and=$AND_OPERATOR&limit=$LIMIT&threshold=$THRESHOLD" \ --header "X-Auth-token: $TOKEN" \ --header 'Content-Type: application/json' \ --data-raw '{ "base64": ""$IMAGE_B64"" }'
package sentisight.api.sample;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class App {
    public static void main(String[] args) throws IOException {
        String token = "";
        String projectId = "0";
        String image_b64 = "";
        String[] labels = {"label1", "label2"};
        int limit = 10;
        double threshold = 0;

        StringBuilder paramsString = new StringBuilder();
        for (String label : labels) {
            paramsString.append("&labels=").append(label);
        }
        paramsString.append("&and=true"); // to use 'or' operator for filtering labels remove this line or change it to '&and=false'
        paramsString.append("&limit=").append(limit);
        paramsString.append("&threshold=").append(threshold);

        String body = "{\r\n    \"base64\": \"%s\"\r\n}".formatted(image_b64);

        URL url = new URL("https://platform.sentisight.ai/api/similarity?project=" + projectId + paramsString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("X-Auth-token", token);
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
        wr.writeBytes(body);
        wr.flush();
        wr.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String output;
        while ((output = in.readLine()) != null) {
            System.out.println(output);
        }
        in.close();
    }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>Sample</title>
  <script>
    const baseApiURL = 'https://platform.sentisight.ai/api/';
    let token = '';
    let projectId;

    function similaritySearch() {
      document.getElementById('button').disabled = true;
      token = document.getElementById('tokenfield').value;
      projectId = document.getElementById('project').value;
      const base64 = document.getElementById('base64').value;
      const labelText = document.getElementById('labels').value;
      let labels = [];
      if (labelText.length) {
        labels = labelText.split(',');
      }
      var lstr = '';
      labels.forEach(function(label) {
        lstr += ('&labels=' + label);
      });
      if (document.getElementById('limit-on').checked) {
        lstr += ('&limit=' + document.getElementById('limit').value)
      }
      if (document.getElementById('threshold-on').checked) {
        lstr += ('&threshold=' + document.getElementById('threshold').value)
      }
      if (document.querySelector('input[name="and"]:checked').value == 'true') {
        lstr += '&and=true';
      }
      var xmlHttp = new XMLHttpRequest();
      xmlHttp.open('POST',  baseApiURL + 'similarity?project=' + projectId + lstr, true);
      xmlHttp.setRequestHeader('Content-Type', 'application/json');
      xmlHttp.setRequestHeader('X-Auth-token', token);
      xmlHttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          document.getElementById('button').disabled = false;
          document.getElementById('results').innerHTML = xmlHttp.responseText;
        }
      }
      const data = JSON.stringify({
        base64
      });
      xmlHttp.send(data);
    }

  </script>
</head>
<body>
Token: <input id="tokenfield" type="text">
<br>
Project id: <input id="project" type="number">
<br>
Labels: <input id="labels" type="text">
<br>
<input type="radio" name="and" value="true"> And
<input type="radio" name="and" value="false" checked> Or
<br>
<input id="limit-on" type="checkbox">Result number: <input id="limit" type="number">
<br>
<input id="threshold-on" type="checkbox">Score threshold: <input id="threshold" type="number" step="0.001">
<br>
Base64: <input id="base64" type="text">
<br>
<button id="button" type="button" onclick="similaritySearch()">Perform similarity search</button>
<br>
<table id=results></table>
</body>
</html>
import requests
import json

token = "your_token"
project_id = "your_project_id"
image_b64 = ""
labels = ["your", "labels", "here"]
limit = 10  # limits result count to this number
threshold = 0  # only shows results above this threshold  (value in percent)

payload = json.dumps({
    "base64": image_b64
})

headers = {"X-Auth-token": token, "Content-Type": "application/json"}

request_url = "https://platform.sentisight.ai/api/similarity?project={}".format(project_id)
for lbl in labels:
    request_url += "&labels={}".format(lbl)

request_url += "&and=true"  # to use 'or' operator for filtering labels remove this line or change it to '&and=false'
request_url += "&limit={}".format(limit)
request_url += "&threshold={}".format(threshold)

r = requests.post(request_url, headers=headers, data=payload)

if r.status_code == 200:
    print(r.text)
else:
    print("Error occured with REST API.")
    print("Status code: {}".format(r.status_code))
    print("Error message: " + r.text)
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;

namespace Sample
{
    class Program
    {
        static void Main()
        {
            const string token = "";
            const int projectId = 0;
            const string imageB64 = "";
            string[] labels = {"label1", "label2"};
            const int limit = 10;
            const double threshold = 0;
            
            var labelString = labels.Aggregate("", (current, label) => current + $"&labels={label}");
            // to use 'or' operator for filtering labels remove the next line or change it to 'labelString += ("&and=false");'
            labelString += ("&and=true"); 
            labelString += ("&limit=" + limit);
            labelString += ("&threshold=" + threshold);

            using var ms = new MemoryStream();
            using var writer = new Utf8JsonWriter(ms);
            writer.WriteStartObject();
            writer.WriteString("base64", imageB64);
            writer.WriteEndObject();
            writer.Flush();
            var json = Encoding.UTF8.GetString(ms.ToArray());
            
            var data = new StringContent(json, Encoding.Default, "application/json");

            var uri = new Uri($"https://platform.sentisight.ai/api/similarity?project={projectId}{labelString}");
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("X-Auth-token", token);
            
            var response = client.PostAsync(uri, data);
            var result = response.Result.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }
    }
}

NvN image similarity search

Set the "X-Auth-token" header to your API token string.

TOKEN="your_token"
PROJECT_ID="your_project_id"
FILTER_LABELS="your labels here" # labels should be separated by spaces
AND_OPERATOR="true" # set to "false" to use "or" operator instead for filtering images by labels
LIMIT=10
THRESHOLD=0

LABEL_OP=''
for LABEL in $FILTER_LABELS ; do
  LABEL_OP+="&labels=$LABEL"
done

curl -H "X-Auth-token: $TOKEN" \
  -X GET "https://platform.sentisight.ai/api/similarity?project=$PROJECT_ID$LABEL_OP&and=$AND_OPERATOR&limit=$LIMIT&threshold=$THRESHOLD"
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class App {
    public static void main(String[] args) throws IOException {
        String token = "";
        String projectId = "0";
        String[] labels = {"label1", "label2"};
        int limit = 10;
        double threshold = 0;
        
        String lstr = "";
        for (String label : labels) {
            lstr += ("&labels=" + label);
        }
        lstr += ("&and=true"); // to use 'or' operator for filtering labels remove this line or change it to '&and=false'
        lstr += ("&limit=" + limit);
        lstr += ("&threshold=" + threshold);

        URL url = new URL("https://platform.sentisight.ai/api/similarity?project=" + projectId + lstr);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("X-Auth-token", token);
        connection.setRequestMethod("GET");

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String output;
        while ((output = in.readLine()) != null) {
            System.out.println(output);
        }
        in.close();
    }
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Sample</title>
        <script>
            const baseApiURL = 'https://platform.sentisight.ai/api/';
            var token = '';
            var predictionId;
            var projectId;

            function similaritySearch(input) {
                document.getElementById('button').disabled = true;
                token = document.getElementById('tokenfield').value;
                projectId = document.getElementById('project').value;
                var labelText = document.getElementById('labels').value;
                var labels = [];
                if (labelText.length) {
                    labels = labelText.split(',');
                }
                var lstr = '';
                labels.forEach(function(label) {
                    lstr += ('&labels=' + label);
                });
                if (document.getElementById('limit-on').checked) {
                    lstr += ('&limit=' + document.getElementById('limit').value)
                }
                if (document.getElementById('threshold-on').checked) {
                    lstr += ('&threshold=' + document.getElementById('threshold').value)
                }
                if (document.querySelector('input[name="and"]:checked').value == 'true') {
                    lstr += '&and=true';
                }
                var xmlHttp = new XMLHttpRequest();
                xmlHttp.open('GET',  baseApiURL + 'similarity?project=' + projectId + lstr, true);
                xmlHttp.setRequestHeader('X-Auth-token', token);
                xmlHttp.onreadystatechange = function () {
                    if (this.readyState == 4 && this.status == 200) {
                        document.getElementById('button').disabled = false;
                        document.getElementById('result').innerHTML = xmlHttp.responseText;
                    }
                }
                xmlHttp.send();
            }

        </script>
    </head>
    <body>
        Token: <input id="tokenfield" type="text">
        <br>
        Project id: <input id="project" type="number">
        <br>
        Labels: <input id="labels" type="text">
        <br>
        <input type="radio" name="and" value="true"> And
        <input type="radio" name="and" value="false" checked> Or
        <br>
        <input id="limit-on" type="checkbox">Result number: <input id="limit" type="number">
        <br>
        <input id="threshold-on" type="checkbox">Score threshold: <input id="threshold" type="number" step="0.001">
        <br>
        <button id="button" type="button" onclick="similaritySearch()">Perform similarity search</button>
        <br>
        <table id="result"></table>
    </body>
</html>
import requests

token = "your_token"
project_id = "your_project_id"
labels = ["your", "labels", "here"]
limit = 10  # limits result count to this number
threshold = 0.5  # only shows results above this threshold (value in percent)

headers = {"X-Auth-token": token}

request_url = "https://platform.sentisight.ai/api/similarity?project={}".format(project_id)
for lbl in labels:
    request_url += "&labels={}".format(lbl)

request_url += "&and=true" # to use 'or' operator for filtering labels remove this line or change it to '&and=false'
request_url += "&limit={}".format(limit)
request_url += "&threshold={}".format(threshold)

r = requests.get(request_url, headers=headers)

if r.status_code == 200:
    print(r.text)
else:
    print("Error occured with REST API.")
    print("Status code: {}".format(r.status_code))
    print("Error message: " + r.text)
using System;
using System.Linq;
using System.Net.Http;

namespace Sample
{
    class Program
    {
        static void Main()
        {
            const string token = "";
            const int projectId = 0;
            string[] labels = {"label1", "label2"};
            const int limit = 10;
            const double threshold = 0;
            
            var labelString = labels.Aggregate("", (current, label) => current + $"&labels={label}");
            // to use 'or' operator for filtering labels remove the next line or change it to 'labelString += ("&and=false");'
            labelString += ("&and=true"); 
            labelString += ("&limit=" + limit);
            labelString += ("&threshold=" + threshold);

            var uri = new Uri($"https://platform.sentisight.ai/api/similarity?project={projectId}{labelString}");
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("X-Auth-token", token);
            
            var response = client.GetAsync(uri);
            var result = response.Result.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);
        }
    }
}

SentiSight.ai OpenAPI specification

List of endpoints: https://app.swaggerhub.com/apis-docs/SentiSight.ai/sentisight.

API code samples: https://app.swaggerhub.com/apis/SentiSight.ai/sentisight.

You can try out our REST API interactively and convert Swagger specification to code samples in many different languages.

Using Image Similarity Search offline - setting up your own REST API server

If you want to set up your own REST API server, you will have to download an offline version of Image Similarity Search model. To do that click "Pre-trained models" -> "Image Similarity Search" -> "Download model".

After the model is downloaded, follow the instructions in Readme.html to set up your local REST API server. You can make the client requests from the same PC on which you set up the server, so the model would be run completely offline. On the other hand, after you set up REST API server, you can also make client requests to this server from many different devices (including mobile) on your network. Note that the REST API server must be run on a Linux system, but the client devices can run on any operating system.

The offline version of the model can be run as a free trial for 30 days. After this period, if you like the offline version, you will have to buy a license from us. Note that we have three options for the speed of the offline model: "slow", "medium" and "fast". The license price depends on the selected speed. The free trial always runs on the "fast" speed mode.


Video tutorials

Below you can find a number of video tutorials that are relevant to this topic.

labeling-by-image-similarity-tutorial

Image similarity search tutorial


Topics covered:
  • 1vN similarity search by uploading image
  • 1vN similarity search by choosing an image from your data set
  • NvN similarity search
  • Similarity search history
  • Similarity search via REST api
labeling-by-image-similarity-tutorial

Labeling by image similarity tutorial


Topics covered:
  • Labeling by image similarity feature
  • Changing parameters
  • Adjusting suggested labels manually
  • Performing AI-assisted labeling iteratively
  • Downloading classification labels