Venket / src /utils /transform_utils.py
venki101's picture
Add files using upload-large-folder tool
3f820d9 verified
Raw History Blame Contribute Delete
1.92 kB
"""Shared geometric raster transforms used by both placement and augmentation."""
from __future__ import annotations
import cv2
import numpy as np
def rotate_and_scale_rgba(rgba: np.ndarray, angle_deg: float, scale: float = 1.0) -> np.ndarray:
"""Rotate (and optionally scale) an RGBA image about its own center.
The output canvas automatically expands to tightly bound the rotated
rectangle so no content is clipped; newly exposed corners are fully
transparent.
"""
h, w = rgba.shape[:2]
if h == 0 or w == 0:
return rgba
cx, cy = w / 2.0, h / 2.0
matrix = cv2.getRotationMatrix2D((cx, cy), angle_deg, scale)
cos, sin = abs(matrix[0, 0]), abs(matrix[0, 1])
new_w = max(int(np.ceil(h * sin + w * cos)), 1)
new_h = max(int(np.ceil(h * cos + w * sin)), 1)
matrix[0, 2] += new_w / 2.0 - cx
matrix[1, 2] += new_h / 2.0 - cy
return cv2.warpAffine(
rgba, matrix, (new_w, new_h),
flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0, 0),
)
def smooth_noise_field(shape: tuple[int, int], rng: np.random.Generator, blur_frac: float = 0.08) -> np.ndarray:
"""Generate a smooth, low-frequency noise field in ``[0, 1]`` of the given ``(h, w)`` shape.
Built by upsampling coarse random noise, which is a fast and dependency-free
stand-in for Perlin/simplex noise -- adequate for subtle shading effects
like paper texture, discoloration, and ink fading.
"""
h, w = shape
coarse_h = max(int(h * blur_frac), 4)
coarse_w = max(int(w * blur_frac), 4)
coarse = rng.uniform(0.0, 1.0, size=(coarse_h, coarse_w)).astype(np.float32)
field = cv2.resize(coarse, (w, h), interpolation=cv2.INTER_CUBIC)
field = cv2.GaussianBlur(field, (0, 0), sigmaX=max(w, h) * 0.01 + 1)
field -= field.min()
max_val = field.max()
if max_val > 1e-6:
field /= max_val
return field