Files
test/effects/pixelate.py
gilesb 406cc7c0c7 Initial commit: video effects processing system
Add S-expression based video effects pipeline with modular effect
definitions, constructs, and recipe files.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 12:34:45 +00:00

73 lines
1.9 KiB
Python

# /// script
# requires-python = ">=3.10"
# dependencies = ["numpy", "opencv-python"]
# ///
"""
@effect pixelate
@version 1.0.0
@author artdag
@description
Pixelate effect. Reduces resolution to create blocky, retro pixel art
look. Great for 8-bit aesthetics.
@param block_size int
@range 2 64
@default 8
Size of pixel blocks. Larger = more pixelated.
@param maintain_edges bool
@default false
Try to preserve edges while pixelating.
@example
(effect pixelate :block_size 16)
@example
;; Beat-reactive pixelation
(effect pixelate :block_size (bind bass :range [4 32]))
"""
import numpy as np
import cv2
def process_frame(frame: np.ndarray, params: dict, state: dict) -> tuple:
"""
Apply pixelate effect to a video frame.
Args:
frame: Input frame as numpy array (H, W, 3) RGB uint8
params: Effect parameters
- block_size: pixel block size (default 8)
- maintain_edges: preserve edges (default False)
state: Persistent state dict
Returns:
Tuple of (processed_frame, new_state)
"""
block_size = max(2, min(int(params.get("block_size", 8)), 64))
maintain_edges = params.get("maintain_edges", False)
if state is None:
state = {}
h, w = frame.shape[:2]
# Scale down then up to create pixelation
small_h = max(1, h // block_size)
small_w = max(1, w // block_size)
small = cv2.resize(frame, (small_w, small_h), interpolation=cv2.INTER_AREA)
result = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)
if maintain_edges:
# Detect edges in original and overlay
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
edges = cv2.Canny(gray, 50, 150)
edges_dilated = cv2.dilate(edges, np.ones((2, 2), np.uint8))
edge_mask = edges_dilated > 0
result[edge_mask] = frame[edge_mask]
return result, state