Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
functional.py222 linesDownload Raw Back to transform
1import numpy as np2from PIL import Image3 4from fastembed.common.types import NumpyArray5 6 7def convert_to_rgb(image: Image.Image) -> Image.Image:8    if image.mode == "RGB":9        return image10 11    image = image.convert("RGB")12    return image13 14 15def center_crop(16    image: Image.Image | NumpyArray,17    size: tuple[int, int],18) -> NumpyArray:19    if isinstance(image, np.ndarray):20        _, orig_height, orig_width = image.shape21    else:22        orig_height, orig_width = image.height, image.width23        # (H, W, C) -> (C, H, W)24        image = np.array(image).transpose((2, 0, 1))25 26    crop_height, crop_width = size27 28    # left upper corner (0, 0)29    top = (orig_height - crop_height) // 230    bottom = top + crop_height31    left = (orig_width - crop_width) // 232    right = left + crop_width33 34    # Check if cropped area is within image boundaries35    if top >= 0 and bottom <= orig_height and left >= 0 and right <= orig_width:36        image = image[..., top:bottom, left:right]37        return image38 39    # Padding with zeros40    new_height = max(crop_height, orig_height)41    new_width = max(crop_width, orig_width)42    new_shape = image.shape[:-2] + (new_height, new_width)43    new_image = np.zeros_like(image, shape=new_shape, dtype=np.float32)44 45    top_pad = (new_height - orig_height) // 246    bottom_pad = top_pad + orig_height47    left_pad = (new_width - orig_width) // 248    right_pad = left_pad + orig_width49    new_image[..., top_pad:bottom_pad, left_pad:right_pad] = image50 51    top += top_pad52    bottom += top_pad53    left += left_pad54    right += left_pad55 56    new_image = new_image[57        ..., max(0, top) : min(new_height, bottom), max(0, left) : min(new_width, right)58    ]59 60    return new_image61 62 63def normalize(64    image: NumpyArray,65    mean: float | list[float],66    std: float | list[float],67) -> NumpyArray:68    num_channels = image.shape[1] if len(image.shape) == 4 else image.shape[0]69 70    if not np.issubdtype(image.dtype, np.floating):71        image = image.astype(np.float32)72 73    mean_list = mean if isinstance(mean, list) else [mean] * num_channels74 75    if len(mean_list) != num_channels:76        raise ValueError(77            f"mean must have the same number of channels as the image, image has {num_channels} channels, got "78            f"{len(mean_list)}"79        )80 81    mean_arr = np.array(mean_list, dtype=np.float32)82 83    std_list = std if isinstance(std, list) else [std] * num_channels84    if len(std_list) != num_channels:85        raise ValueError(86            f"std must have the same number of channels as the image, image has {num_channels} channels, got {len(std_list)}"87        )88 89    std_arr = np.array(std_list, dtype=np.float32)90 91    image_upd = ((image.T - mean_arr) / std_arr).T92    return image_upd93 94 95def resize(96    image: Image.Image,97    size: int | tuple[int, int],98    resample: int | Image.Resampling = Image.Resampling.BILINEAR,99) -> Image.Image:100    if isinstance(size, tuple):101        return image.resize(size, resample)102 103    height, width = image.height, image.width104    short, long = (width, height) if width <= height else (height, width)105 106    new_short, new_long = size, int(size * long / short)107    if width <= height:108        new_size = (new_short, new_long)109    else:110        new_size = (new_long, new_short)111    return image.resize(new_size, resample)112 113 114def rescale(image: NumpyArray, scale: float, dtype: type = np.float32) -> NumpyArray:115    return (image * scale).astype(dtype)116 117 118def pil2ndarray(image: Image.Image | NumpyArray) -> NumpyArray:119    if isinstance(image, Image.Image):120        return np.asarray(image).transpose((2, 0, 1))121    return image122 123 124def pad2square(125    image: Image.Image,126    size: int,127    fill_color: str | int | tuple[int, ...] = 0,128) -> Image.Image:129    height, width = image.height, image.width130 131    left, right = 0, width132    top, bottom = 0, height133 134    crop_required = False135    if width > size:136        left = (width - size) // 2137        right = left + size138        crop_required = True139 140    if height > size:141        top = (height - size) // 2142        bottom = top + size143        crop_required = True144 145    new_image = Image.new(mode="RGB", size=(size, size), color=fill_color)146    new_image.paste(image.crop((left, top, right, bottom)) if crop_required else image)147    return new_image148 149 150def resize_longest_edge(151    image: Image.Image,152    max_size: int,153    resample: int | Image.Resampling = Image.Resampling.LANCZOS,154) -> Image.Image:155    height, width = image.height, image.width156    aspect_ratio = width / height157 158    if width >= height:159        # Width is longer160        new_width = max_size161        new_height = int(new_width / aspect_ratio)162    else:163        # Height is longer164        new_height = max_size165        new_width = int(new_height * aspect_ratio)166 167    # Ensure even dimensions168    if new_height % 2 != 0:169        new_height += 1170    if new_width % 2 != 0:171        new_width += 1172 173    return image.resize((new_width, new_height), resample)174 175 176def crop_ndarray(177    image: NumpyArray,178    x1: int,179    y1: int,180    x2: int,181    y2: int,182    channel_first: bool = True,183) -> NumpyArray:184    if channel_first:185        # (C, H, W) format186        return image[:, y1:y2, x1:x2]187    else:188        # (H, W, C) format189        return image[y1:y2, x1:x2, :]190 191 192def resize_ndarray(193    image: NumpyArray,194    size: tuple[int, int],195    resample: int | Image.Resampling = Image.Resampling.LANCZOS,196    channel_first: bool = True,197) -> NumpyArray:198    # Convert to PIL-friendly format (H, W, C)199    if channel_first:200        img_hwc = image.transpose((1, 2, 0))201    else:202        img_hwc = image203 204    # Handle different dtypes205    if img_hwc.dtype == np.float32 or img_hwc.dtype == np.float64:206        # Assume normalized, scale to 0-255 for PIL207        img_hwc_scaled = (img_hwc * 255).astype(np.uint8)208        pil_img = Image.fromarray(img_hwc_scaled, mode="RGB")209        resized = pil_img.resize(size, resample)210        result = np.array(resized).astype(np.float32) / 255.0211    else:212        # uint8 or similar213        pil_img = Image.fromarray(img_hwc.astype(np.uint8), mode="RGB")214        resized = pil_img.resize(size, resample)215        result = np.array(resized)216 217    # Convert back to original format218    if channel_first:219        result = result.transpose((2, 0, 1))220 221    return result222 
codekingpro/portable-devtools · Team Ai