Download utils/utils.py from next-social/ComfyUI_Seg_VITON2: direct link, hf CLI and curl.
- Browser
- Download file 4.48 kB
-
https://huggingface.co/next-social/ComfyUI_Seg_VITON2/resolve/main/utils/utils.py
- Command line
-
hf download hf://next-social/ComfyUI_Seg_VITON2/utils/utils.py
-
curl -L -o utils.py https://huggingface.co/next-social/ComfyUI_Seg_VITON2/resolve/main/utils/utils.py
4.48 kB
| import torch | |
| import numpy as np | |
| import io | |
| from PIL import Image,ImageOps, ImageFilter | |
| from urllib.request import urlopen | |
| import datetime | |
| import os | |
| import cv2 | |
| import requests | |
| from io import BytesIO | |
| #comfyui自己的图像就是tensor | |
| def tensor2pil(image): | |
| return Image.fromarray(np.clip(255. * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) | |
| # Convert PIL to Tensor | |
| def pil2tensor(image): | |
| return torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0) | |
| # PIL to Mask | |
| def pil2mask(image): | |
| image_np = np.array(image.convert("L")).astype(np.float32) / 255.0 | |
| mask = torch.from_numpy(image_np) | |
| return 1.0 - mask | |
| # tensor to cv2 | |
| def tensor2cv2(img): | |
| tmp = ((img.cpu().numpy().transpose(1, 2, 0) + 1.0) * 127.5).astype(np.uint8) | |
| return cv2.cvtColor(tmp, cv2.COLOR_RGB2BGR) | |
| # convert PIL image to numpy array | |
| def piltonumpy_array(binary_mask_image): | |
| tensor_bw = binary_mask_image.convert("RGB") | |
| tensor_bw = np.array(tensor_bw).astype(np.float32) / 255.0 | |
| tensor_bw = torch.from_numpy(tensor_bw)[None,] | |
| tensor_bw = tensor_bw.squeeze(0)[..., 0] | |
| return tensor_bw | |
| # 保存tensor图片 | |
| def save_tensor_image(img,path): | |
| pil_image = tensor2pil(img) | |
| pil_image.save(path) | |
| def save_image(img, filename): | |
| tmp = ((img.detach().cpu().numpy().transpose(1, 2, 0) + 1.0) * 127.5).astype(np.uint8) | |
| cv2.imwrite(filename, cv2.cvtColor(tmp, cv2.COLOR_RGB2BGR)) | |
| def ioBytes_to_tensor(bytes): | |
| image = Image.open(bytes) | |
| return pil2tensor(image) | |
| # Flutter ImageFilter 所使用的模糊算法高斯模糊 | |
| def gaussian_region(image, radius=5.0): | |
| image = ImageOps.invert(image.convert("L")) | |
| image = image.filter(ImageFilter.GaussianBlur(radius=int(radius))) | |
| return image.convert("RGB") | |
| # 网络下载图片 | |
| def download_image(url): | |
| response = requests.get(url) | |
| return Image.open(BytesIO(response.content)).convert("RGB") | |
| def open_pil_image(path): | |
| img = Image.open(path) | |
| img = ImageOps.exif_transpose(img) | |
| image = img.convert("RGB") | |
| image = np.array(image).astype(np.float32) / 255.0 | |
| image = torch.from_numpy(image)[None,] | |
| return image | |
| def img_from_url(url): | |
| img = io.BytesIO(urlopen(url).read()) | |
| return open_pil_image(img) | |
| def save_images(img_list, folder): | |
| if not os.path.exists(folder): | |
| os.makedirs(folder) | |
| now = datetime.datetime.now() | |
| date_str = now.strftime("%Y-%m-%d") | |
| folder_path = os.path.join(folder, date_str) | |
| if not os.path.exists(folder_path): | |
| os.makedirs(folder_path) | |
| time_str = now.strftime("%H_%M_%S") | |
| for idx, img in enumerate(img_list): | |
| image_number = idx + 1 | |
| filename = f"{time_str}_{image_number}.jpg" | |
| save_path = os.path.join(folder_path, filename) | |
| cv2.imwrite(save_path, img[..., ::-1]) | |
| # 未测试 | |
| def save_tensors_images(img_tensors, img_names, save_dir): | |
| for img_tensor, img_name in zip(img_tensors, img_names): | |
| tensor = (img_tensor.clone()+1)*0.5 * 255 | |
| tensor = tensor.cpu().clamp(0,255) | |
| try: | |
| array = tensor.numpy().astype('uint8') | |
| except: | |
| array = tensor.detach().numpy().astype('uint8') | |
| if array.shape[0] == 1: | |
| array = array.squeeze(0) | |
| elif array.shape[0] == 3: | |
| array = array.swapaxes(0, 1).swapaxes(1, 2) | |
| im = Image.fromarray(array) | |
| im.save(os.path.join(save_dir, img_name), format='JPEG') | |
| def check_channels(image): | |
| channels = image.shape[2] if len(image.shape) == 3 else 1 | |
| if channels == 1: | |
| image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR) | |
| elif channels > 3: | |
| image = image[:, :, :3] | |
| return image | |
| def resize_image(img, max_length=768): | |
| height, width = img.shape[:2] | |
| max_dimension = max(height, width) | |
| if max_dimension > max_length: | |
| scale_factor = max_length / max_dimension | |
| new_width = int(round(width * scale_factor)) | |
| new_height = int(round(height * scale_factor)) | |
| new_size = (new_width, new_height) | |
| img = cv2.resize(img, new_size) | |
| height, width = img.shape[:2] | |
| img = cv2.resize(img, (width-(width % 64), height-(height % 64))) | |
| return img | |
| # 未测试 | |
| def gen_noise(shape): | |
| noise = np.zeros(shape, dtype=np.uint8) | |
| ### noise | |
| noise = cv2.randn(noise, 0, 255) | |
| noise = np.asarray(noise / 255, dtype=np.uint8) | |
| noise = torch.tensor(noise, dtype=torch.float32) | |
| return noise |