Spaces:
Build error
Build error
import glob | |
import os | |
import cv2 | |
import argparse | |
import shutil | |
import math | |
from PIL import Image | |
import numpy as np | |
def resize_images(src_img_folder, dst_img_folder, max_resolution="512x512", divisible_by=2, interpolation=None, save_as_png=False, copy_associated_files=False): | |
# Split the max_resolution string by "," and strip any whitespaces | |
max_resolutions = [res.strip() for res in max_resolution.split(',')] | |
# # Calculate max_pixels from max_resolution string | |
# max_pixels = int(max_resolution.split("x")[0]) * int(max_resolution.split("x")[1]) | |
# Create destination folder if it does not exist | |
if not os.path.exists(dst_img_folder): | |
os.makedirs(dst_img_folder) | |
# Select interpolation method | |
if interpolation == 'lanczos4': | |
cv2_interpolation = cv2.INTER_LANCZOS4 | |
elif interpolation == 'cubic': | |
cv2_interpolation = cv2.INTER_CUBIC | |
else: | |
cv2_interpolation = cv2.INTER_AREA | |
# Iterate through all files in src_img_folder | |
img_exts = (".png", ".jpg", ".jpeg", ".webp", ".bmp") # copy from train_util.py | |
for filename in os.listdir(src_img_folder): | |
# Check if the image is png, jpg or webp etc... | |
if not filename.endswith(img_exts): | |
# Copy the file to the destination folder if not png, jpg or webp etc (.txt or .caption or etc.) | |
shutil.copy(os.path.join(src_img_folder, filename), os.path.join(dst_img_folder, filename)) | |
continue | |
# Load image | |
image = Image.open(os.path.join(src_img_folder, filename)) | |
if not image.mode == "RGB": | |
image = image.convert("RGB") | |
img = np.array(image, np.uint8) | |
base, _ = os.path.splitext(filename) | |
for max_resolution in max_resolutions: | |
# Calculate max_pixels from max_resolution string | |
max_pixels = int(max_resolution.split("x")[0]) * int(max_resolution.split("x")[1]) | |
# Calculate current number of pixels | |
current_pixels = img.shape[0] * img.shape[1] | |
# Calculate current resolution | |
current_resolution = (img.shape[0], img.shape[1]) | |
# Calculate target resolution | |
target_resolution = (int(max_resolution.split("x")[0]), int(max_resolution.split("x")[1])) | |
# Skip to the next image if the current resolution is less than the target resolution | |
if current_resolution[0] < target_resolution[0] or current_resolution[1] < target_resolution[1]: | |
print(f"Skipped image: {filename} as its resolution is smaller than target resolution") | |
continue | |
# Check if the image needs resizing | |
if current_pixels > max_pixels: | |
# Calculate scaling factor | |
scale_factor = max_pixels / current_pixels | |
# Calculate new dimensions | |
new_height = int(img.shape[0] * math.sqrt(scale_factor)) | |
new_width = int(img.shape[1] * math.sqrt(scale_factor)) | |
# Resize image | |
img = cv2.resize(img, (new_width, new_height), interpolation=cv2_interpolation) | |
else: | |
new_height, new_width = img.shape[0:2] | |
# Calculate the new height and width that are divisible by divisible_by (with/without resizing) | |
new_height = new_height if new_height % divisible_by == 0 else new_height - new_height % divisible_by | |
new_width = new_width if new_width % divisible_by == 0 else new_width - new_width % divisible_by | |
# Center crop the image to the calculated dimensions | |
y = int((img.shape[0] - new_height) / 2) | |
x = int((img.shape[1] - new_width) / 2) | |
img = img[y:y + new_height, x:x + new_width] | |
# Split filename into base and extension | |
new_filename = base + '+' + max_resolution + ('.png' if save_as_png else '.jpg') | |
# Save resized image in dst_img_folder | |
# cv2.imwrite(os.path.join(dst_img_folder, new_filename), img, [cv2.IMWRITE_JPEG_QUALITY, 100]) | |
image = Image.fromarray(img) | |
image.save(os.path.join(dst_img_folder, new_filename), quality=100) | |
proc = "Resized" if current_pixels > max_pixels else "Saved" | |
print(f"{proc} image: {filename} with size {img.shape[0]}x{img.shape[1]} as {new_filename}") | |
# If other files with same basename, copy them with resolution suffix | |
if copy_associated_files: | |
asoc_files = glob.glob(os.path.join(src_img_folder, base + ".*")) | |
for asoc_file in asoc_files: | |
ext = os.path.splitext(asoc_file)[1] | |
if ext in img_exts: | |
continue | |
for max_resolution in max_resolutions: | |
new_asoc_file = base + '+' + max_resolution + ext | |
print(f"Copy {asoc_file} as {new_asoc_file}") | |
shutil.copy(os.path.join(src_img_folder, asoc_file), os.path.join(dst_img_folder, new_asoc_file)) | |
def setup_parser() -> argparse.ArgumentParser: | |
parser = argparse.ArgumentParser( | |
description='Resize images in a folder to a specified max resolution(s) / 指定されたフォルダ内の画像を指定した最大画像サイズ(面積)以下にアスペクト比を維持したままリサイズします') | |
parser.add_argument('src_img_folder', type=str, help='Source folder containing the images / 元画像のフォルダ') | |
parser.add_argument('dst_img_folder', type=str, help='Destination folder to save the resized images / リサイズ後の画像を保存するフォルダ') | |
parser.add_argument('--max_resolution', type=str, | |
help='Maximum resolution(s) in the format "512x512,384x384, etc, etc" / 最大画像サイズをカンマ区切りで指定 ("512x512,384x384, etc, etc" など)', default="512x512,384x384,256x256,128x128") | |
parser.add_argument('--divisible_by', type=int, | |
help='Ensure new dimensions are divisible by this value / リサイズ後の画像のサイズをこの値で割り切れるようにします', default=1) | |
parser.add_argument('--interpolation', type=str, choices=['area', 'cubic', 'lanczos4'], | |
default='area', help='Interpolation method for resizing / リサイズ時の補完方法') | |
parser.add_argument('--save_as_png', action='store_true', help='Save as png format / png形式で保存') | |
parser.add_argument('--copy_associated_files', action='store_true', | |
help='Copy files with same base name to images (captions etc) / 画像と同じファイル名(拡張子を除く)のファイルもコピーする') | |
return parser | |
def main(): | |
parser = setup_parser() | |
args = parser.parse_args() | |
resize_images(args.src_img_folder, args.dst_img_folder, args.max_resolution, | |
args.divisible_by, args.interpolation, args.save_as_png, args.copy_associated_files) | |
if __name__ == '__main__': | |
main() | |