vanshpatil16's picture
DeepShield API β€” 7-detector image deepfake detection
6be0044
Raw
History Blame Contribute Delete
1.93 kB
"""Abstract base class every detector must implement."""
from __future__ import annotations
import base64
from abc import ABC, abstractmethod
from pathlib import Path
from backend.core.schema import DetectionResult, Verdict
class BaseDetector(ABC):
"""
Contract:
- Each detector receives an image path.
- Returns a DetectionResult with p_fake in [0, 1].
- Must never raise β€” catch all exceptions and return
DetectionResult with error set.
"""
name: str = "base"
@abstractmethod
async def detect(self, image_path: str) -> DetectionResult:
"""Run detection. Must not raise."""
# ── Helpers ──────────────────────────────────────────────────
@staticmethod
def _to_base64(image_path: str) -> str:
data = Path(image_path).read_bytes()
return base64.b64encode(data).decode("utf-8")
@staticmethod
def _mime_type(image_path: str) -> str:
ext = Path(image_path).suffix.lower()
return {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".webp": "image/webp",
".gif": "image/gif",
".bmp": "image/bmp",
}.get(ext, "image/jpeg")
@staticmethod
def _verdict_from_p_fake(
p_fake: float,
ai_threshold: float = 0.65,
real_threshold: float = 0.35,
) -> Verdict:
if p_fake >= ai_threshold:
return Verdict.AI_GENERATED
if p_fake <= real_threshold:
return Verdict.REAL
return Verdict.UNCERTAIN
def _error_result(self, error: str) -> DetectionResult:
return DetectionResult(
detector=self.name,
p_fake=0.5,
verdict=Verdict.UNCERTAIN,
confidence=0.0,
error=error,
)