deepfake-server / src /viz /attention_maps.py
DevQueen's picture
Sync from GitHub via hub-sync
1dc2504 verified
Raw
History Blame Contribute Delete
1.92 kB
from __future__ import annotations
import argparse
from pathlib import Path
import cv2
import numpy as np
import torch
from PIL import Image
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
from torchvision import transforms
from src.models.lrcn_vit import LRCNViT
class CamWrapper(torch.nn.Module):
def __init__(self, model: LRCNViT) -> None:
super().__init__()
self.model = model
def forward(self, x: torch.Tensor) -> torch.Tensor:
blink = torch.zeros((x.shape[0], x.shape[1]), device=x.device)
logits, _ = self.model(x, blink)
return logits
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--checkpoint", required=True)
parser.add_argument("--image", required=True)
parser.add_argument("--out", required=True)
args = parser.parse_args()
device = "cuda" if torch.cuda.is_available() else "cpu"
model = LRCNViT(backbone_pretrained=False).to(device)
model.load_state_dict(torch.load(args.checkpoint, map_location=device))
model.eval()
image = np.array(Image.open(args.image).convert("RGB").resize((224, 224))).astype(np.float32) / 255.0
tensor = transforms.ToTensor()(image).unsqueeze(0).unsqueeze(1).to(device)
blink = torch.zeros((1, 1), device=device)
target_layer = [model.backbone.blocks[-1].norm1] if hasattr(model.backbone, "blocks") else [model.backbone]
cam = GradCAM(model=CamWrapper(model), target_layers=target_layer)
# For sequence models we use single-frame sequence.
grayscale_cam = cam(input_tensor=tensor, targets=None)[0]
cam_img = show_cam_on_image(image, grayscale_cam, use_rgb=True)
Path(args.out).parent.mkdir(parents=True, exist_ok=True)
cv2.imwrite(args.out, cv2.cvtColor(cam_img, cv2.COLOR_RGB2BGR))
print(f"Saved attention map to {args.out}")
if __name__ == "__main__":
main()