Add calibrated SynthID pixel detector

This commit is contained in:
Victor Kuznetsov
2026-08-11 11:09:55 -07:00
parent 7091d73f2e
commit 8a648794ad
32 changed files with 2394 additions and 146 deletions
+3 -41
View File
@@ -1,50 +1,12 @@
"""Shared periodic-residual helpers for SynthID research probes."""
"""Compatibility imports for shared periodic-residual helpers."""
from __future__ import annotations
import cv2
import numpy as np
from remove_ai_watermarks.synthid_detector import fold_residual_template, unit_tile
def fold_residual_template(
pixels: np.ndarray,
*,
tile_height: int,
tile_width: int,
denoise_sigma: float,
) -> np.ndarray:
"""Estimate a zero-mean periodic residual template by modulo folding."""
if pixels.ndim != 3 or pixels.shape[2] != 3:
raise ValueError("pixels must have shape (height, width, 3)")
if tile_height < 1 or tile_width < 1 or denoise_sigma <= 0.0:
raise ValueError("tile dimensions and denoise sigma must be positive")
height, width = pixels.shape[:2]
if height % tile_height != 0 or width % tile_width != 0:
raise ValueError("image geometry must be divisible by the tile geometry")
source = pixels.astype(np.float32)
denoised = cv2.GaussianBlur(
source,
(0, 0),
sigmaX=denoise_sigma,
sigmaY=denoise_sigma,
borderType=cv2.BORDER_REFLECT_101,
)
residual = source - denoised
repeats_y = height // tile_height
repeats_x = width // tile_width
folded = residual.reshape(repeats_y, tile_height, repeats_x, tile_width, 3).mean(
axis=(0, 2),
dtype=np.float64,
)
return folded - np.mean(folded, axis=(0, 1), keepdims=True)
def unit_tile(tile: np.ndarray) -> tuple[np.ndarray, float]:
"""Return TILE normalized by its L2 norm and the original norm."""
norm = float(np.linalg.norm(tile))
if norm == 0.0:
return np.zeros_like(tile, dtype=np.float64), 0.0
return np.asarray(tile, dtype=np.float64) / norm, norm
__all__ = ["cyclic_tile_correlations", "fold_residual_template", "unit_tile"]
def cyclic_tile_correlations(template: np.ndarray, tile: np.ndarray) -> np.ndarray: