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>
This commit is contained in:
72
effects/pixelate.py
Normal file
72
effects/pixelate.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# /// 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
|
||||
Reference in New Issue
Block a user