Path: blob/master/extensions-builtin/postprocessing-for-training/scripts/postprocessing_autosized_crop.py
2448 views
from PIL import Image12from modules import scripts_postprocessing, ui_components3import gradio as gr456def center_crop(image: Image, w: int, h: int):7iw, ih = image.size8if ih / h < iw / w:9sw = w * ih / h10box = (iw - sw) / 2, 0, iw - (iw - sw) / 2, ih11else:12sh = h * iw / w13box = 0, (ih - sh) / 2, iw, ih - (ih - sh) / 214return image.resize((w, h), Image.Resampling.LANCZOS, box)151617def multicrop_pic(image: Image, mindim, maxdim, minarea, maxarea, objective, threshold):18iw, ih = image.size19err = lambda w, h: 1 - (lambda x: x if x < 1 else 1 / x)(iw / ih / (w / h))20wh = max(((w, h) for w in range(mindim, maxdim + 1, 64) for h in range(mindim, maxdim + 1, 64)21if minarea <= w * h <= maxarea and err(w, h) <= threshold),22key=lambda wh: (wh[0] * wh[1], -err(*wh))[::1 if objective == 'Maximize area' else -1],23default=None24)25return wh and center_crop(image, *wh)262728class ScriptPostprocessingAutosizedCrop(scripts_postprocessing.ScriptPostprocessing):29name = "Auto-sized crop"30order = 40203132def ui(self):33with ui_components.InputAccordion(False, label="Auto-sized crop") as enable:34gr.Markdown('Each image is center-cropped with an automatically chosen width and height.')35with gr.Row():36mindim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension lower bound", value=384, elem_id="postprocess_multicrop_mindim")37maxdim = gr.Slider(minimum=64, maximum=2048, step=8, label="Dimension upper bound", value=768, elem_id="postprocess_multicrop_maxdim")38with gr.Row():39minarea = gr.Slider(minimum=64 * 64, maximum=2048 * 2048, step=1, label="Area lower bound", value=64 * 64, elem_id="postprocess_multicrop_minarea")40maxarea = gr.Slider(minimum=64 * 64, maximum=2048 * 2048, step=1, label="Area upper bound", value=640 * 640, elem_id="postprocess_multicrop_maxarea")41with gr.Row():42objective = gr.Radio(["Maximize area", "Minimize error"], value="Maximize area", label="Resizing objective", elem_id="postprocess_multicrop_objective")43threshold = gr.Slider(minimum=0, maximum=1, step=0.01, label="Error threshold", value=0.1, elem_id="postprocess_multicrop_threshold")4445return {46"enable": enable,47"mindim": mindim,48"maxdim": maxdim,49"minarea": minarea,50"maxarea": maxarea,51"objective": objective,52"threshold": threshold,53}5455def process(self, pp: scripts_postprocessing.PostprocessedImage, enable, mindim, maxdim, minarea, maxarea, objective, threshold):56if not enable:57return5859cropped = multicrop_pic(pp.image, mindim, maxdim, minarea, maxarea, objective, threshold)60if cropped is not None:61pp.image = cropped62else:63print(f"skipped {pp.image.width}x{pp.image.height} image (can't find suitable size within error threshold)")646566