diff --git a/py/crop_by_mask.py b/py/crop_by_mask.py index 4fa89fa..a06e8dd 100644 --- a/py/crop_by_mask.py +++ b/py/crop_by_mask.py @@ -22,6 +22,7 @@ class CropByMask: "right_reserve": ("INT", {"default": 20, "min": -9999, "max": 9999, "step": 1}), }, "optional": { + "crop_box": ("BOX",), } } @@ -32,15 +33,16 @@ class CropByMask: OUTPUT_NODE = True def crop_by_mask(self, image, mask_for_crop, invert_mask, detect, - top_reserve, bottom_reserve, left_reserve, right_reserve - ): + top_reserve, bottom_reserve, + left_reserve, right_reserve, + crop_box=None + ): ret_images = [] ret_masks = [] l_images = [] l_masks = [] - for l in image: l_images.append(torch.unsqueeze(l, 0)) if mask_for_crop.dim() == 2: @@ -54,28 +56,32 @@ class CropByMask: l_masks.append(tensor2pil(torch.unsqueeze(mask_for_crop, 0)).convert('L')) _mask = mask2image(mask_for_crop) - bluredmask = gaussian_blur(_mask, 20).convert('L') - x = 0 - y = 0 - width = 0 - height = 0 - if detect == "min_bounding_rect": - (x, y, width, height) = min_bounding_rect(bluredmask) - elif detect == "max_inscribed_rect": - (x, y, width, height) = max_inscribed_rect(bluredmask) - else: - (x, y, width, height) = mask_area(_mask) - log(f"{NODE_NAME}: Box detected. x={x},y={y},width={width},height={height}") - canvas_width, canvas_height = tensor2pil(torch.unsqueeze(image[0], 0)).convert('RGB').size - x1 = x - left_reserve if x - left_reserve > 0 else 0 - y1 = y - top_reserve if y - top_reserve > 0 else 0 - x2 = x + width + right_reserve if x + width + right_reserve < canvas_width else canvas_width - y2 = y + height + bottom_reserve if y + height + bottom_reserve < canvas_height else canvas_height preview_image = tensor2pil(mask_for_crop).convert('RGB') - preview_image = draw_rect(preview_image, x, y, width, height, line_color="#F00000", line_width=(width+height)//100) - preview_image = draw_rect(preview_image, x1, y1, x2 - x1, y2 - y1, - line_color="#00F000", line_width=(width+height)//200) - crop_box = (x1, y1, x2, y2) + if crop_box is None: + bluredmask = gaussian_blur(_mask, 20).convert('L') + x = 0 + y = 0 + width = 0 + height = 0 + if detect == "min_bounding_rect": + (x, y, width, height) = min_bounding_rect(bluredmask) + elif detect == "max_inscribed_rect": + (x, y, width, height) = max_inscribed_rect(bluredmask) + else: + (x, y, width, height) = mask_area(_mask) + log(f"{NODE_NAME}: Box detected. x={x},y={y},width={width},height={height}") + canvas_width, canvas_height = tensor2pil(torch.unsqueeze(image[0], 0)).convert('RGB').size + x1 = x - left_reserve if x - left_reserve > 0 else 0 + y1 = y - top_reserve if y - top_reserve > 0 else 0 + x2 = x + width + right_reserve if x + width + right_reserve < canvas_width else canvas_width + y2 = y + height + bottom_reserve if y + height + bottom_reserve < canvas_height else canvas_height + crop_box = (x1, y1, x2, y2) + preview_image = draw_rect(preview_image, x, y, width, height, line_color="#F00000", + line_width=(width + height) // 100) + preview_image = draw_rect(preview_image, crop_box[0], crop_box[1], + crop_box[2] - crop_box[0], crop_box[3] - crop_box[1], + line_color="#00F000", + line_width=(crop_box[2] - crop_box[0] + crop_box[3] - crop_box[1]) // 200) for i in range(len(l_images)): _canvas = tensor2pil(l_images[i]).convert('RGB') _mask = l_masks[0] diff --git a/py/imagefunc.py b/py/imagefunc.py index b82b34a..02cbba5 100644 --- a/py/imagefunc.py +++ b/py/imagefunc.py @@ -16,6 +16,7 @@ import scipy.ndimage import cv2 import random import time +from tqdm import tqdm from functools import lru_cache from typing import Union, List from PIL import Image, ImageFilter, ImageChops, ImageDraw, ImageOps, ImageEnhance, ImageFont @@ -93,6 +94,12 @@ def pil2cv2(pil_img:Image) -> np.array: def pil2tensor(image:Image) -> torch.Tensor: return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0) +def np2pil(np_image:np.ndarray) -> Image: + return Image.fromarray(np_image) + +def pil2np(pil_image:Image) -> np.array: + return np.ndarray(pil_image) + def np2tensor(img_np: Union[np.ndarray, List[np.ndarray]]) -> torch.Tensor: if isinstance(img_np, list): return torch.cat([np2tensor(img) for img in img_np], dim=0) @@ -270,6 +277,81 @@ def blend_hard_mix(background_image:Image, layer_image:Image) -> Image: img = img * mask return cv22pil(ski2cv2(img)) +def tuple_averge(tuples:list) -> tuple: + values = [] + ret = [] + for i in tuples[0]: + values.append(0) + ret.append(0) + for t in tuples: + for j in range(len(t)): + values[j] += t[j] + for k in range(len(values)): + ret[k] = int(values[k] / len(tuples)) + return tuple(ret) + +def get_pixel_from_round(image:Image, position:tuple) -> tuple: + (x, y) = position + width, height = image.size + pixels = [] + if x > 0: + pixels.append(image.getpixel((x - 1, y))) + if y > 0: + pixels.append(image.getpixel((x - 1, y - 1))) + if y < height: + pixels.append(image.getpixel((x - 1, y + 1))) + if x < width: + pixels.append(image.getpixel((x + 1, y))) + if y > 0: + pixels.append(image.getpixel((x + 1, y - 1))) + if y < height: + pixels.append(image.getpixel((x + 1, y + 1))) + if y > 0: + pixels.append(image.getpixel((x, y-1))) + if y < height: + pixels.append(image.getpixel((x, y + 1))) + return tuple_averge(pixels) + +def displace_pixel(image:Image, source_pixel:tuple, target_pixel:tuple) -> Image: + # ret_image = image.copy() + image.putpixel(target_pixel, image.getpixel(source_pixel)) + return image + +def displace_pixel_np(np_image:np.ndarray, source_pixel:tuple, target_pixel:tuple) -> np.ndarray: + np_image[target_pixel[1], target_pixel[0], :] = np_image[source_pixel[1], source_pixel[0], :] + return np_image + +# def de_warp(image:Image) -> Image: + + # + # img = pil2cv2(image) + # gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + # edges = cv2.Canny(gray, 50, 150, apertureSize=3) + # + # # 霍夫变换 + # lines = cv2.HoughLines(edges, 1, np.pi / 180, 0) + # rotate_angle = 0 + # for rho, theta in lines[0]: + # a = np.cos(theta) + # b = np.sin(theta) + # x0 = a * rho + # y0 = b * rho + # x1 = int(x0 + 1000 * (-b)) + # y1 = int(y0 + 1000 * (a)) + # x2 = int(x0 - 1000 * (-b)) + # y2 = int(y0 - 1000 * (a)) + # if x1 == x2 or y1 == y2: + # continue + # t = float(y2 - y1) / (x2 - x1) + # rotate_angle = math.degrees(math.atan(t)) + 45 + # if rotate_angle > 45: + # rotate_angle = -90 + rotate_angle + # elif rotate_angle < -45: + # rotate_angle = 90 + rotate_angle + # rotate_img = scipy.ndimage.rotate(img, rotate_angle) + # return cv22pil(rotate_img) + + def shift_image(image:Image, distance_x:int, distance_y:int, background_color:str='#000000', cyclic:bool=False) -> Image: width = image.width height = image.height @@ -348,6 +430,14 @@ def remove_background(image:Image, mask:Image, color:str) -> Image: ret_image.paste(image, mask=mask) return ret_image +def sharpen(image:Image) -> Image: + img = pil2cv2(image) + Laplace_kernel = np.array([[-1, -1, -1], + [-1, 9, -1], + [-1, -1, -1]], dtype=np.float32) + ret_image = cv2.filter2D(img, -1, Laplace_kernel) + return cv22pil(ret_image) + def gaussian_blur(image:Image, radius:int) -> Image: # image = image.convert("RGBA") ret_image = image.filter(ImageFilter.GaussianBlur(radius=radius))