Automating Image Processing for Product Images using Python
Tags: python, automation, design
Published: 2023-07-05 17:07:33

In today's digital age, product images play a crucial role in e-commerce and marketing. However, preparing product images for online platforms can be a time-consuming task. In this blog post, I will share a Python script that automates the image processing workflow for product images. By using the Python Imaging Library (PIL) and rembg library, we can remove image backgrounds, crop the images to fit the product dimensions, resize them, and create a new canvas with specific size and color.

**Overview of the Script**
The script we'll be discussing today follows these steps:
1- Remove the image background using the rembg library.
2- Crop the image to include only the product dimensions.
3- Resize the cropped image to a specific size while maintaining the aspect ratio.
4- Create a new canvas with a specified size and color.
5- Paste the resized product image onto the new canvas.

Now, let's dive into the code!

**Dependencies and Installation**
To run the script, you need to have the PIL (Pillow) library and the rembg library installed. You can install them using pip:
`pip install pillow rembg`

**Usage Instructions**
To use the script, follow these steps:
1.Place your product images in the specified folder and subfolders.
2. Update the `folder_dir` variable in the script to point to the folder containing your product images.
3. Run the script using a Python interpreter.

The script will process all the product images inside the folder and its subfolders, applying the image processing steps mentioned earlier. The processed images will be saved with a "_Processed" suffix appended to the original filename.

**Function Explanation**
`append_id(filename)`
```
def append_id(filename):
    p = Path(filename)
    return "{0}_{2}{1}".format(Path.joinpath(p.parent, p.stem), ".png", "Processed")
```
This function appends an ID to the output image filename. It takes the original filename as input and returns a modified filename with the "_Processed" suffix appended. This helps distinguish the processed images from the original ones.

`autocrop_image(img, border=0)`
```
def autocrop_image(img, border=0):
    bbox = img.getbbox()
    img = img.crop(bbox)
    (scale, height) = img.size
    scale += border * 2
    height += border * 2
    cropped_image = Image.new("RGBA", (scale, height), (0, 0, 0, 0))
    cropped_image.paste(img, (border, border))
    return cropped_image
```
This function autocrops an image by removing any unnecessary whitespace or background. It takes an input image `img` and an optional border parameter (default is 0) that adds extra padding around the cropped image. It calculates the bounding box of the image using `img.getbbox()`, crops the image to the contents of the bounding box, and then creates a new image with the appropriate size to accommodate the cropped image along with the border. Finally, it pastes the cropped image onto the new image and returns the resulting cropped image.

`resize_image(img, myScale)`
```
def resize_image(img, myScale):
    img_width, img_height = img.size

    if img_height > img_width:
        hpercent = (myScale/float(img_height))
        wsize = int((float(img_width)*float(hpercent)))
        resized_img = img.resize((wsize, myScale), Image.Resampling.LANCZOS)

    if img_width > img_height:
        wpercent = (myScale/float(img_width))
        hsize = int((float(img_height)*float(wpercent)))
        resized_img = img.resize((myScale, hsize), Image.Resampling.LANCZOS)
    return resized_img
```
This function resizes the image while maintaining the aspect ratio. It takes an input image `img` and a desired scale `myScale`. The function first determines whether the image is in portrait or landscape orientation based on the comparison of its height and width. It then calculates the resized dimensions accordingly, using the desired scale. Finally, it resizes the image using `img.resize()` with the calculated dimensions and returns the resized image.

`resize_canvas(img, canvas_width, canvas_height)`
```
def resize_canvas(img, canvas_width, canvas_height):
    old_width, old_height = img.size
    x1 = int(math.floor((canvas_width - old_width) / 2))
    y1 = int(math.floor((canvas_height - old_height) / 2))
    mode = img.mode
    if len(mode) == 1:
        new_background = (255)
    if len(mode) == 3:
        new_background = (255, 255, 255)
    if len(mode) == 4:
        new_background = (255, 255, 255, 255)
    newImage = Image.new(mode, (canvas_width, canvas_height), new_background)
    newImage.alpha_composite(
        img, ((canvas_width - old_width) // 2, (canvas_height - old_height) // 2))
    return newImage
```
This function resizes the canvas and places the image on it. It takes an input image `img`, canvas width `canvas_width`, and canvas height `canvas_height`. The function calculates the necessary positioning to center the image on the canvas based on the difference between the canvas dimensions and the image dimensions. It then creates a new image with the specified canvas dimensions and the appropriate background color based on the image mode. Finally, it pastes the input image onto the new image at the calculated position and returns the resulting image with the resized canvas.

`process_files(folder_dir)`
```
def process_files(folder_dir):
    for entry in os.scandir(folder_dir):
        if entry.is_file() and entry.name.lower().endswith(image_extensions):
            image_path = entry.path
            img = Image.open(image_path)
            output_path = append_id(image_path)
            removedBGimage = remove(img, True)
            croppedImage = autocrop_image(removedBGimage, 0)
            resizedImage = resize_image(croppedImage, 700)
            combinedImage = resize_canvas(resizedImage, 1000, 1000)
            combinedImage.save(output_path)
        elif entry.is_dir():
            process_files(entry.path)
```
This function processes the files inside the specified folder and its subfolders. It takes the `folder_dir` as input. It iterates through each entry in the folder using `os.scandir()`. If the entry is a file and has a supported image extension, it opens the image using `Image.open()`. It then generates the output path by calling the `append_id()` function, removes the image background using the `remove()` function from the rembg library, autocrops the image, resizes it, creates a new canvas, and finally saves the processed image to the output path. If the entry is a directory, it recursively calls the `process_files()` function to process the files inside the subdirectory.

**Conclusion**
In this blog post, we explored a Python script that automates image processing for product images. By leveraging the power of PIL and rembg, we can remove image backgrounds, crop images, resize them, and create new canvases for a polished and professional look. By automating this workflow, we can save time and effort in preparing product images for various e-commerce and marketing platforms.

You can find the complete script and additional details in the [GitHub repository](https://github.com/elanoz/pythonAutomation-Scripts/blob/main/ProcessProductImages.py).

I hope you find this script helpful in streamlining your image processing tasks. Happy automating!