Download notebook · View source · Open in Colab
Work with Images
An Image stores image data together with metadata properties. ApertureDB can filter images by those properties and return their bytes. This example adds a food photograph, retrieves and updates its metadata, and deletes it.
The examples require Python 3.10 or later, an ApertureDB connection profile or environment credentials, and permission to create, read, update, and delete objects. A unique documentation_run property separates the example data from other records. Cleanup uses that value, so keep the setup variables available until cleanup completes.
Connect to ApertureDB
ApertureDB Cloud The SDK connects with an API key from your Cloud instance. Obtain the key from Connect > Generate API Key and add it to a .env file in this directory:
APERTUREDB_KEY=your_key_here
Local evaluation: follow the deployment guide, then configure your connection profile.
%pip install --quiet "aperturedb==0.5.1" "python-dotenv==1.1.1"
Note: you may need to restart the kernel to use updated packages.
# Option A: ApertureDB Cloud
from dotenv import load_dotenv
load_dotenv() # loads APERTUREDB_KEY from .env into the environment
False
# For local evaluation, configure the profile from your versioned deployment package.
# https://docs.aperturedata.io/administration/deployment/DockerCompose
from aperturedb.CommonLibrary import create_connector
client = create_connector()
import uuid
documentation_run = uuid.uuid4().hex
ingredient_class = "CookbookIngredient_" + documentation_run
connection_class = "CookbookIngredientLink_" + documentation_run
def checked_query(query, input_blobs=None):
response, output_blobs = client.query(query, input_blobs or [])
assert isinstance(response, list) and len(response) == len(query), response
for command in response:
result = next(iter(command.values()))
assert result.get("status") == 0, response
return response, output_blobs
response, _ = checked_query([{"GetStatus": {}}])
client.print_last_response()
[
{
"GetStatus": {
"info": "OK",
"status": 0,
"system": "ApertureDB",
"version": "0.19.15"
}
}
]
Create or Add an Image of a Dish to ApertureDB
AddImage stores the supplied photograph with properties describing the dish. The image bytes accompany the JSON command as an input blob.
The Python SDK loaders handle bulk ingestion.
# Download the sample file needed in this example
from pathlib import Path
from urllib.request import urlopen
import hashlib
fixture_path = Path("data/focaccia_brittany.jpg")
fixture_path.parent.mkdir(exist_ok=True)
fixture_url = "https://raw.githubusercontent.com/aperture-data/Cookbook/e333f6c59070b9165033d9ddd5af852a6b9624ba/notebooks/simple/data/focaccia_brittany.jpg"
fixture_sha256 = "4b104ba601ab3bf1126579e9dc795842551fc25be9ab2640795da2fb461f7061"
if not fixture_path.exists() or hashlib.sha256(fixture_path.read_bytes()).hexdigest() != fixture_sha256:
with urlopen(fixture_url, timeout=60) as response:
fixture_path.write_bytes(response.read())
assert hashlib.sha256(fixture_path.read_bytes()).hexdigest() == fixture_sha256
print("Verified fixture:", fixture_path.name)
Verified fixture: focaccia_brittany.jpg
query = [{
"AddImage": {
# Notice the missing "class" property since we already know its an Image (represented as _Image in ApertureDB)
"properties": {
'documentation_run': documentation_run,
"name": "Focaccia",
"id": 35,
"contributor": "Vishakha",
"category": "starter",
"cuisine": "Italian",
"location": "Brittany",
"caption": "fresh made focaccia with herbs from the garden"
},
"if_not_found": ['all', ['$id', '==', 35], ['$documentation_run', '==', documentation_run]]
}
}]
# Read the image data as a binary blob
fd = open("data/focaccia_brittany.jpg", 'rb')
image_arr = [ fd.read() ]
fd.close()
response, blobs = checked_query(query, image_arr)
client.print_last_response()
[
{
"AddImage": {
"status": 0
}
}
]
Query image by its metadata attributes
FindImage selects the photograph by its metadata and returns its property values.
from IPython.display import Image, display
query = [{
"FindImage": {
"constraints": ['all', ['all', ['$name', '==', 'Focaccia'], ['$location', '>', 'A']], ['$documentation_run', '==', documentation_run]],
"blobs": True, # This is set to False by default
"results": {
"all_properties": True
}
}
}]
response, blobs = checked_query(query)
client.print_last_response()
for image_blob in blobs:
display(Image(data=image_blob))
assert response[0]["FindImage"]["returned"] == 1
assert response[0]["FindImage"]["entities"][0]["name"] == "Focaccia"
assert len(blobs) == 1 and blobs[0]
[
{
"FindImage": {
"blobs_start": 0,
"entities": [
{
"_blob_index": 0,
"_uniqueid": "10.2.1160",
"caption": "fresh made focaccia with herbs from the garden",
"category": "starter",
"contributor": "Vishakha",
"cuisine": "Italian",
"documentation_run": "52f2248299804531b551f6658fa4b3c3",
"id": 35,
"location": "Brittany",
"name": "Focaccia"
}
],
"returned": 1,
"status": 0
}
}
]

Update properties of the image already in ApertureDB
UpdateImage changes existing metadata values or adds properties to matching images.
query = [{
"UpdateImage": {
"properties": {
"recipe_url": "https://www.allrecipes.com/recipe/23451/fantastic-focaccia-bread/" # property will get added if missing or the value will be updated
},
"constraints": ['all', ['$name', '==', 'Focaccia'], ['$documentation_run', '==', documentation_run]],
}
}]
response, blobs = checked_query(query)
client.print_last_response()
[
{
"UpdateImage": {
"count": 1,
"status": 0
}
}
]
query = [{
"FindImage": {
"constraints": ['all', ['$name', '==', 'Focaccia'], ['$documentation_run', '==', documentation_run]],
"results": {
"all_properties": True
}
}
}]
response, blobs = checked_query(query)
client.print_last_response()
assert response[0]["FindImage"]["entities"][0]["recipe_url"].startswith("https://")
[
{
"FindImage": {
"entities": [
{
"_uniqueid": "10.2.1160",
"caption": "fresh made focaccia with herbs from the garden",
"category": "starter",
"contributor": "Vishakha",
"cuisine": "Italian",
"documentation_run": "52f2248299804531b551f6658fa4b3c3",
"id": 35,
"location": "Brittany",
"name": "Focaccia",
"recipe_url": "https://www.allrecipes.com/recipe/23451/fantastic-focaccia-bread/"
}
],
"returned": 1,
"status": 0
}
}
]
Delete the image
DeleteImage removes the image selected by its metadata and this run's identifier.
query = [{
"DeleteImage": {
"constraints": ['all', ['$name', '==', 'Focaccia'], ['$documentation_run', '==', documentation_run]]
}
}]
response, blobs = checked_query(query)
client.print_last_response()
[
{
"DeleteImage": {
"count": 1,
"status": 0
}
}
]
Verify deletion
After deletion, the same image query returns no matches.
query = [{
"FindImage": {
"constraints": ['all', ['$name', '==', 'Focaccia'], ['$documentation_run', '==', documentation_run]],
"results": {
"all_properties": True
}
}
}]
response, blobs = checked_query(query)
client.print_last_response()
assert response[0]["FindImage"]["returned"] == 0
[
{
"FindImage": {
"returned": 0,
"status": 0
}
}
]
What's next?
- Bulk load images
- Add embeddings or regions of interest to ApertureDB