""" Geometry Primitives Library Geometric transforms: rotate, scale, flip, translate, remap. """ import numpy as np import cv2 def prim_translate(img, dx, dy): """Translate image by (dx, dy) pixels.""" h, w = img.shape[:2] M = np.float32([[1, 0, dx], [0, 1, dy]]) return cv2.warpAffine(img, M, (w, h)) def prim_rotate(img, angle, cx=None, cy=None): """Rotate image by angle degrees around center (cx, cy).""" h, w = img.shape[:2] if cx is None: cx = w / 2 if cy is None: cy = h / 2 M = cv2.getRotationMatrix2D((cx, cy), angle, 1.0) return cv2.warpAffine(img, M, (w, h)) def prim_scale(img, sx, sy, cx=None, cy=None): """Scale image by (sx, sy) around center (cx, cy).""" h, w = img.shape[:2] if cx is None: cx = w / 2 if cy is None: cy = h / 2 # Build transform matrix M = np.float32([ [sx, 0, cx * (1 - sx)], [0, sy, cy * (1 - sy)] ]) return cv2.warpAffine(img, M, (w, h)) def prim_flip_h(img): """Flip image horizontally.""" return cv2.flip(img, 1) def prim_flip_v(img): """Flip image vertically.""" return cv2.flip(img, 0) def prim_flip(img, direction="horizontal"): """Flip image in given direction.""" if direction in ("horizontal", "h"): return prim_flip_h(img) elif direction in ("vertical", "v"): return prim_flip_v(img) elif direction in ("both", "hv", "vh"): return cv2.flip(img, -1) return img def prim_transpose(img): """Transpose image (swap x and y).""" return np.transpose(img, (1, 0, 2)) def prim_remap(img, map_x, map_y): """Remap image using coordinate maps.""" return cv2.remap(img, map_x.astype(np.float32), map_y.astype(np.float32), cv2.INTER_LINEAR) def prim_make_coords(w, h): """Create coordinate grids for remapping.""" x = np.arange(w, dtype=np.float32) y = np.arange(h, dtype=np.float32) map_x, map_y = np.meshgrid(x, y) return (map_x, map_y) def prim_perspective(img, src_pts, dst_pts): """Apply perspective transform.""" src = np.float32(src_pts) dst = np.float32(dst_pts) M = cv2.getPerspectiveTransform(src, dst) h, w = img.shape[:2] return cv2.warpPerspective(img, M, (w, h)) def prim_affine(img, src_pts, dst_pts): """Apply affine transform using 3 point pairs.""" src = np.float32(src_pts) dst = np.float32(dst_pts) M = cv2.getAffineTransform(src, dst) h, w = img.shape[:2] return cv2.warpAffine(img, M, (w, h)) def _get_legacy_geometry_primitives(): """Import geometry primitives from legacy primitives module.""" from sexp_effects.primitives import ( prim_coords_x, prim_coords_y, prim_ripple_displace, prim_fisheye_displace, prim_kaleidoscope_displace, ) return { 'coords-x': prim_coords_x, 'coords-y': prim_coords_y, 'ripple-displace': prim_ripple_displace, 'fisheye-displace': prim_fisheye_displace, 'kaleidoscope-displace': prim_kaleidoscope_displace, } PRIMITIVES = { # Basic transforms 'translate': prim_translate, 'rotate-img': prim_rotate, 'scale-img': prim_scale, # Flips 'flip-h': prim_flip_h, 'flip-v': prim_flip_v, 'flip': prim_flip, 'transpose': prim_transpose, # Remapping 'remap': prim_remap, 'make-coords': prim_make_coords, # Advanced transforms 'perspective': prim_perspective, 'affine': prim_affine, # Displace / coordinate ops (from legacy primitives) **_get_legacy_geometry_primitives(), }