DEV Community

loading...
Cover image for Learn How to Add Object Detection Capabilities to Your Appwrite Storage Using Cloud Functions
Appwrite

Learn How to Add Object Detection Capabilities to Your Appwrite Storage Using Cloud Functions

Christy Jacob
・6 min read

In this tutorial, we will cover how we can leverage Appwrite’s Cloud functions feature to execute certain tasks when certain events take place in the server. You can find a complete list of available system events here.

In this example, we will demonstrate how we can detect objects in an image that the user has uploaded. This could be useful if you’re building something like google photos where you would like to categorize photos based on objects in the image.

For the sake of this example, we will be using Cloudmersive's People and Object Detection API. A similar concept applies to other API providers like Google’s Vision API or Amazon’s Recognition API. So let’s get started.

Create your Cloud Function

The first step is to create a Cloudmersive account and obtain the free tier API Key. Now it's time to create your Cloud Function in the Appwrite Console. Head over to the Functions section of your console and select Add Function. You can give your function a funky new name and select the preferred environment. We will be using Python for this example.

Add Function Dialog

Let's write some code

The next step is to write the code that will be executed and upload it. Create a directory to hold your Cloud Function. Then create your main code file and a requirements.txt.

$ mkdir cloud-functions-demo
$ cd cloud-functions-demo
$ touch main.py
$ touch requirements.txt
Enter fullscreen mode Exit fullscreen mode

We will be using two dependencies for this example

  1. cloudmersive-image-api-client
  2. appwrite

Add these to your requirements.txt. We would typically perform a pip install at this stage but that would install the libraries in the shared libraries path. We need the libraries to be installed in the same folder so that they can be packaged easily.

Run the following command to install the libraries inside the local .appwrite directory. Appwrite’s Python environment will know how to autoload a file from that directory without any special configuration.

PIP_TARGET=./.appwrite pip install -r ./requirements.txt --upgrade --ignore-installed
Enter fullscreen mode Exit fullscreen mode

Great. It’s time to start editing the main.py file. We start by importing the relevant libraries.

from __future__ import print_function
import time
from pprint import pprint
import json 
import os

# For cloud vision API
import cloudmersive_image_api_client
from cloudmersive_image_api_client.rest import ApiException

# Appwrite SDK
from appwrite.client import Client
from appwrite.services.storage import Storage
Enter fullscreen mode Exit fullscreen mode

We will use a temporary file to access the image during the function execution. Let’s give this file a name. This is required because the Cloudmersive library expects a file path and not binary data as input.

FILENAME = "temp.jpg"
Enter fullscreen mode Exit fullscreen mode

When a function is triggered by an event, we can obtain a lot of metadata about the event from some special environment variables that are set by Appwrite. A complete list is available here. In our case, we need the ID of the file that was uploaded in order to fetch it. Appwrite conveniently exposes this information as an environment variable named APPWRITE_FUNCTION_EVENT_PAYLOAD. Let’s parse this JSON string to retrieve the file ID.

# Triggered by the storage.files.create event
payload = json.loads(os.environ["APPWRITE_FUNCTION_EVENT_PAYLOAD"])
fileID = payload["$id"]
Enter fullscreen mode Exit fullscreen mode

Now it’s time to set up the Appwrite SDK

# Setup appwrite client
client = Client()
client.set_endpoint('http://192.168.1.6/v1') # PRIVATE IP OF YOUR APPWRITE CONTAINER
client.set_project('5fca866c65afc') # YOUR PROJECT ID
client.set_key(os.environ["APPWRITE_KEY"])
Enter fullscreen mode Exit fullscreen mode

Note: Within the Cloud Function, you cannot use localhost to refer to your Appwrite server, because localhost refers to your own runtime environment. You will have to find the private IP of your default network interface using ifconfig (usually eth0 in linux or en0 in macOS).

Using the SDK, lets fetch the image and save it:

# Get the image file 
storage = Storage(client)
result = storage.get_file_preview(fileID)

# Save the file to the container
with open(FILENAME, "wb") as newFile:
    newFile.write(result)
Enter fullscreen mode Exit fullscreen mode

We’re almost done. Now we will set up the Cloudmersive SDK and make our API request

# Configure API key authorization: Apikey
configuration = cloudmersive_image_api_client.Configuration()
configuration.api_key['Apikey'] = os.environ['API_KEY']

# create an instance of the API class
api_instance = cloudmersive_image_api_client.RecognizeApi(cloudmersive_image_api_client.ApiClient(configuration))
image_file = FILENAME # file | Image file to perform the operation on.  Common file formats such as PNG, JPEG are supported.

try:
    # Detect objects including types and locations in an image
    api_response = api_instance.recognize_detect_objects(image_file)
    pprint(api_response)
except ApiException as e:
    print("Exception when calling RecognizeApi->recognize_detect_objects: %s\n" % e)
Enter fullscreen mode Exit fullscreen mode

Packaging the Cloud function

Before we can package our cloud function, we need to ensure that our directory has the following structure.

.
├── .appwrite/
├── main.py
└── requirements.txt
Enter fullscreen mode Exit fullscreen mode

We package the function by creating a tar file out of our folder.

$ cd ..
$ tar -zcvf code.tar.gz cloud-functions-demo
Enter fullscreen mode Exit fullscreen mode

We can now upload this tarfile to our function’s dashboard by selecting the Deploy Tag option. Our entry point command, in this case, would be:

$ python main.py
Enter fullscreen mode Exit fullscreen mode

Note: You can also automate the code upload process using the Appwrite server SDK latest version and your CI server. In future versions, Appwrite will also support this process using a dedicated CLI tool, directly from your terminal.

Deploy Tag

Once created, we need to define a trigger for the function. In our case, we wish to trigger it whenever a new file is uploaded to the Appwrite server. So we would be interested in the storage.files.create event. The trigger can be enabled under the Settings tab of the function.

Function Settings

Once the triggers are enabled, it’s time for our final step, Function Variables. Appwrite allows you to securely store secret keys using Appwrite Function Variables which will be available as environment variables to your program. The best part is that these keys are encrypted and stored securely on Appwrite’s internal DB. In this example, we have used two environment variables namely API_KEY (Cloudmersive API Key) and APPWRITE_KEY (Appwrite API Key) so let’s add them to the Function Variables. Don’t forget to click the Update option once you’re happy with your settings.

Great! We’re done with all the setup. All that’s left now is to test the Cloud Function.

Testing

Now it’s time to test your shiny new Cloud Function! Head over to the Storage section of Appwrite and create a new file by clicking on the ‘+’ button at the bottom right. Choose an image of your choice and click Create.

Upload File

Your Cloud Function would now have been triggered. You can check it out by heading over to Functions > Your Function Name > Logs

Execution Logs

Once the execution is complete, you can check the response from the API.

API Response

And in a few simple steps, we successfully deployed our first Cloud Function. The possibilities with Cloud Functions are endless! Stay tuned for more Cloud Function ideas from the Appwrite Team.

Learn More

Credits

Photo by Arseny Togulev on Unsplash

Discussion (1)

Collapse
kohsheen1234 profile image
Kohsheen Tiku

This is some really cool stuff 🥳🤯