Spaces:
Sleeping
Sleeping
| """Image resizing to FLUX-compatible resolutions (dimensions divisible by 32).""" | |
| import cv2 | |
| import numpy as np | |
| from typing import Tuple | |
| from PIL import Image | |
| class FluxResizer: | |
| """ | |
| Resizer that ensures images are compatible with FLUX requirements. | |
| - FLUX: Dimensions divisible by 32 (due to 2x2 packing on top of 16-stride VAE) | |
| """ | |
| # Predefined optimal resolutions (all divisible by 32) | |
| OPTIMAL_RESOLUTIONS = [ | |
| # Square and near-square | |
| (1024, 1024), # 1:1 (64×64, 64×64) | |
| (896, 1152), # ~0.78:1 (56×72) | |
| (1152, 896), # ~1.29:1 (72×56) | |
| (768, 1344), # ~0.57:1 (48×84) | |
| (1344, 768), # ~1.75:1 (84×48) | |
| # Additional common ratios | |
| (832, 1216), # ~0.68:1 (52×76) | |
| (1216, 832), # ~1.46:1 (76×52) | |
| (704, 1408), # 0.5:1 (44×88) | |
| (1408, 704), # 2:1 (88×44) | |
| (960, 1088), # ~0.88:1 (60×68) | |
| (1088, 960), # ~1.13:1 (68×60) | |
| ] | |
| def __init__(self): | |
| self.resolution_aspects = [ | |
| (h, w, w / h) for h, w in self.OPTIMAL_RESOLUTIONS | |
| ] | |
| def select_best_resolution(self, original_h: int, original_w: int) -> Tuple[int, int]: | |
| """Pick the optimal resolution whose aspect ratio best matches the input.""" | |
| original_aspect = original_w / original_h | |
| best_resolution = None | |
| min_aspect_diff = float('inf') | |
| for h, w, aspect in self.resolution_aspects: | |
| aspect_diff = abs(original_aspect - aspect) | |
| if aspect_diff < min_aspect_diff: | |
| min_aspect_diff = aspect_diff | |
| best_resolution = (h, w) | |
| return best_resolution | |
| def resize_image(self, image: np.ndarray) -> Tuple[np.ndarray, Tuple[int, int]]: | |
| """Resize an (H, W, C) numpy image to the optimal FLUX-compatible resolution.""" | |
| original_h, original_w = image.shape[:2] | |
| target_h, target_w = self.select_best_resolution(original_h, original_w) | |
| resized_image = cv2.resize(image, (target_w, target_h), interpolation=cv2.INTER_LINEAR) | |
| return resized_image, (target_h, target_w) | |
| def resize_pil_image(self, image: Image.Image) -> Tuple[Image.Image, Tuple[int, int]]: | |
| """Resize a PIL image to the optimal FLUX-compatible resolution.""" | |
| original_w, original_h = image.size # PIL uses (W, H) | |
| target_h, target_w = self.select_best_resolution(original_h, original_w) | |
| resized_image = image.resize((target_w, target_h), Image.LANCZOS) | |
| return resized_image, (target_h, target_w) | |
| def resize_mask(self, mask: np.ndarray, target_size: Tuple[int, int]) -> np.ndarray: | |
| """Resize a mask to target_size=(H, W) using nearest-neighbor interpolation.""" | |
| target_h, target_w = target_size | |
| if len(mask.shape) == 3 and mask.shape[2] == 1: | |
| mask = mask.squeeze(2) | |
| resized_mask = cv2.resize(mask, (target_w, target_h), interpolation=cv2.INTER_NEAREST) | |
| return resized_mask | |
| def get_compatible_resolutions(self) -> list: | |
| """Return list of all compatible resolutions.""" | |
| return self.OPTIMAL_RESOLUTIONS.copy() | |
| def verify_compatibility(height: int, width: int) -> bool: | |
| """True if both dimensions are divisible by 32 (FLUX requirement).""" | |
| return (height % 32 == 0) and (width % 32 == 0) | |