API

Using API you can:

  • create/delete/update collections
  • upload and delete images
  • search through collections using filters . Note: right now public collections do not require JWT token.

Let’s start

You can play with publicly available at https://app.khumbu.im/public .

First of all, you need to create account at https://app.khumbu.im/signup
After that you can login and create your first collection.

You need to get JWT token to work with private data:

import imghdr
import io
import json
import shutil
import requests

valid_credentials = {
     "email": "your@username.com",
     "password": "your_password",
}

ROOT_URL = "https://api-facade.khumbu.im"

JWT_CREATE_URL = ROOT_URL + '/auth/jwt/create'
JWT_VERIFY_URL = ROOT_URL + '/auth/jwt/verify'
JWT_REFRESH_URL = ROOT_URL + '/auth/jwt/refresh'
AUTH_USERS_URL = ROOT_URL + '/auth/users/'


def get_tokens():
    resp = requests.post(url=JWT_CREATE_URL, json=valid_credentials)
    return resp.json()


def get_auth_headers():
    return {"Authorization": "Bearer %s" % get_tokens()["access"]}


Image Uploading and Indexing

Each collection has unique id:

Below we are sending image some_file.jpg to newly created collection with id 5e05289d6483e25b40e161c7. It’s possible to send many files in one request. Max file size is 5mb, max size of request – 15mb.

UPLOADER_URL_ID = ROOT_URL + '/image_uploader/%s'

# max file size - 5mb
def send_one_file(collection_id, filepath):
    files = {'file_1': open(filepath, 'rb')}

    url = UPLOADER_URL_ID % collection_id
    resp = requests.post(url, files=files, headers=get_auth_headers())
    return resp

print(send_one_file("5e05289d6483e25b40e161c7","some_file.jpg"))

Please, keep in mind, that right now indexing is disabled (GPUs are really expensive!). If you want to play with private collection, drop us a letter.

Image Search

You can search though any of public collections – just do not send any auth headers.

Images can be filtered by:

filter descriptionnamevalue
tags or objects for imagetextcat tree person
number of facesfaces.count[0, 1000]
nudity scorensfw_score[0, 1]
height of imageheight[200, 3000]
width of imagewidth[300, 3000]
aperture (exif)aperture[1, 32]
exposure value (exif)exposure[0.00025, 20]
focal length (exif)focal_length[5, 600]
ISO (exif)iso[25, 12800]
year (exif)date_year[2000, 2020]
month (exif)date_month[1, 12]
day of week (exif)date_weekday[1, 7]
hour (exif)date_hour[0, 23]
# example with all possible filters
all_filters = {"text": "cat",
               "faces.count": [0, 25],
               "nsfw_score": [0, 1],
               "height": [50, 10000],
               "width": [50, 10000],
               "aperture": [1, 32],
               "exposure": [0.00025, 20],
               "focal_length": [5, 600],
               "iso": [25, 12800],
               "date_year": [2000, 2020],
               "date_month": [1, 12],
               "date_weekday": [1, 7],
               "date_hour": [0, 23],
               "date_range": [25, 12800]
               }

So let’s find something!

########## search =======================
SEARCH_URL = ROOT_URL + "/search?collection_id=%s&page=%s&per_page=%s&query=%s"
IMAGE_URL = ROOT_URL + "/get_image?imageinfo_id=%s&type=%s"


def search(collection_id, query, page, per_page):
    url = SEARCH_URL % (collection_id, page, per_page, json.dumps(query))
    resp = requests.get(url)
    return resp.json()


def get_image(imageinfo_id, image_size):
    image_url = IMAGE_URL % (imageinfo_id, image_size)
    print("getting image %s" % image_url)
    resp = requests.get(image_url)

    image_obj = io.BytesIO(resp.content)

    ext = imghdr.what(image_obj)
    image_obj.seek(0)
    with open(imageinfo_id + "." + ext, 'wb') as out_file:
        shutil.copyfileobj(image_obj, out_file)


search_results = search("5dff72e66483e25b40e0222e", {"text": "tree"}, 1, 10)
for idx, result in enumerate(search_results):
    iamgeinfo_id = result["id"]
    print(idx, iamgeinfo_id)
    # orignal. preview, small
    get_image(iamgeinfo_id, "small")

all_filters = {"text": "cat",
               "faces.count": [0, 25],
               "nsfw_score": [0, 1],
               "height": [50, 10000],
               "width": [50, 10000],
               "aperture": [1, 32],
               "exposure": [0.00025, 20],
               "focal_length": [5, 600],
               "iso": [25, 12800],
               "date_year": [2000, 2020],
               "date_month": [1, 12],
               "date_weekday": [1, 7],
               "date_hour": [0, 23],
               }

Examples

Gist https://gist.github.com/hudvin/cdceb01d7e9a4ceb4639bf6e53139017