How to process images from a local directory

A common use case for the Remove Background API is to process a large amount of images, which are stored in a local directory.

In this tutorial, we'll see how it's possible to process these images by integrating the Remove Background API with a Python script.

This tutorial takes example of processing images through the Remove Background API, but this approach would also work with our other APIs that accept a POST HTTP call: the Generate Background API and the Image Editing API Legacy.

Step 1: Calling the Remove Background API

First, we'll write a function that can process a local image through the Remove Background API and save the result image returned by the API to the disk:

import requests

API_KEY = "REPLACE_WITH_YOUR_API_KEY"

def process_image(input_image_path, output_image_path):
    try:
        url = "https://sdk.photoroom.com/v1/segment"

        with open(input_image_path, 'rb') as image_file:
            files = { "image_file": image_file }

            headers = {
                "Accept": "image/png, application/json",
                "x-api-key": API_KEY
            }

            response = requests.post(url, files=files, headers=headers)
            response.raise_for_status()

            with open(output_image_path, 'wb') as f:
                f.write(response.content)
                print(f"Image downloaded and saved to {output_image_path}")

    except requests.RequestException as e:
        print(f"Error: {str(e)}")
        return str(e)

This code is pretty straightforward:

  1. it opens the image stored at input_image_path

  2. uses the requests library to make the POST HTTP call to the API

  3. saves the result image at output_image_path

Notice that you will need to update the value of the constant API_KEY with your own API key.

If you don't have an API key, here are the steps to create yours.

Step 2: Iterating over a local directory

Now that we have a function to process a single image, the next step is to iterate over all the images stored in a local directory and call process_image() for each of them.

import concurrent.futures
import os

def iterate_over_directory(input_directory_path, result_directory_path):
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        for root, _, files in os.walk(input_directory_path):
            for file in files:
                file_path = os.path.join(root, file)

                result_file_name = os.path.splitext(os.path.basename(file_path))[0] + '.png'
                result_path = os.path.join(result_directory_path, result_file_name)

                if not os.path.exists(result_path): # don't re-process images 
                    executor.submit(process_image, file_path, result_path)     

This time the code is a bit more complex, but here are its important steps:

  1. we iterate over the files inside the directory at input_directory_path

  2. then for each file we:

    1. compose the result_path where the result image will be saved

    2. check that a file doesn't already exist at result_path (so as to not process the same image twice)

    3. call the function process_image() through an executor, which allows us to execute 4 API calls in parallel

If you want, you can increase the value of the argument max_workers to run more API calls in parallel. Keep in mind though that the API is rate limited to 500 calls/minutes.

Step 3: Running the script

We're almost there, the last thing we need is to actually run the script.

To do this we'll add this final piece of code:

if __name__ == "__main__":
    INPUT_DIRECTORY = "./input/"
    OUTPUT_DIRECTORY = "./output/"

    if not os.path.exists(OUTPUT_DIRECTORY):
        os.makedirs(OUTPUT_DIRECTORY)

    iterate_over_directory(input_directory_path=INPUT_DIRECTORY, result_directory_path=OUTPUT_DIRECTORY)

Here we set the constants INPUT_DIRECTORY and OUTPUT_DIRECTORY to the paths of respectively:

  • the directory where the input images are stored

  • the directory where we want to save the result images.

Then all that's left is to actually run the script using the terminal:

$ pip install requests # run once to install the library `requests`
$ python script.py

Conclusion

In this tutorial, we saw how to use a Python script to easily process images stored locally with the Photoroom API.

We took the example of processing images through the Remove Background API, but this approach would also work with our other APIs that accept a POST HTTP call: the Generate Background API and the Edit Image API Legacy.

Download the code sample

Here's the entire code sample, if you want to easily save it to a file:

import concurrent.futures
import os
import requests

API_KEY = "REPLACE_WITH_YOUR_API_KEY"

def process_image(input_image_path, output_image_path):
    try:
        url = "https://sdk.photoroom.com/v1/segment"

        with open(input_image_path, 'rb') as image_file:
            files = { "image_file": image_file }

            headers = {
                "Accept": "image/png, application/json",
                "x-api-key": API_KEY
            }

            response = requests.post(url, files=files, headers=headers)
            response.raise_for_status()

            with open(output_image_path, 'wb') as f:
                f.write(response.content)
                print(f"Image downloaded and saved to {output_image_path}")

    except requests.RequestException as e:
        print(f"Error: {str(e)}")
        return str(e)
    
def iterate_over_directory(input_directory_path, result_directory_path):
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
        for root, _, files in os.walk(input_directory_path):
            for file in files:
                file_path = os.path.join(root, file)

                result_file_name = os.path.splitext(os.path.basename(file_path))[0] + '.png'
                result_path = os.path.join(result_directory_path, result_file_name)

                if not os.path.exists(result_path): # don't re-process images 
                    executor.submit(process_image, file_path, result_path)    

if __name__ == "__main__":
    INPUT_DIRECTORY = "./input/"
    OUTPUT_DIRECTORY = "./output/"

    if not os.path.exists(OUTPUT_DIRECTORY):
        os.makedirs(OUTPUT_DIRECTORY)

    iterate_over_directory(input_directory_path=INPUT_DIRECTORY, result_directory_path=OUTPUT_DIRECTORY)

Last updated