Spaces:
Configuration error
Configuration error
from itertools import product | |
from math import ceil | |
from typing import Sequence, Union | |
import cv2 | |
import numpy as np | |
from custom_albumentations.augmentations.functional import convolve | |
from custom_albumentations.augmentations.geometric.functional import scale | |
from custom_albumentations.augmentations.utils import ( | |
_maybe_process_in_chunks, | |
clipped, | |
preserve_shape, | |
) | |
__all__ = ["blur", "median_blur", "gaussian_blur", "glass_blur"] | |
def blur(img: np.ndarray, ksize: int) -> np.ndarray: | |
blur_fn = _maybe_process_in_chunks(cv2.blur, ksize=(ksize, ksize)) | |
return blur_fn(img) | |
def median_blur(img: np.ndarray, ksize: int) -> np.ndarray: | |
if img.dtype == np.float32 and ksize not in {3, 5}: | |
raise ValueError(f"Invalid ksize value {ksize}. For a float32 image the only valid ksize values are 3 and 5") | |
blur_fn = _maybe_process_in_chunks(cv2.medianBlur, ksize=ksize) | |
return blur_fn(img) | |
def gaussian_blur(img: np.ndarray, ksize: int, sigma: float = 0) -> np.ndarray: | |
# When sigma=0, it is computed as `sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8` | |
blur_fn = _maybe_process_in_chunks(cv2.GaussianBlur, ksize=(ksize, ksize), sigmaX=sigma) | |
return blur_fn(img) | |
def glass_blur( | |
img: np.ndarray, sigma: float, max_delta: int, iterations: int, dxy: np.ndarray, mode: str | |
) -> np.ndarray: | |
x = cv2.GaussianBlur(np.array(img), sigmaX=sigma, ksize=(0, 0)) | |
if mode == "fast": | |
hs = np.arange(img.shape[0] - max_delta, max_delta, -1) | |
ws = np.arange(img.shape[1] - max_delta, max_delta, -1) | |
h: Union[int, np.ndarray] = np.tile(hs, ws.shape[0]) | |
w: Union[int, np.ndarray] = np.repeat(ws, hs.shape[0]) | |
for i in range(iterations): | |
dy = dxy[:, i, 0] | |
dx = dxy[:, i, 1] | |
x[h, w], x[h + dy, w + dx] = x[h + dy, w + dx], x[h, w] | |
elif mode == "exact": | |
for ind, (i, h, w) in enumerate( | |
product( | |
range(iterations), | |
range(img.shape[0] - max_delta, max_delta, -1), | |
range(img.shape[1] - max_delta, max_delta, -1), | |
) | |
): | |
ind = ind if ind < len(dxy) else ind % len(dxy) | |
dy = dxy[ind, i, 0] | |
dx = dxy[ind, i, 1] | |
x[h, w], x[h + dy, w + dx] = x[h + dy, w + dx], x[h, w] | |
else: | |
ValueError(f"Unsupported mode `{mode}`. Supports only `fast` and `exact`.") | |
return cv2.GaussianBlur(x, sigmaX=sigma, ksize=(0, 0)) | |
def defocus(img: np.ndarray, radius: int, alias_blur: float) -> np.ndarray: | |
length = np.arange(-max(8, radius), max(8, radius) + 1) | |
ksize = 3 if radius <= 8 else 5 | |
x, y = np.meshgrid(length, length) | |
aliased_disk = np.array((x**2 + y**2) <= radius**2, dtype=np.float32) | |
aliased_disk /= np.sum(aliased_disk) | |
kernel = gaussian_blur(aliased_disk, ksize, sigma=alias_blur) | |
return convolve(img, kernel=kernel) | |
def central_zoom(img: np.ndarray, zoom_factor: int) -> np.ndarray: | |
h, w = img.shape[:2] | |
h_ch, w_ch = ceil(h / zoom_factor), ceil(w / zoom_factor) | |
h_top, w_top = (h - h_ch) // 2, (w - w_ch) // 2 | |
img = scale(img[h_top : h_top + h_ch, w_top : w_top + w_ch], zoom_factor, cv2.INTER_LINEAR) | |
h_trim_top, w_trim_top = (img.shape[0] - h) // 2, (img.shape[1] - w) // 2 | |
return img[h_trim_top : h_trim_top + h, w_trim_top : w_trim_top + w] | |
def zoom_blur(img: np.ndarray, zoom_factors: Union[np.ndarray, Sequence[int]]) -> np.ndarray: | |
out = np.zeros_like(img, dtype=np.float32) | |
for zoom_factor in zoom_factors: | |
out += central_zoom(img, zoom_factor) | |
img = ((img + out) / (len(zoom_factors) + 1)).astype(img.dtype) | |
return img | |