From d8bb35f328ba9dec7c5be54a9f3c664adfb331ed Mon Sep 17 00:00:00 2001 From: fujammy <467918@qq.com> Date: Thu, 26 Dec 2024 21:29:45 +0800 Subject: [PATCH] Enhance image resizing functionality by adding mask generation for all resizing methods. Updated the resize_image function to return a mask alongside the resized image, ensuring better handling of image boundaries. Improved the calculate_mask function to support various alignment modes and ensure accurate mask creation. This update enhances the overall image processing capabilities. --- .gitignore | 4 + __pycache__/__init__.cpython-311.pyc | Bin 1884 -> 1853 bytes __pycache__/click_popup.cpython-311.pyc | Bin 1067 -> 1036 bytes __pycache__/color_picker.cpython-311.pyc | Bin 2130 -> 2099 bytes .../dynamic_image_input.cpython-311.pyc | Bin 2209 -> 2178 bytes .../image_resolution_adjuster.cpython-311.pyc | Bin 15791 -> 19317 bytes __pycache__/install.cpython-311.pyc | Bin 3175 -> 3144 bytes .../multiline_text_input.cpython-311.pyc | Bin 1072 -> 1041 bytes .../remove_empty_lines.cpython-311.pyc | Bin 3656 -> 3625 bytes __pycache__/text_combiner.cpython-311.pyc | Bin 4417 -> 4386 bytes image_resolution_adjuster.py | 208 ++++++++++-------- 11 files changed, 126 insertions(+), 86 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72ccc96 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +# Python cache files +__pycache__/ +*.py[cod] +*$py.class \ No newline at end of file diff --git a/__pycache__/__init__.cpython-311.pyc b/__pycache__/__init__.cpython-311.pyc index a627e8d11212d96dcfbaaadd1165bc28d42f8e34..f2d68ec400252817ae3b2b4f1109826d35ac2402 100644 GIT binary patch delta 52 zcmcb^x0jD^IWI340}v>x=A_HAZ{+*NA|B*v731jX?i}NspPN=0>gkeNmYS1au-S@L Gi3tE~D-ON@ delta 83 zcmdnXcZZK}IWI340}xyk%1M9Dwvq1}i&>$YRg9yjyK_i>eok?WbAE1GWvHi1YFTPd fenBdXA77rCmy%yz9AA)MRFasKle$@&Rf!1zhQ}Px diff --git a/__pycache__/click_popup.cpython-311.pyc b/__pycache__/click_popup.cpython-311.pyc index 4818ffeb2d729c63dc127eb085425e17a0f1dbff..1de41fe707ca10fa65592af78a30b5e7e8678fce 100644 GIT binary patch delta 49 zcmZ3@(Zj*LoR^o20SFXTb2f4dGKz=jWzXhI+cBmZj$87iFykopPy44IWI340}#}SY~(u1C?4i%731jX?i}NspPN=0>gkeNmYS1au$h&~mkj_t C&ke!= delta 79 zcmdlia7ln`IWI340}upl+{ks5(X7%-8m#bKc_gxIX^e8GSt&0wJbF!zaSOH bk1x;6OUW-UjxWeBDoISrN!|R6(U%PX{GA)# diff --git a/__pycache__/dynamic_image_input.cpython-311.pyc b/__pycache__/dynamic_image_input.cpython-311.pyc index 79d557a51ac9e76cbd429c360ff5ddfe9dde59f7..0820103fae5998173e45463e4cf269b2a3d94463 100644 GIT binary patch delta 48 zcmZ1|*d)lcoR^o20SKxBH*!TWipP3d#W;GpJI6TZ=cZMLdb*^RrRL-pY@Wr)&JF-6 CPz{Cv delta 79 zcmZn?Tqwx3oR^o20SFG=*vJ*dXjbE9731jX?i`YzpHm#;oS&Ok8S3ehT9%rVUyusp b$Cqd3rR0|v#~0)ml_VzRq;9TeWM>Be>z*3{ diff --git a/__pycache__/image_resolution_adjuster.cpython-311.pyc b/__pycache__/image_resolution_adjuster.cpython-311.pyc index 8a76136cbdbc7f509c9d28a87f8aacead8b149fe..b83526c096ec888adf2ab8212eb7989274575e87 100644 GIT binary patch delta 7058 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 Ow^OoD@1r7lL;nLX-(p+< delta 4073 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 DBU%l_ delta 80 zcmbQpv4MkoIWI340}xan$lk~;!Dv?NW)FykopPy44pF diff --git a/__pycache__/remove_empty_lines.cpython-311.pyc b/__pycache__/remove_empty_lines.cpython-311.pyc index 98a5e829274d72b5c8b7d33ea4f472097ee429d6..ed0fb8d5c787d1f6786679e3e2fe5d7336994cbb 100644 GIT binary patch delta 48 zcmX>hvr>j@IWI340}up0*~oRBNj%2WD#p>%-8sfNKR2y1)YB!kEHx*;V6!;0AvXY4 C_zr#m delta 79 zcmZ1}b3%q|IWI340}xzH-pF;G$*kJVD#p>%-8m#bKc_gxIX^e8GSt&0wJbF!zaSOH bk1x;6OUW-UjxWeBDoISrN!|Q|$&ecW5YHSa diff --git a/__pycache__/text_combiner.cpython-311.pyc b/__pycache__/text_combiner.cpython-311.pyc index d5c5adda31ce817831a628154e38ef28ef9b5c24..6dab7a4743b1b57b67e547332f5b8371eacf2d35 100644 GIT binary patch delta 48 zcmX@8v`C3-IWI340}#Z;Z{+&OC?4)<731jX?i}NspPN=0>gkeNmYS1au-TAFfFA%! CP7V|R delta 79 zcmZ3abWn+FIWI340}%9F*vR#f(X7nPD#p>%-8m#bKc_gxIX^e8GSt&0wJbF!zaSOH bk1x;6OUW-UjxWeBDoISrN!={OB)|^<8yp*7 diff --git a/image_resolution_adjuster.py b/image_resolution_adjuster.py index 62f38d6..3f93873 100644 --- a/image_resolution_adjuster.py +++ b/image_resolution_adjuster.py @@ -44,70 +44,81 @@ def resize_image(image, target_width, target_height, method='contain', backgroun y_offset = (target_height - new_height) // 2 padded_img.paste(resized_img, (x_offset, y_offset)) - # 在返回之前计算mask + # 生成mask mask = calculate_mask((img_width, img_height), (target_width, target_height), method) - return np.array(padded_img).astype(np.float32)/255.0, mask, new_width, new_height + return np.array(padded_img).astype(np.float32)/255.0, mask, target_width, target_height elif method == 'cover': # Cover: 缩放图像以覆盖目标尺寸,保持宽高比,可能裁剪 - img_ratio = img_width / img_height - target_ratio = target_width / target_height - if img_ratio > target_ratio: + img_ratio = img_width / img_height + target_ratio = target_width / target_height + if img_ratio > target_ratio: new_height = target_height new_width = int(target_height * img_ratio) - else: + else: new_width = target_width new_height = int(target_width / img_ratio) - resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) - x_offset = (new_width - target_width) // 2 - y_offset = (new_height - target_height) // 2 - cropped_img = resized_img.crop((x_offset, y_offset, x_offset + target_width, y_offset + target_height)) - return np.array(cropped_img).astype(np.float32)/255.0 , target_width, target_height + resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + x_offset = (new_width - target_width) // 2 + y_offset = (new_height - target_height) // 2 + cropped_img = resized_img.crop((x_offset, y_offset, x_offset + target_width, y_offset + target_height)) + + # 生成mask + mask = calculate_mask((img_width, img_height), (target_width, target_height), method) + return np.array(cropped_img).astype(np.float32)/255.0, mask, target_width, target_height elif method == 'fill': # Fill: 拉伸图像以填充目标尺寸,忽略宽高比,可能变形 resized_img = img.resize((target_width, target_height), Image.Resampling.LANCZOS) - return np.array(resized_img).astype(np.float32)/255.0, target_width, target_height + # 生成mask + mask = calculate_mask((img_width, img_height), (target_width, target_height), method) + return np.array(resized_img).astype(np.float32)/255.0, mask, target_width, target_height elif method == 'inside': - # Inside: 和 contain 相同,保持宽高比,缩小或不改变图像使其完全适合容器 - img_ratio = img_width / img_height - target_ratio = target_width / target_height - if img_ratio > target_ratio: + # Inside: 和 contain 相同,保持宽高比,缩小或不改变图像使其完全适合容器 + img_ratio = img_width / img_height + target_ratio = target_width / target_height + if img_ratio > target_ratio: new_width = target_width new_height = int(target_width / img_ratio) - else: + else: new_height = target_height new_width = int(target_height * img_ratio) - resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) - - # 解析背景颜色 - try: - color = tuple(int(background_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) - except ValueError: - color = (0, 0, 0) # 默认黑色 - - padded_img = Image.new('RGB', (target_width, target_height), color) - x_offset = (target_width - new_width) // 2 - y_offset = (target_height - new_height) // 2 - padded_img.paste(resized_img, (x_offset, y_offset)) - return np.array(padded_img).astype(np.float32)/255.0, target_width, target_height + resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + + # 解析背景颜色 + try: + color = tuple(int(background_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4)) + except ValueError: + color = (0, 0, 0) # 默认黑色 + + padded_img = Image.new('RGB', (target_width, target_height), color) + x_offset = (target_width - new_width) // 2 + y_offset = (target_height - new_height) // 2 + padded_img.paste(resized_img, (x_offset, y_offset)) + + # 生成mask + mask = calculate_mask((img_width, img_height), (target_width, target_height), method) + return np.array(padded_img).astype(np.float32)/255.0, mask, target_width, target_height elif method == 'outside': - # Outside: 和 cover 相同,保持宽高比,放大或不改变图像使其完全覆盖容器 - img_ratio = img_width / img_height - target_ratio = target_width / target_height - if img_ratio > target_ratio: - new_height = target_height - new_width = int(target_height * img_ratio) - else: - new_width = target_width - new_height = int(target_width / img_ratio) - resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) - x_offset = (new_width - target_width) // 2 - y_offset = (new_height - target_height) // 2 - cropped_img = resized_img.crop((x_offset, y_offset, x_offset + target_width, y_offset + target_height)) - return np.array(cropped_img).astype(np.float32)/255.0 , target_width, target_height + # Outside: 和 cover 相同,保持宽高比,放大或不改变图像使其完全覆盖容器 + img_ratio = img_width / img_height + target_ratio = target_width / target_height + if img_ratio > target_ratio: + new_height = target_height + new_width = int(target_height * img_ratio) + else: + new_width = target_width + new_height = int(target_width / img_ratio) + resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + x_offset = (new_width - target_width) // 2 + y_offset = (new_height - target_height) // 2 + cropped_img = resized_img.crop((x_offset, y_offset, x_offset + target_width, y_offset + target_height)) + + # 生成mask + mask = calculate_mask((img_width, img_height), (target_width, target_height), method) + return np.array(cropped_img).astype(np.float32)/255.0, mask, target_width, target_height def pad_image(image, target_width, target_height, position='center', background_color='#000000'): """Pad an image to the target dimensions with specified background color.""" @@ -247,72 +258,97 @@ def create_outline(image, background_color): return np.array(outlined).astype(np.float32) / 255.0 def calculate_mask(original_size, target_size, extend_mode, feather=0): - """计算填充区域的mask + """计算填充区域的mask,白色(1)表示图像区域,黑色(0)表示背景/填充区域 Args: original_size: (width, height) 原始图像尺寸 target_size: (width, height) 目标尺寸 extend_mode: 扩展模式 feather: 羽化程度 Returns: - torch.Tensor: mask张量 + torch.Tensor: mask张量,1表示图像区域,0表示背景/填充区域 """ orig_w, orig_h = original_size target_w, target_h = target_size - # 创建目标尺寸的mask,初始化为0(黑色,表示填充区域) + # 创建目标尺寸的mask(默认全黑,表示背景) mask = torch.zeros((target_h, target_w)) - if extend_mode in ["contain", "inside"]: - # 计算缩放后的尺寸 + if extend_mode == "fill": + mask.fill_(1.0) + + elif extend_mode in ["cover", "outside"]: + mask.fill_(1.0) + + elif extend_mode in ["contain", "inside"]: ratio = min(target_w/orig_w, target_h/orig_h) new_w = int(orig_w * ratio) new_h = int(orig_h * ratio) - # 计算偏移量(居中) x_offset = (target_w - new_w) // 2 y_offset = (target_h - new_h) // 2 - # 设置非填充区域为1(白色) - mask[y_offset:y_offset + new_h, x_offset:x_offset + new_w] = 1 + mask[y_offset:y_offset + new_h, x_offset:x_offset + new_w] = 1.0 elif extend_mode in ["top", "bottom", "left", "right", "center"]: - # 计算偏移量 - if extend_mode == "top": - x_offset = (target_w - orig_w) // 2 + # 1. 首先判断原始图像是否需要缩放 + if orig_w <= target_w and orig_h <= target_h: + # 图像小于或等于目标尺寸,不需要缩放 + new_w = orig_w + new_h = orig_h + else: + # 需要缩放,根据对齐方式选择缩放策略 + if extend_mode in ["left", "right"]: + # 左右对齐优先考虑高度 + ratio = target_h / orig_h + new_h = target_h + new_w = int(orig_w * ratio) + # 如果宽度超出,则按宽度重新计算 + if new_w > target_w: + ratio = target_w / orig_w + new_w = target_w + new_h = int(orig_h * ratio) + elif extend_mode in ["top", "bottom"]: + # 上下对齐优先考虑宽度 + ratio = target_w / orig_w + new_w = target_w + new_h = int(orig_h * ratio) + # 如果高度超出,则按高度重新计算 + if new_h > target_h: + ratio = target_h / orig_h + new_h = target_h + new_w = int(orig_w * ratio) + else: # center + # 居中对齐选择最适合的缩放比例 + ratio = min(target_w / orig_w, target_h / orig_h) + new_w = int(orig_w * ratio) + new_h = int(orig_h * ratio) + + # 2. 根据对齐方式计算偏移量 + if extend_mode == "center": + x_offset = (target_w - new_w) // 2 + y_offset = (target_h - new_h) // 2 + elif extend_mode == "top": + x_offset = (target_w - new_w) // 2 y_offset = 0 elif extend_mode == "bottom": - x_offset = (target_w - orig_w) // 2 - y_offset = target_h - orig_h + x_offset = (target_w - new_w) // 2 + y_offset = target_h - new_h elif extend_mode == "left": x_offset = 0 - y_offset = (target_h - orig_h) // 2 - elif extend_mode == "right": - x_offset = target_w - orig_w - y_offset = (target_h - orig_h) // 2 - else: # center - x_offset = (target_w - orig_w) // 2 - y_offset = (target_h - orig_h) // 2 - - # 设置非填充区域为1(白色) - mask[y_offset:y_offset + orig_h, x_offset:x_offset + orig_w] = 1 - - # 应用羽化效果 - if feather > 0: - # 将mask转换为适合卷积的格式 [B, C, H, W] - mask = mask.unsqueeze(0).unsqueeze(0) - - # 创建高斯核进行羽化 - kernel_size = 2 * feather + 1 - sigma = feather / 3 - - # 应用高斯模糊 - mask = F.gaussian_blur(mask, kernel_size=(kernel_size, kernel_size), sigma=(sigma, sigma)) - - # 转换回原始格式 - mask = mask.squeeze(0).squeeze(0) - - # 确保mask值在0-1范围内 - mask = torch.clamp(mask, 0, 1) + y_offset = (target_h - new_h) // 2 + else: # right + x_offset = target_w - new_w + y_offset = (target_h - new_h) // 2 + + # 3. 确保所有值都在有效范围内 + x_offset = max(0, min(x_offset, target_w - new_w)) + y_offset = max(0, min(y_offset, target_h - new_h)) + new_w = min(new_w, target_w) + new_h = min(new_h, target_h) + + # 4. 生成mask + if new_w > 0 and new_h > 0: + mask[y_offset:y_offset + new_h, x_offset:x_offset + new_w] = 1.0 return mask @@ -356,7 +392,7 @@ class ImageResolutionAdjuster: "min_height": ("INT", {"default": 640, "min": 1, "max": 8192, "step": 1}), "background_color": ("STRING", {"default": "#000000", "multiline": False}), "add_outline": ("BOOLEAN", {"default": False}), - "feather": ("INT", {"default": 0, "min": 0, "max": 10, "step": 1}), + # "feather": ("INT", {"default": 0, "min": 0, "max": 10, "step": 1}), }, "hidden": {"color_widget": "COMBO"} }