Yashp2003/repro-hector-artifacts / scripts /verify_claim_3_stam.py
Yashp2003's picture
download
raw
4.66 kB
#!/usr/bin/env python3
"""Verify Claim 3: STAM uses inverse warping and Gaussian masking."""
import torch
import torch.nn.functional as F
import torch.nn as nn
import numpy as np
import json
import sys
def gaussian_blur_2d(tensor, sigma=2.0):
"""Apply 2D Gaussian blur to each frame independently."""
B, C, H, W = tensor.shape
device = tensor.device
k = int(sigma * 4) | 1
if k < 3:
return tensor
x = torch.arange(k, device=device).float() - k // 2
gauss_1d = torch.exp(-x**2 / (2 * sigma**2))
gauss_1d = gauss_1d / gauss_1d.sum()
kernel = gauss_1d[:, None] * gauss_1d[None, :]
kernel = kernel.view(1, 1, k, k).repeat(C, 1, 1, 1)
padding = k // 2
return F.conv2d(F.pad(tensor, (padding, padding, padding, padding), mode='replicate'), kernel, groups=C)
def test_stam():
results = {
"claim": "Spatio-Temporal Alignment Module (STAM)",
"status": "PASS",
"details": [],
"metrics": {}
}
device = "cuda" if torch.cuda.is_available() else "cpu"
B, C, T, H, W = 1, 4, 8, 32, 32
trajectories = torch.zeros(T, 2).to(device)
scales = torch.ones(T).to(device)
for t in range(T):
trajectories[t] = torch.tensor([-0.8 + 1.6 * t / (T-1), 0.0]).to(device)
feat = torch.randn(B, C, T, H, W).to(device)
warped = []
for t in range(T):
p_t = trajectories[t]
s_t = scales[t]
grid_y, grid_x = torch.meshgrid(
torch.linspace(-1, 1, H, device=device),
torch.linspace(-1, 1, W, device=device),
indexing='ij'
)
grid_base = torch.stack([grid_x, grid_y], dim=-1)
grid = (grid_base - p_t.view(1, 1, 2)) / (s_t + 1e-6)
w = F.grid_sample(
feat[:, :, t:t+1, :, :].reshape(B, C, H, W),
grid.unsqueeze(0).expand(B, H, W, 2),
mode='bilinear', padding_mode='zeros', align_corners=False
).reshape(B, C, 1, H, W)
warped.append(w)
warped = torch.cat(warped, dim=2)
assert warped.shape == (B, C, T, H, W)
results["details"].append("Inverse warping: per-frame grid sampling \u2713")
mask = (torch.rand(B, 1, T, H, W) > 0.7).float().to(device)
gaussian_masks = []
for t in range(T):
blurred = gaussian_blur_2d(mask[:, :, t], sigma=2.0)
gaussian_masks.append(torch.sigmoid(blurred * 5.0).unsqueeze(2))
gaussian_mask = torch.cat(gaussian_masks, dim=2)
def edge_content(m):
gx = torch.abs(m[:, :, :, :, :-1] - m[:, :, :, :, 1:]).mean()
gy = torch.abs(m[:, :, :, :-1, :] - m[:, :, :, 1:, :]).mean()
return (gx + gy).item()
binary_edges = edge_content(mask)
gaussian_edges = edge_content(gaussian_mask)
results["metrics"]["binary_mask_edges"] = round(binary_edges, 4)
results["metrics"]["gaussian_mask_edges"] = round(gaussian_edges, 4)
assert gaussian_edges < binary_edges, "Gaussian mask should have smoother edges"
results["details"].append(f"Gaussian mask reduces edge artifacts ({gaussian_edges:.4f} vs {binary_edges:.4f}) \u2713")
M_i = torch.sigmoid(torch.randn(B, 1, T, H, W)).to(device)
M_v = torch.sigmoid(torch.randn(B, 1, T, H, W)).to(device)
M_union = torch.clamp(M_i + M_v, 0, 1)
mask_4ch = torch.cat([M_i, M_v, M_union, M_union], dim=1)
assert mask_4ch.shape == (B, 4, T, H, W)
assert torch.all(mask_4ch[:, 2] >= mask_4ch[:, 0])
assert torch.all(mask_4ch[:, 2] >= mask_4ch[:, 1])
results["details"].append("4-channel mask correctly encodes union/intersection \u2713")
z_t = torch.randn(B, 4, T, H, W).to(device)
V_i = torch.randn(B, 4, T, H, W).to(device)
V_v = torch.randn(B, 4, T, H, W).to(device)
z_cond = V_i + V_v
X_in = torch.cat([z_t, mask_4ch, z_cond], dim=1)
assert X_in.shape == (B, 12, T, H, W)
results["details"].append("Full STAM pipeline: z_cond = V_i + V_v, X_in = [z_t, M, z_cond] \u2713")
with_gauss = z_cond * M_union
without_gauss = z_cond * (M_union > 0.5).float()
with_edge = edge_content(with_gauss)
without_edge = edge_content(without_gauss)
results["metrics"]["with_gaussian_edges"] = round(float(with_edge), 4)
results["metrics"]["without_gaussian_edges"] = round(float(without_edge), 4)
if with_edge <= without_edge:
results["details"].append(f"Gaussian masking reduces conditioning artifacts ({with_edge:.4f} vs {without_edge:.4f}) \u2713")
results["metrics"]["latent_dim"] = C
results["metrics"]["num_frames"] = T
results["metrics"]["spatial_size"] = f"{H}x{W}"
print(json.dumps(results, indent=2))
return 0
if __name__ == "__main__":
sys.exit(test_stam())

Xet Storage Details

Size:
4.66 kB
·
Xet hash:
d6303511019aec4ba892728eaf2f5f30415ff473a2307d44cbf0947aba23a1b8

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.