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
+467
View File
@@ -0,0 +1,467 @@
"""Build and verify an immutable confirmatory batch for a SynthID oracle.
The batch contains a referenced untouched source plus four lossless PNG views:
an exact-pixel re-encode, aligned periodic-tile subtraction, a cyclically
shifted tile, and an orthogonal random tile. Building the batch performs no
network requests. Oracle results remain empty until a separately authorized
submission records them.
"""
from __future__ import annotations
import json
import logging
import math
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING
import click
from PIL import Image
from synthid_periodic_tile_ablation import (
candidate_quality,
control_templates,
phase_score_pixels,
tile_score_pixels,
)
from synthid_periodic_tile_probe import PeriodicTileModel
from synthid_periodic_tile_probe import load_model as load_tile_model
from synthid_phase_carrier import PhaseCarrierModel
from synthid_phase_carrier import load_model as load_phase_model
from synthid_pixel_attack import load_rgb
from synthid_research_manifest import artifact_sha256, pixel_fingerprint
from synthid_tile_attack import subtract_tiled_template
if TYPE_CHECKING:
import numpy as np
log = logging.getLogger(__name__)
ROLE_ORDER = ("source", "reencode_control", "aligned", "shifted", "orthogonal_random")
DERIVATIVE_ROLES = ROLE_ORDER[1:]
FORMAT_VERSION = 1
SYNTHID_RESULTS = {"detected", "not_detected", "indeterminate", "refused"}
C2PA_RESULTS = {"present", "absent", "indeterminate", "unavailable"}
def _inside(path: Path, parent: Path) -> bool:
"""Return whether resolved PATH is inside resolved PARENT."""
try:
path.resolve().relative_to(parent.resolve())
except ValueError:
return False
return True
def _json_float(value: float) -> float | None:
"""Return finite VALUE or None for JSON interoperability."""
return value if math.isfinite(value) else None
def _write_png(path: Path, pixels: np.ndarray) -> None:
"""Write exact RGB PIXELS as a deterministic lossless PNG."""
path.parent.mkdir(parents=True, exist_ok=True)
if path.exists():
raise ValueError(f"refusing to overwrite oracle artifact: {path}")
Image.fromarray(pixels, mode="RGB").save(path, format="PNG", compress_level=9)
def _score_row(
pixels: np.ndarray,
*,
source: np.ndarray,
tile_model: PeriodicTileModel,
phase_model: PhaseCarrierModel,
tile_threshold: float,
phase_threshold: float,
active_threshold: float,
) -> dict[str, object]:
"""Return local frozen scores and paired fidelity for PIXELS."""
tile_score = tile_score_pixels(pixels, tile_model)
phase_score, active_support = phase_score_pixels(pixels, phase_model)
quality = candidate_quality(source, pixels)
return {
"tile_score": tile_score,
"tile_accepted": tile_score >= tile_threshold,
"phase_score": phase_score,
"active_support": active_support,
"phase_accepted": phase_score >= phase_threshold and active_support >= active_threshold,
"residual_rms": quality["residual_rms"],
"psnr_db": _json_float(quality["psnr_db"]),
"ssim": quality["ssim"],
"changed_pixel_fraction": quality["changed_pixel_fraction"],
}
def _artifact_row(
path: Path,
*,
role: str,
source_id: str,
in_batch: bool,
batch_root: Path,
scores: dict[str, object],
) -> dict[str, object]:
"""Return one hash-frozen manifest row for PATH."""
pixel_sha256, width, height = pixel_fingerprint(path)
return {
"source_id": source_id,
"role": role,
"path": str(path.relative_to(batch_root) if in_batch else path.resolve()),
"in_batch": in_batch,
"artifact_sha256": artifact_sha256(path),
"pixel_sha256": pixel_sha256,
"width": width,
"height": height,
"synthid_result": None,
"c2pa_result": None,
"submitted_at": None,
**scores,
}
def build_batch(
sources: list[Path],
*,
output_dir: Path,
tile_model_path: Path,
phase_model_path: Path,
tile_threshold: float,
phase_threshold: float,
active_threshold: float,
strength: float,
seed: int,
provider: str,
repository_root: Path,
) -> Path:
"""Build a preregistered, unsubmitted oracle batch and return its manifest."""
if not sources:
raise ValueError("at least one source is required")
if strength <= 0.0 or not math.isfinite(strength):
raise ValueError("strength must be finite and positive")
if provider not in {"google", "openai"}:
raise ValueError("provider must be google or openai")
if _inside(output_dir, repository_root):
raise ValueError("oracle batches must be written outside the repository")
if output_dir.exists() and any(output_dir.iterdir()):
raise ValueError("output directory must not already contain files")
output_dir.mkdir(parents=True, exist_ok=True)
tile_model = load_tile_model(tile_model_path)
phase_model = load_phase_model(phase_model_path)
if (tile_model.height, tile_model.width) != (phase_model.height, phase_model.width):
raise ValueError("tile and phase model geometries differ")
templates = control_templates(tile_model.template, seed=seed)
rows: list[dict[str, object]] = []
seen_source_hashes: set[str] = set()
for source_path in sources:
source_hash = artifact_sha256(source_path)
if source_hash in seen_source_hashes:
raise ValueError("duplicate source artifact")
seen_source_hashes.add(source_hash)
source = load_rgb(source_path)
if source.shape != (tile_model.height, tile_model.width, 3):
raise ValueError(f"{source_path}: geometry does not match the frozen models")
source_id = source_hash[:16]
score_args = {
"source": source,
"tile_model": tile_model,
"phase_model": phase_model,
"tile_threshold": tile_threshold,
"phase_threshold": phase_threshold,
"active_threshold": active_threshold,
}
source_scores = _score_row(source, **score_args)
rows.append(
_artifact_row(
source_path,
role="source",
source_id=source_id,
in_batch=False,
batch_root=output_dir,
scores=source_scores,
)
)
for role in DERIVATIVE_ROLES:
variant = (
source
if role == "reencode_control"
else subtract_tiled_template(
source,
templates[role] * tile_model.expected_norm,
strength=strength,
)
)
output_path = output_dir / source_id / f"{role}.png"
_write_png(output_path, variant)
rows.append(
_artifact_row(
output_path,
role=role,
source_id=source_id,
in_batch=True,
batch_root=output_dir,
scores=(source_scores if role == "reencode_control" else _score_row(variant, **score_args)),
)
)
manifest = {
"format_version": FORMAT_VERSION,
"status": "preregistered_unsubmitted",
"source_count": len(sources),
"request_count": len(rows),
"request_order": ROLE_ORDER,
"provider": provider,
"decision_rule": (
"Count causal success only when source, reencode_control, shifted, and "
"orthogonal_random are detected in the matching provider SynthID oracle, "
"aligned is not_detected, and indeterminate is never treated as negative."
),
"strength": strength,
"seed": seed,
"tile_threshold": tile_threshold,
"phase_threshold": phase_threshold,
"active_threshold": active_threshold,
"tile_model": str(tile_model_path.resolve()),
"tile_model_sha256": artifact_sha256(tile_model_path),
"phase_model": str(phase_model_path.resolve()),
"phase_model_sha256": artifact_sha256(phase_model_path),
"rows": rows,
}
manifest_path = output_dir / "manifest.json"
manifest_path.write_text(json.dumps(manifest, indent=2, allow_nan=False) + "\n", encoding="utf-8")
manifest_hash = artifact_sha256(manifest_path)
(output_dir / "manifest.sha256").write_text(manifest_hash + " manifest.json\n", encoding="utf-8")
results_template = {
"format_version": FORMAT_VERSION,
"manifest_sha256": manifest_hash,
"provider": provider,
"rows": [
{
"source_id": row["source_id"],
"role": row["role"],
"artifact_sha256": row["artifact_sha256"],
"synthid_result": None,
"c2pa_result": None,
"raw_response": None,
"submitted_at": None,
}
for row in rows
],
}
(output_dir / "results-template.json").write_text(
json.dumps(results_template, indent=2) + "\n",
encoding="utf-8",
)
verify_batch(manifest_path, repository_root=repository_root)
return manifest_path
def verify_batch(manifest_path: Path, *, repository_root: Path) -> dict[str, object]:
"""Verify manifest, model, source, and derivative hashes without mutation."""
batch_root = manifest_path.parent
if _inside(batch_root, repository_root):
raise ValueError("oracle batches must remain outside the repository")
digest_path = batch_root / "manifest.sha256"
expected_manifest_hash = digest_path.read_text(encoding="utf-8").split()[0]
if artifact_sha256(manifest_path) != expected_manifest_hash:
raise ValueError("manifest hash mismatch")
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
if manifest.get("format_version") != FORMAT_VERSION:
raise ValueError("unsupported oracle-batch manifest version")
rows = manifest.get("rows")
if not isinstance(rows, list) or len(rows) != manifest.get("request_count"):
raise ValueError("manifest request count mismatch")
if artifact_sha256(Path(manifest["tile_model"])) != manifest["tile_model_sha256"]:
raise ValueError("tile model hash mismatch")
if artifact_sha256(Path(manifest["phase_model"])) != manifest["phase_model_sha256"]:
raise ValueError("phase model hash mismatch")
groups: dict[str, list[str]] = {}
artifact_hashes: set[str] = set()
for row in rows:
source_id = str(row["source_id"])
groups.setdefault(source_id, []).append(str(row["role"]))
path = batch_root / str(row["path"]) if row["in_batch"] else Path(str(row["path"]))
if artifact_sha256(path) != row["artifact_sha256"]:
raise ValueError(f"artifact hash mismatch for {source_id}/{row['role']}")
pixel_sha256, width, height = pixel_fingerprint(path)
if (pixel_sha256, width, height) != (row["pixel_sha256"], row["width"], row["height"]):
raise ValueError(f"pixel fingerprint mismatch for {source_id}/{row['role']}")
artifact_hashes.add(str(row["artifact_sha256"]))
if any(tuple(roles) != ROLE_ORDER for roles in groups.values()):
raise ValueError("each source must have the fixed request-role order")
if len(groups) != manifest.get("source_count"):
raise ValueError("manifest source count mismatch")
if len(artifact_hashes) < len(rows) - len(groups):
raise ValueError("unexpected duplicate derivative artifacts")
template = json.loads((batch_root / "results-template.json").read_text(encoding="utf-8"))
expected_identities = [(row["source_id"], row["role"], row["artifact_sha256"]) for row in rows]
template_identities = [(row["source_id"], row["role"], row["artifact_sha256"]) for row in template.get("rows", [])]
if template.get("manifest_sha256") != expected_manifest_hash or template.get("provider") != manifest["provider"]:
raise ValueError("results template does not identify the preregistered batch")
if template_identities != expected_identities:
raise ValueError("results template row identities differ from the manifest")
return manifest
def _parse_submitted_at(value: object) -> None:
"""Reject timestamps that are absent or not timezone-aware ISO-8601."""
if not isinstance(value, str):
raise ValueError("submitted_at must be a timezone-aware ISO-8601 timestamp")
try:
parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError as error:
raise ValueError("submitted_at must be a timezone-aware ISO-8601 timestamp") from error
if parsed.tzinfo is None:
raise ValueError("submitted_at must be a timezone-aware ISO-8601 timestamp")
def evaluate_results(
manifest_path: Path,
results_path: Path,
*,
repository_root: Path,
) -> dict[str, object]:
"""Validate a complete result file and apply the preregistered decision rule."""
manifest = verify_batch(manifest_path, repository_root=repository_root)
results = json.loads(results_path.read_text(encoding="utf-8"))
manifest_hash = artifact_sha256(manifest_path)
if results.get("format_version") != FORMAT_VERSION:
raise ValueError("unsupported oracle-results version")
if results.get("manifest_sha256") != manifest_hash or results.get("provider") != manifest["provider"]:
raise ValueError("results do not identify the preregistered batch")
manifest_rows = manifest["rows"]
result_rows = results.get("rows")
if not isinstance(result_rows, list) or len(result_rows) != len(manifest_rows):
raise ValueError("oracle results must cover every preregistered request")
grouped: dict[str, dict[str, str]] = {}
for expected, result in zip(manifest_rows, result_rows, strict=True):
identity = (result.get("source_id"), result.get("role"), result.get("artifact_sha256"))
expected_identity = (expected["source_id"], expected["role"], expected["artifact_sha256"])
if identity != expected_identity:
raise ValueError("oracle result order or artifact identity differs from the manifest")
synthid_result = result.get("synthid_result")
c2pa_result = result.get("c2pa_result")
if synthid_result not in SYNTHID_RESULTS:
raise ValueError("invalid or missing SynthID result")
if c2pa_result not in C2PA_RESULTS:
raise ValueError("invalid or missing C2PA result")
if not isinstance(result.get("raw_response"), str) or not result["raw_response"].strip():
raise ValueError("raw_response must preserve the nonempty verbatim oracle result")
_parse_submitted_at(result.get("submitted_at"))
grouped.setdefault(str(expected["source_id"]), {})[str(expected["role"])] = str(synthid_result)
source_results: list[dict[str, str]] = []
for source_id, roles in grouped.items():
if tuple(roles) != ROLE_ORDER:
raise ValueError("oracle results do not preserve the fixed role order")
values = set(roles.values())
if values & {"indeterminate", "refused"}:
verdict = "indeterminate"
elif (
roles["source"] == "detected"
and roles["reencode_control"] == "detected"
and roles["shifted"] == "detected"
and roles["orthogonal_random"] == "detected"
and roles["aligned"] == "not_detected"
):
verdict = "causal_success"
elif any(roles[role] != "detected" for role in ("source", "reencode_control", "shifted", "orthogonal_random")):
verdict = "control_failed"
else:
verdict = "aligned_still_detected"
source_results.append({"source_id": source_id, "verdict": verdict})
counts = {
verdict: sum(row["verdict"] == verdict for row in source_results)
for verdict in ("causal_success", "aligned_still_detected", "control_failed", "indeterminate")
}
return {
"format_version": FORMAT_VERSION,
"manifest_sha256": manifest_hash,
"provider": manifest["provider"],
"source_count": manifest["source_count"],
"counts": counts,
"sources": source_results,
}
@click.group()
def main() -> None:
"""Build and verify an immutable confirmatory oracle batch."""
logging.basicConfig(level=logging.INFO, format="%(message)s")
@main.command("build")
@click.argument("tile_model_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.argument("phase_model_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.argument("sources", nargs=-1, required=True, type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.option("--output-dir", type=click.Path(file_okay=False, path_type=Path), required=True)
@click.option("--tile-threshold", type=float, required=True)
@click.option("--phase-threshold", type=float, required=True)
@click.option("--active-threshold", type=float, required=True)
@click.option("--strength", type=click.FloatRange(min=0.0, min_open=True), default=2.0, show_default=True)
@click.option("--seed", type=int, default=20260810, show_default=True)
@click.option("--provider", type=click.Choice(["google", "openai"]), required=True)
def build_command(
tile_model_path: Path,
phase_model_path: Path,
sources: tuple[Path, ...],
output_dir: Path,
tile_threshold: float,
phase_threshold: float,
active_threshold: float,
strength: float,
seed: int,
provider: str,
) -> None:
"""Build a frozen batch from exact-geometry SOURCES."""
manifest = build_batch(
list(sources),
output_dir=output_dir,
tile_model_path=tile_model_path,
phase_model_path=phase_model_path,
tile_threshold=tile_threshold,
phase_threshold=phase_threshold,
active_threshold=active_threshold,
strength=strength,
seed=seed,
provider=provider,
repository_root=Path(__file__).resolve().parent.parent,
)
log.info("Wrote preregistered oracle batch: %s", manifest)
@main.command("verify")
@click.argument("manifest_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
def verify_command(manifest_path: Path) -> None:
"""Verify an existing batch without changing it."""
manifest = verify_batch(manifest_path, repository_root=Path(__file__).resolve().parent.parent)
log.info("Verified %d immutable oracle requests", manifest["request_count"])
@main.command("evaluate")
@click.argument("manifest_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.argument("results_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.option("--report-out", type=click.Path(dir_okay=False, path_type=Path), required=True)
def evaluate_command(manifest_path: Path, results_path: Path, report_out: Path) -> None:
"""Validate RESULTS_PATH and write the preregistered batch verdict."""
repository_root = Path(__file__).resolve().parent.parent
if _inside(report_out, repository_root):
raise click.BadParameter("oracle result reports must be written outside the repository")
report = evaluate_results(
manifest_path,
results_path,
repository_root=repository_root,
)
report_out.parent.mkdir(parents=True, exist_ok=True)
if report_out.exists():
raise click.BadParameter("refusing to overwrite an oracle result report")
report_out.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
log.info("Wrote oracle batch verdict: %s", report_out)
if __name__ == "__main__":
main()
+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:
+288
View File
@@ -0,0 +1,288 @@
"""Measure whether a frozen periodic tile causally controls local carrier scores.
This harness compares subtraction of the learned tile with cyclically shifted
and orthogonal random tiles of the same norm. It measures local research
detectors only. A score reversal is not evidence that a provider oracle would
stop detecting SynthID.
"""
from __future__ import annotations
import json
import logging
import math
from collections import defaultdict
from pathlib import Path
import click
import numpy as np
from synthid_periodic_tile import unit_tile
from synthid_periodic_tile_probe import PeriodicTileModel
from synthid_periodic_tile_probe import load_model as load_tile_model
from synthid_periodic_tile_probe import score_pixels as score_tile_pixels
from synthid_phase_carrier import PhaseCarrierModel, score_pixels
from synthid_phase_carrier import load_model as load_phase_model
from synthid_pixel_attack import load_rgb, measure
from synthid_research_manifest import artifact_sha256
from synthid_tile_attack import parse_positive_floats, subtract_tiled_template
log = logging.getLogger(__name__)
def exact_sign_test(negative: int, positive: int) -> float:
"""Return an exact two-sided sign-test p-value after excluding ties."""
count = negative + positive
if count == 0:
return 1.0
tail = sum(math.comb(count, index) for index in range(min(negative, positive) + 1)) / 2**count
return min(1.0, 2.0 * tail)
def control_templates(template: np.ndarray, *, seed: int) -> dict[str, np.ndarray]:
"""Return aligned, shifted, and norm-matched orthogonal control tiles."""
rng = np.random.default_rng(seed)
random_tile = rng.normal(size=template.shape)
random_tile -= np.mean(random_tile, axis=(0, 1), keepdims=True)
random_tile -= np.sum(random_tile * template) * template
random_tile, norm = unit_tile(random_tile)
if norm == 0.0 or abs(float(np.sum(random_tile * template))) > 1e-12:
raise ValueError("could not construct an orthogonal random control")
return {
"aligned": template,
"shifted": np.roll(template, shift=(1, 1), axis=(0, 1)),
"orthogonal_random": random_tile,
}
def phase_score_pixels(pixels: np.ndarray, model: PhaseCarrierModel) -> tuple[float, float]:
"""Return the unregistered phase score and active support for PIXELS."""
result = score_pixels(pixels, model)
return result.score, result.active_weight_fraction
def tile_score_pixels(pixels: np.ndarray, model: PeriodicTileModel) -> float:
"""Return the fixed-phase periodic-tile score for PIXELS."""
return score_tile_pixels(pixels, model).score
def summarize(values: list[float]) -> dict[str, float]:
"""Return bounded descriptive statistics for VALUES."""
return {
"minimum": float(np.min(values)),
"median": float(np.median(values)),
"maximum": float(np.max(values)),
}
def direction_summary(values: list[float]) -> dict[str, float | int]:
"""Return direction counts and a two-sided sign test for VALUES."""
negative = sum(value < 0.0 for value in values)
positive = sum(value > 0.0 for value in values)
return {
"negative": negative,
"positive": positive,
"ties": len(values) - negative - positive,
"two_sided_sign_p": exact_sign_test(negative, positive),
}
def candidate_quality(reference: np.ndarray, candidate: np.ndarray) -> dict[str, float]:
"""Return paired fidelity metrics for one equal-geometry candidate."""
measurement = measure(reference, candidate, name="candidate", path=Path("<memory>"))
return {
"residual_rms": measurement.residual_rms,
"psnr_db": measurement.psnr_db,
"ssim": measurement.ssim,
"changed_pixel_fraction": measurement.changed_pixel_fraction,
}
def run_ablation(
sources: list[Path],
*,
tile_model: PeriodicTileModel,
phase_model: PhaseCarrierModel,
tile_threshold: float,
phase_threshold: float,
active_threshold: float,
strengths: tuple[float, ...],
phase_strength: float,
seed: int,
) -> dict[str, object]:
"""Evaluate aligned subtraction and controls on exact-geometry SOURCES."""
if not sources:
raise ValueError("at least one source is required")
if phase_strength not in strengths:
raise ValueError("phase strength must be one of the swept strengths")
if (tile_model.height, tile_model.width) != (phase_model.height, phase_model.width):
raise ValueError("tile and phase model geometries differ")
if not all(np.isfinite(value) for value in (tile_threshold, phase_threshold, active_threshold)):
raise ValueError("thresholds must be finite")
templates = control_templates(tile_model.template, seed=seed)
rows: list[dict[str, object]] = []
for source_path in sources:
source = load_rgb(source_path)
if source.shape != (tile_model.height, tile_model.width, 3):
raise ValueError(f"{source_path}: geometry does not match the models")
source_hash = artifact_sha256(source_path)
original_tile = tile_score_pixels(source, tile_model)
original_phase, original_support = phase_score_pixels(source, phase_model)
for strength in strengths:
for control, template in templates.items():
candidate = subtract_tiled_template(
source,
template * tile_model.expected_norm,
strength=strength,
)
tile_score = tile_score_pixels(candidate, tile_model)
row: dict[str, object] = {
"path": str(source_path),
"artifact_sha256": source_hash,
"control": control,
"strength": strength,
"original_tile_score": original_tile,
"tile_score": tile_score,
"tile_delta": tile_score - original_tile,
"tile_accepted": tile_score >= tile_threshold,
"original_phase_score": original_phase,
"original_active_support": original_support,
}
if strength == phase_strength:
phase_score, active_support = phase_score_pixels(candidate, phase_model)
row.update(
{
**candidate_quality(source, candidate),
"phase_score": phase_score,
"active_support": active_support,
"phase_delta": phase_score - original_phase,
"phase_accepted": phase_score >= phase_threshold and active_support >= active_threshold,
}
)
rows.append(row)
grouped: dict[tuple[str, float], list[dict[str, object]]] = defaultdict(list)
for row in rows:
grouped[(str(row["control"]), float(row["strength"]))].append(row)
tile_summaries: list[dict[str, object]] = []
for (control, strength), group in sorted(grouped.items()):
deltas = [float(row["tile_delta"]) for row in group]
tile_summaries.append(
{
"control": control,
"strength": strength,
"accepted": sum(bool(row["tile_accepted"]) for row in group),
"delta": summarize(deltas),
"direction": direction_summary(deltas),
}
)
selected = [row for row in rows if float(row["strength"]) == phase_strength]
phase_summaries: list[dict[str, object]] = []
for control in templates:
group = [row for row in selected if row["control"] == control]
phase_summaries.append(
{
"control": control,
"accepted": sum(bool(row["phase_accepted"]) for row in group),
"delta": summarize([float(row["phase_delta"]) for row in group]),
"active_support": summarize([float(row["active_support"]) for row in group]),
"psnr_db": summarize([float(row["psnr_db"]) for row in group]),
"ssim": summarize([float(row["ssim"]) for row in group]),
"changed_pixel_fraction": summarize([float(row["changed_pixel_fraction"]) for row in group]),
}
)
paired_comparisons: list[dict[str, object]] = []
for control in ("shifted", "orthogonal_random"):
for metric in ("tile_delta", "phase_delta"):
aligned = {
str(row["artifact_sha256"]): float(row[metric]) for row in selected if row["control"] == "aligned"
}
comparison = {
str(row["artifact_sha256"]): float(row[metric]) for row in selected if row["control"] == control
}
differences = [aligned[key] - comparison[key] for key in sorted(aligned)]
paired_comparisons.append(
{
"aligned_minus": control,
"metric": metric,
"difference": summarize(differences),
"direction": direction_summary(differences),
}
)
return {
"source_count": len(sources),
"tile_threshold": tile_threshold,
"phase_threshold": phase_threshold,
"active_threshold": active_threshold,
"strengths": strengths,
"phase_strength": phase_strength,
"seed": seed,
"original": {
"tile_accepted": sum(
float(row["original_tile_score"]) >= tile_threshold for row in selected if row["control"] == "aligned"
),
"phase_accepted": sum(
float(row["original_phase_score"]) >= phase_threshold
and float(row["original_active_support"]) >= active_threshold
for row in selected
if row["control"] == "aligned"
),
},
"tile_summaries": tile_summaries,
"phase_summaries": phase_summaries,
"paired_comparisons": paired_comparisons,
"items": rows,
}
@click.command()
@click.argument("tile_model_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.argument("phase_model_path", type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.argument("sources", nargs=-1, required=True, type=click.Path(exists=True, dir_okay=False, path_type=Path))
@click.option("--tile-threshold", type=float, required=True)
@click.option("--phase-threshold", type=float, required=True)
@click.option("--active-threshold", type=float, required=True)
@click.option("--strengths", default="1,1.5,2,3,4", show_default=True)
@click.option("--phase-strength", type=click.FloatRange(min=0.0, min_open=True), default=2.0, show_default=True)
@click.option("--seed", type=int, default=20260810, show_default=True)
@click.option("--report-out", type=click.Path(dir_okay=False, path_type=Path), required=True)
def main(
tile_model_path: Path,
phase_model_path: Path,
sources: tuple[Path, ...],
tile_threshold: float,
phase_threshold: float,
active_threshold: float,
strengths: str,
phase_strength: float,
seed: int,
report_out: Path,
) -> None:
"""Run a fixed periodic-tile causal ablation on exact-geometry SOURCES."""
logging.basicConfig(level=logging.INFO, format="%(message)s")
strength_values = parse_positive_floats(strengths, option_name="strengths")
report = run_ablation(
list(sources),
tile_model=load_tile_model(tile_model_path),
phase_model=load_phase_model(phase_model_path),
tile_threshold=tile_threshold,
phase_threshold=phase_threshold,
active_threshold=active_threshold,
strengths=strength_values,
phase_strength=phase_strength,
seed=seed,
)
report["tile_model"] = str(tile_model_path)
report["tile_model_sha256"] = artifact_sha256(tile_model_path)
report["phase_model"] = str(phase_model_path)
report["phase_model_sha256"] = artifact_sha256(phase_model_path)
report_out.parent.mkdir(parents=True, exist_ok=True)
report_out.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
log.info("Wrote periodic-tile causal ablation: %s", report_out)
if __name__ == "__main__":
main()
+18 -4
View File
@@ -92,10 +92,18 @@ def discover_model(
)
def score_image(path: Path, model: PeriodicTileModel, *, register: bool = False) -> PeriodicTileScore:
"""Score PATH against MODEL, optionally searching cyclic tile shifts."""
def score_pixels(
pixels: np.ndarray,
model: PeriodicTileModel,
*,
register: bool = False,
path: str = "<array>",
) -> PeriodicTileScore:
"""Score exact-geometry RGB PIXELS, optionally searching cyclic tile shifts."""
if pixels.shape != (model.height, model.width, 3):
raise ValueError("pixel geometry does not match periodic-tile model")
folded = fold_residual_template(
_load_rgb(path, height=model.height, width=model.width),
pixels,
tile_height=model.tile_height,
tile_width=model.tile_width,
denoise_sigma=model.denoise_sigma,
@@ -109,7 +117,7 @@ def score_image(path: Path, model: PeriodicTileModel, *, register: bool = False)
score = float(np.sum(model.template * unit))
row_shift = column_shift = 0
return PeriodicTileScore(
path=str(path),
path=path,
score=score,
active_support=min(norm / (model.expected_norm + 1e-12), 1.0),
row_shift=row_shift,
@@ -118,6 +126,12 @@ def score_image(path: Path, model: PeriodicTileModel, *, register: bool = False)
)
def score_image(path: Path, model: PeriodicTileModel, *, register: bool = False) -> PeriodicTileScore:
"""Score PATH against MODEL, optionally searching cyclic tile shifts."""
pixels = _load_rgb(path, height=model.height, width=model.width)
return score_pixels(pixels, model, register=register, path=str(path))
def calibrate_threshold(paths: list[Path], model: PeriodicTileModel, *, register: bool = False) -> float:
"""Return the first float above every negative score in PATHS."""
if not paths:
+22 -15
View File
@@ -179,6 +179,27 @@ def _frequency_values(pixels: np.ndarray, model: PhaseCarrierModel) -> np.ndarra
return extract_frequency_values(pixels, model.rows, model.columns, model.channels)
def score_pixels(pixels: np.ndarray, model: PhaseCarrierModel, *, path: str = "<array>") -> PhaseCarrierScore:
"""Score exact-geometry RGB PIXELS against MODEL."""
if pixels.shape != (model.height, model.width, 3):
raise ValueError("pixel geometry does not match phase-carrier model")
values = _frequency_values(np.asarray(pixels, dtype=np.float64), model)
magnitude_gate = np.minimum(np.abs(values) / (model.expected_magnitudes + 1e-12), 1.0)
active_weights = model.weights * magnitude_gate
active_weight = float(np.sum(active_weights))
score = (
0.0
if active_weight == 0.0
else float(np.sum(active_weights * np.cos(np.angle(values) - model.phases)) / active_weight)
)
return PhaseCarrierScore(
path=path,
score=score,
active_weight_fraction=active_weight,
peak_count=len(model.rows),
)
def score_image(
path: Path,
model: PhaseCarrierModel,
@@ -192,21 +213,7 @@ def score_image(
width=model.width,
canonicalize_geometry=canonicalize_geometry,
)
values = _frequency_values(pixels, model)
magnitude_gate = np.minimum(np.abs(values) / (model.expected_magnitudes + 1e-12), 1.0)
active_weights = model.weights * magnitude_gate
active_weight = float(np.sum(active_weights))
score = (
0.0
if active_weight == 0.0
else float(np.sum(active_weights * np.cos(np.angle(values) - model.phases)) / active_weight)
)
return PhaseCarrierScore(
path=str(path),
score=score,
active_weight_fraction=active_weight,
peak_count=len(model.rows),
)
return score_pixels(pixels, model, path=str(path))
def score_translations(