Sign In

Automating Image Resizing for Hypernetwork/LoRA Training

6

Automating Image Resizing for Hypernetwork/LoRA Training

Overview

  • You'll need square images to start.

  • Below is Python code you can save to a .py file to automatically resize and pad your images to make them square.

  • You may already have a program that does this, but this is a simple, customizable solution if you don't. I've tested the code, and it works!

Supported Image Formats:

The script supports only .png, .jpg, and .jpeg image formats. It will search for these file types in the bin folder. Ensure that your images are saved in one of these formats.

If your images are in a different format, you can easily convert them using tools like birme.net for resizing and saving them to a supported format.

Requirements:

  • Python IDE: Ensure that you have a Python environment set up. You can use any Python IDE like VSCode, PyCharm, or even the terminal.

  • Install Python and Pillow: If you haven’t already, install the Pillow library for image manipulation. Run this command in the terminal:

    pip install pillow

  • Create a Python Script: Save the code below into a .py file.

  • Folder Setup: Either place the script in the same folder as your images or specify the image path in the script.

  • Run the Script: Open a terminal and run the script using python filename.py (where filename.py is the name of your Python file).

Assumptions:

This Python script assumes the following:

  1. Images that need to be resized are stored in a folder named bin.

  2. The Python script is in the same directory as the bin folder.

What This Script Does:

  1. It searches through the folder named bin for images with the .png, .jpg, or .jpeg extensions.

  2. It checks the horizontal and vertical dimensions of each image and adds padding to make the image square, centering it within the new square dimensions.

  3. The script saves the padded images in a new folder called bin_2. If bin_2 already exists, the script will create bin_3, bin_4, and so on.

  4. After saving the padded images, if the copy_delete option is enabled in the batch file (1 = enabled, 0 = disabled):

    • It will copy the original files and folders from bin to a folder named originals, overwriting any existing files with the same name.

    • After copying, it deletes the original files from bin.

    • It ensures that all images inside subfolders are moved, and then it removes the empty subfolders.

    • It maintains file and folder hierarchy when copying into both the originals folder and the bin folder.

  5. Empty bin Folder Check:

    The script checks if the bin folder contains any images before processing. If the folder is empty, it will display a message:
    "The bin folder is empty. Please add images."
    Once this message is shown, the script will terminate without creating any new folders or performing further actions.

Running the Code:

  1. Copy and paste the Python code into a .py file (e.g., resizer.py).

  2. To run the code:

    • Open a terminal or command prompt.

    • Navigate to the folder containing the script (or open the command prompt directly in the folder by typing cmd.exe in the explorer bar).

    • Run the script by typing: python resizer.py

Automating with a Batch File:

To simplify this process for future runs, you can create a batch file with the following code and save it as a .bat file. This will automatically execute the script with your chosen options when double-clicked.

In the batch file, you can customize:

  • Color: Set the padding color using standard color names (e.g., red, blue, white) or RGB/HEX formats.

  • Copy/Delete Option: Enable or disable copying images to the originals folder and deleting them from the bin folder.

Here’s an example of what your batch file could look like:

@echo off 

REM Set the desired padding color (e.g., 'red', '#ff0000', or '255,0,0') 

SET COLOR=white 

REM Set the option to enable or disable copying to 'originals' and deleting from 'bin' (1 to enable, 0 to disable) 

SET COPY_DELETE=1 

REM Run the Python script with the color and copy_delete options 

python resizer.py --color %COLOR% --copy_delete %COPY_DELETE% pause

The Code - with color options

