Veritas-AI / predict_fusion.py
Aditya-Jadhav150
feat: upgrade to Veritas-AI v3.1 architecture, fast video & image deepfake pipeline, UI enhancements
37b2345
Raw
History Blame Contribute Delete
5.04 kB
# -*- coding: utf-8 -*-
"""predict_fusion.py
CLI inference script for the Hybrid AI Image Forensics system.
It loads the persisted XGBoost model and StandardScaler, extracts the nine
scalar forensic scores from a single image, and prints a polished report.
"""
import os
import argparse
import joblib
import pandas as pd
import torch
import cv2
import numpy as np
from sklearn.preprocessing import StandardScaler
# Core components – already in the repo
from core.alignment import GeometricAligner
from core.diffusion_latent import DiffusionErrorLoop
from core.statistical_extraction import StatisticalFeatureExtractor
# --------------------------------------------------------------
# Helper functions removed: utilizing core.metrics
# --------------------------------------------------------------
from core.metrics import ForensicMetricExtractor
from core.metadata_forensics import MetadataForensicsEngine
def main():
parser = argparse.ArgumentParser(description="Run forensic inference on a single image")
parser.add_argument("--image", "-i", required=True, help="Path to image file")
parser.add_argument("--model", default=os.path.join('dataset', 'fusion_engine_best.json'), help="Path to saved XGBoost model JSON")
parser.add_argument("--scaler", default=os.path.join('dataset', 'scaler.json'), help="Path to saved StandardScaler JSON")
parser.add_argument("--device", default="cpu", help="Device to run models on (cpu or cuda)")
args = parser.parse_args()
# Load model & scaler
if not os.path.isfile(args.model):
raise FileNotFoundError(f"Model file not found: {args.model}")
if not os.path.isfile(args.scaler):
raise FileNotFoundError(f"Scaler file not found: {args.scaler}")
from xgboost import XGBClassifier
import json
model = XGBClassifier()
model.load_model(args.model)
scaler = StandardScaler()
with open(args.scaler, 'r') as f:
s_data = json.load(f)
scaler.mean_ = np.array(s_data["mean"])
scaler.var_ = np.array(s_data["var"])
scaler.scale_ = np.array(s_data["scale"])
scaler.n_features_in_ = s_data["n_features_in"]
# -------------------- Load image & align --------------------
bgr = cv2.imread(args.image)
if bgr is None:
raise ValueError(f"Could not read image: {args.image}")
aligner = GeometricAligner(device=args.device)
aligned = aligner.align_and_crop(bgr, return_tensor=True)
if aligned is None:
raise RuntimeError("Face detection failed – no face found in the image.")
# -------------------- Load Metric Extractor --------------------
metric_extractor = ForensicMetricExtractor(device=args.device)
metadata_engine = MetadataForensicsEngine()
# -------------------- Extract Metadata Forensics ---------------
metadata_results = metadata_engine.analyze(args.image)
meta_score = metadata_results.get('metadata_forensic_score', 0.5)
# -------------------- Denormalize image --------------------
mean = np.array([0.485, 0.456, 0.406]).reshape(3, 1, 1)
std = np.array([0.229, 0.224, 0.225]).reshape(3, 1, 1)
aligned_np = aligned.cpu().numpy()
unnorm = (aligned_np * std + mean) * 255.0
rgb = np.clip(unnorm, 0, 255).transpose(1, 2, 0).astype(np.uint8)
# -------------------- Compute scores --------------------
feature_dict = metric_extractor.extract_all(aligned, rgb)
# Add metadata forensic score to feature dict
feature_dict['metadata_forensic_score'] = meta_score
df_feat = pd.DataFrame([feature_dict])
# The scaler expects specific columns in the same order as training.
# The scaler natively expects 10 features now.
df_scaled = scaler.transform(df_feat)
# -------------------- Predict --------------------
prob_fake = model.predict_proba(df_scaled)[0, 1]
verdict = "AI Generated" if prob_fake >= 0.5 else "Real"
confidence = prob_fake * 100 if prob_fake >= 0.5 else (1 - prob_fake) * 100
# -------------------- Pretty report --------------------
print("\n" + "=" * 40)
print(" AI IMAGE FORENSIC REPORT")
print("=" * 40 + "\n")
print(f"Spatial Artifact Score : {feature_dict['spatial_score']:.2f}")
print(f"Frequency Anomaly Score : {feature_dict['freq_score']:.2f}")
print(f"Noise Residual Score : {feature_dict['latent_score']:.2f}")
print(f"Embedding Consistency : {feature_dict['stat_score']:.2f}")
print(f"Entropy Score : {feature_dict['entropy']:.2f}")
print(f"Edge Density Score : {feature_dict['edge_density']:.2f}")
print(f"Laplacian Variance Score : {feature_dict['laplacian_variance']:.2f}")
print(f"Color Kurtosis Score : {feature_dict['color_kurtosis']:.2f}")
print(f"JPEG Consistency Score : {feature_dict['jpeg_consistency']:.2f}")
print("-" * 40)
print("FINAL RESULT:")
print(f"Likely {verdict}")
print(f"Confidence: {confidence:.0f}%")
print("=" * 40 + "\n")
if __name__ == "__main__":
main()