Pujan-Dev's picture
fixed the download issue
50c40fa
from typing import IO
import io
import numpy as np
from PIL import Image
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
import torch
from torchvision import transforms
from .preprocessor import preprocessor
from .inferencer import interferencer
from .model_loader import models
from config import Config
security = HTTPBearer()
async def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)):
token = credentials.credentials
expected_token = Config.SECRET_TOKEN
if token != expected_token:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid or expired token",
)
return token
class ClassificationController:
"""
Controller to handle the image classification logic.
"""
def classify_image(self, image_file: IO) -> dict:
"""
Orchestrates the classification of a single image file.
Args:
image_file (IO): The image file to classify.
Returns:
dict: The classification result.
"""
try:
# Step 1: Preprocess the image
image_tensor = preprocessor.process(image_file)
# Step 2: Perform inference
result = interferencer.predict(image_tensor)
return result
except ValueError as e:
# Handle specific errors like invalid images
return {"error": str(e)}
except Exception as e:
# Handle unexpected errors
print(f"An unexpected error occurred: {e}")
return {"error": "An internal error occurred during classification."}
# Create a single instance of the controller
controller = ClassificationController()
class documentForger:
"""
Document forgery detector that uses the ELA-trained EfficientNet model
when available (models.doc_model). Returns a dict with verdict and confidence.
"""
def is_forged(self, document_file: IO) -> dict:
# Ensure a document model is loaded
if not hasattr(models, 'doc_model') or models.doc_model is None:
_downloadmodel = Config.DOCUMENT_FORGERY_MODEL_PATH
return {"detail": "Document forgery model not available."}
# Read file bytes
try:
data = document_file.read()
img = Image.open(io.BytesIO(data)).convert('RGB')
except Exception as e:
return {"detail": f"Could not open document image: {e}"}
# Compute ELA map (same approach as the notebook)
try:
buf = io.BytesIO()
img.save(buf, format='JPEG', quality=90)
buf.seek(0)
recompressed = Image.open(buf).convert('RGB')
ela_arr = np.abs(np.array(img, dtype=np.float32) - np.array(recompressed, dtype=np.float32))
p99 = np.percentile(ela_arr, 99)
if p99 > 0:
ela_arr = np.clip(ela_arr * (255.0 / p99), 0, 255).astype(np.uint8)
else:
ela_arr = ela_arr.astype(np.uint8)
ela_pil = Image.fromarray(ela_arr, mode='RGB')
except Exception as e:
return {"detail": f"Failed to compute ELA: {e}"}
# Transform and run through model
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
])
tensor = transform(ela_pil).unsqueeze(0).to(models.device)
with torch.no_grad():
logits = models.doc_model(tensor)
probs = torch.softmax(logits, dim=1)[0, 1].item()
# Interpret confidence using configurable thresholds (values in 0..1)
low = getattr(Config, 'DOCUMENT_FORGERY_POSSIBLE_LOW', 0.40)
high = getattr(Config, 'DOCUMENT_FORGERY_FORGED_LOW', 0.55)
if probs < low:
verdict = 'LIKELY AUTHENTIC'
elif probs < high:
verdict = 'POSSIBLY FORGED'
else:
verdict = 'LIKELY FORGED'
return {
"verdict": verdict,
"confidence": float(probs),
"confidence_pct": round(float(probs) * 100, 2),
}
# Create a single instance of the document forger
document_forger = documentForger()