(indentation matters - copy and paste between the ``` into a text editor and save it as a .py file)

```
import os
import argparse
import shutil  # To copy files
from PIL import Image, ImageOps

# Parse command-line arguments
parser = argparse.ArgumentParser(description="Image Resizer with Custom Padding Color and Optional File Copy/Delete")
parser.add_argument('--color', type=str, default='white', help="Padding color (e.g., 'white', 'black', 'red') or RGB tuple like '255,0,0' for red.")
parser.add_argument('--copy_delete', type=int, default=0, help="Set to 1 to enable copying to 'originals' and deleting from 'bin', 0 to disable.")
parser.add_argument('--delete_empty_folders', type=int, default=0, help="Set to 1 to delete empty folders if no images are detected, 0 to disable.")
args = parser.parse_args()

# Convert color input to RGB if necessary
def parse_color(color_string):
    if ',' in color_string:
        return tuple(map(int, color_string.split(',')))  # Convert '255,0,0' to (255, 0, 0)
    return color_string  # Return color name like 'white', 'black', etc.

# Get the padding color from the command-line arguments
padding_color = parse_color(args.color)

# Path to the folder containing the original images
image_folder = './bin'
originals_folder = './originals'  # Define originals_folder here to be accessible throughout

# Function to create a new folder with incremental names like bin_2, bin_3, etc.
def create_output_folder(base_name='bin_2'):
    folder_name = base_name
    counter = 2
    # Increment the folder name if one already exists
    while os.path.exists(folder_name):
        counter += 1
        folder_name = f'bin_{counter}'
    os.makedirs(folder_name)  # Create the new folder
    return folder_name

# Check if there are any images in the bin folder and its subfolders
image_files = []
for root, dirs, files in os.walk(image_folder):
    for filename in files:
        if filename.endswith(('.png', '.jpg', '.jpeg')):
            image_files.append(os.path.join(root, filename))

# If no images are found, handle the situation based on the --delete_empty_folders argument
if not image_files:
    if args.delete_empty_folders == 1:
        # Remove all empty folders
        for root, dirs, files in os.walk(image_folder, topdown=False):
            for dir in dirs:
                dir_path = os.path.join(root, dir)
                try:
                    os.rmdir(dir_path)  # Only removes if the directory is empty
                    print(f"Removed empty folder: {dir_path}")
                except OSError:
                    pass  # Skip non-empty directories
        print("No images detected. Empty folders have been removed.")
    else:
        print("No images detected. No folders were removed. Please add images.")
    exit()

# Create a new output folder for the processed images
output_folder = create_output_folder()

# Recursively process images inside the bin folder and subfolders
for image_path in image_files:
    # Determine the relative folder structure for output
    root = os.path.dirname(image_path)
    relative_path = os.path.relpath(root, image_folder)
    output_subfolder = os.path.join(output_folder, relative_path)
    
    if not os.path.exists(output_subfolder):
        os.makedirs(output_subfolder)
    
    # Process the image
    filename = os.path.basename(image_path)
    image = Image.open(image_path)
    width, height = image.size
    
    # Calculate padding to make the image square
    if width < height:
        padding = ((height - width) // 2, 0, (height - width) // 2, 0)  # Pad width
    else:
        padding = (0, (width - height) // 2, 0, (width - height) // 2)  # Pad height

    # Add padding to the image to make it square
    padded_image = ImageOps.expand(image, padding, fill=padding_color)

    # Save the padded image in the corresponding output subfolder
    output_image_path = os.path.join(output_subfolder, filename)
    padded_image.save(output_image_path)
    print(f'Processed and saved padded image: {filename} in folder {output_subfolder}')

# Check if the copy/delete option is enabled
if args.copy_delete == 1:
    # After processing, copy the original files to the 'originals' folder
    for image_path in image_files:
        root = os.path.dirname(image_path)
        relative_path = os.path.relpath(root, image_folder)
        originals_subfolder = os.path.join(originals_folder, relative_path)
        
        if not os.path.exists(originals_subfolder):
            os.makedirs(originals_subfolder)
        
        # Copy and then delete the file
        filename = os.path.basename(image_path)
        shutil.copy(image_path, os.path.join(originals_subfolder, filename))
        print(f'Copied {filename} to {originals_subfolder}')
        os.remove(image_path)
        print(f'Deleted {filename} from {image_path}')

    # Remove empty folders after deleting files
    for root, dirs, files in os.walk(image_folder, topdown=False):  # Walk bottom-up to remove empty directories
        for dir in dirs:
            dir_path = os.path.join(root, dir)
            try:
                os.rmdir(dir_path)  # Only removes if the directory is empty
                print(f'Removed empty folder: {dir_path}')
            except OSError:
                pass  # If the folder is not empty, skip it



```

The .BAT File

@echo off

REM Set the desired padding color

REM To set a color, either use a standard color name such as red, black, white, blue, green, etc., or use the formats below.

REM For a full list of supported colors, visit:

REM https://pillow.readthedocs.io/en/stable/reference/ImageColor.html

REM You can use RGB (e.g., 255,0,0), RGBA (e.g., 255,0,0,128), HEX (e.g., #ff0000), or HEX with opacity (e.g., #ff0000cc, where 'cc' is 204 in decimal, representing 80% opacity).

REM Pillow accepts one-word color names (e.g., black, red, brown, purple, green, white).

REM For custom colors, use the following formats:

REM - RGB: 0,0,0 (values between 0-255 for red, green, and blue)

REM - HEX: #RRGGBB or #RRGGBBAA, where 'AA' represents opacity

REM Below are examples of valid color formats you can use:

REM SET COLOR=#ff0000 (Hex for red)

REM SET COLOR=#ff0000cc (Hex for red with 80% opacity)

REM SET COLOR=255,0,0 (RGB for red)

REM SET COLOR=white (Standard color name)

REM If the color format is incorrect, the script will not execute properly, and an empty folder may be created.

REM Set the desired padding color

REM Change to any color or RGB values like '255,0,0'

SET COLOR=white

REM Set the option to enable or disable copying to originals and deleting from bin (1 to enable, 0 to disable)

REM Set to 1 to enable, 0 to disable

SET COPY_DELETE=1

REM Run the Python script and pass the color option and the copy_delete flag


REM Set the option to delete empty folders if no images are detected (1 to enable, 0 to disable)
SET DELETE_EMPTY_FOLDERS=1

REM Run the Python script with the color, copy_delete, and delete_empty_folders options
python resizer.py --color %COLOR% --copy_delete %COPY_DELETE% --delete_empty_folders %DELETE_EMPTY_FOLDERS%

pause

About the Colors supported

  • Pillow Documentation: For more details on color formats supported by Pillow, you can refer to the official documentation: Pillow Color Documentation

  • One-Word Colors: Pillow supports basic one-word color names like white, red, black, green, etc.

  • RGB Colors: If you want more precise colors, you can use RGB values. RGB stands for Red, Green, Blue, and each value ranges from 0 to 255. For example, RGB(0, 255, 0) represents pure green, where 255 is the maximum intensity for a color channel.

  • Hexadecimal Colors: You can also use hexadecimal color codes, which are commonly used in web development. For example, #ff0000 is red, where ff represents maximum intensity for the red channel.
    You can find a list of common hexadecimal colors here:
    Hexadecimal Colors

  • Where to Set the Color in the .BAT File:
    In the .BAT file, find the line that says:

    SET COLOR=

    This is where you specify your desired color. You can set it to any valid one-word color, RGB value, or hexadecimal code.

  • Common Two-Word Colors and RGB Values:

    Color Name RGB Values

    Light Blue (173, 216, 230)

    Dark Blue (0, 0, 139)

    Light Green (144, 238, 144)

    Dark Green (0, 100, 0)

    Light Gray (211, 211, 211)

    Dark Gray (169, 169, 169)

    Light Yellow (255, 255, 224)

    Dark Red (139, 0, 0)

    Light Pink (255, 182, 193)

    Dark Orange (255, 140, 0)

    Light Cyan (224, 255, 255)

    Dark Cyan (0, 139, 139)

    Light Coral (240, 128, 128)

    Dark Violet (148, 0, 211)

    Light Salmon (255, 160, 122)

    Dark Khaki (189, 183, 107)

    Light Goldenrod (250, 250, 210)

    Dark Magenta (139, 0, 139)

    Light Slate Gray (119, 136, 153)

I used ChatGPT to create the code, and reviewed the article for accuracy and conciseness. I've tested the code and verified that it works. Hope that someone gets use out of it - in any case, I had it created for my uses. Just sharing it in case anyone else needed a free solution.

6