docforensics / model /inference.py
Suryakarthik-1
Deploy DocForensics to Hugging Face Spaces
70520f0
Raw
History Blame Contribute Delete
1.61 kB
from dataclasses import dataclass
import numpy as np
import torch
import torch.nn.functional as F
from core.config import CHECKPOINTS_DIR, MODEL_INPUT_SIZE
from model.architecture import TamperNet
@dataclass
class ModelOut:
confidence: float # 0..1, probability of tampering
heatmap: np.ndarray # H x W float32, same spatial size as input image
_cached_model = None
def load_model(weights_path: str | None = None) -> TamperNet:
global _cached_model
if _cached_model is not None:
return _cached_model
path = weights_path or str(CHECKPOINTS_DIR / 'best.pt')
model = TamperNet()
model.load_state_dict(torch.load(path, map_location='cpu'))
model.eval()
_cached_model = model
return model
def predict(model: TamperNet, img: np.ndarray) -> ModelOut:
"""Run the model on a single HxWx3 float32 image (values 0..1)."""
h, w = img.shape[:2]
# Resize to model input size
tensor = torch.from_numpy(img).permute(2, 0, 1).unsqueeze(0).float() # (1,3,H,W)
tensor = F.interpolate(tensor, size=(MODEL_INPUT_SIZE, MODEL_INPUT_SIZE),
mode='bilinear', align_corners=False)
with torch.no_grad():
pred_mask, pred_logit = model(tensor)
# Confidence: sigmoid of the classification logit
confidence = torch.sigmoid(pred_logit).item()
# Heatmap: resize back to original image dimensions
heatmap = F.interpolate(pred_mask, size=(h, w), mode='bilinear', align_corners=False)
heatmap = heatmap.squeeze().numpy() # (H, W)
return ModelOut(confidence=confidence, heatmap=heatmap)