Downloads · 30 days
0
salmanzaman777/digital-image-forgery-detection-model
digital-image-forgery-detection-model is a image classification model from salmanzaman777. Use it when you need a label for an image. It is set up for keras. The card lists the license as mit.
Classifies an image as Authentic or Forged by fusing raw RGB pixels (frozen ResNet50) with an Error Level Analysis (ELA) map (custom CNN) that amplifies JPEG compression inconsistencies left by tampering.
Downloads · 30 days
0
Access
Public
Updated Jun 20, 2026
Repo size
97.6 MB
Likes
0
Public
Click a slice to open those files.
.h597.6 MB · 100%
From the Hugging Face model README
Classifies an image as Authentic or Forged by fusing raw RGB pixels (frozen ResNet50) with an Error Level Analysis (ELA) map (custom CNN) that amplifies JPEG compression inconsistencies left by tampering.
M3_best_v2.h5 (~98 MB, full Keras 3 model) · License: MIT[rgb 224×224×3, ela 224×224×3]CASIA v2 (7,492 authentic + 5,124 tampered; 70/15/15 stratified split, SEED 42), Adam (lr 0.001), BCE loss, batch 32, Colab GPU. Decision threshold = 0.50.
| Metric | Value | Ablation | AUC-ROC | |
|---|---|---|---|---|
| AUC-ROC (test) | 0.9774 | RGB only | 0.5822 | |
| Test accuracy | ~92% | ELA only | 0.9807 | |
| Error rate | ~8% | Dual (M3) | 0.9774 |
The model is fundamentally ELA-driven (RGB alone ≈ random); ResNet50 adds texture context.
OOD: high-quality phone photos (HDR/multi-frame) yield large ELA residuals → often flagged forged. Scope: CASIA-only — won't generalise to GANs, deepfakes, or inpainting; ResNet50 stays frozen (no fine-tuning).
ELA must match training exactly: JPEG q=90 → diff → 15× brightness → JPEG q=75 → tf.image.decode_jpeg → bilinear resize → ÷255.
import io, numpy as np, tensorflow as tf
from PIL import Image, ImageChops, ImageEnhance
from huggingface_hub import hf_hub_download
IMG = (224, 224)
model = tf.keras.models.load_model(hf_hub_download(
repo_id="salmanzaman777/digital-image-forgery-detection-model",
filename="M3_best_v2.h5"), compile=False)
def ela(img, q=90, scale=15):
img = img.convert("RGB"); buf = io.BytesIO(); img.save(buf, "JPEG", quality=q); buf.seek(0)
d = ImageEnhance.Brightness(ImageChops.difference(img, Image.open(buf).convert("RGB"))).enhance(scale)
out = io.BytesIO(); d.save(out, "JPEG", quality=75)
x = tf.image.resize(tf.image.decode_jpeg(out.getvalue(), channels=3), IMG)
return (tf.cast(x, tf.float32) / 255.0).numpy()
image = Image.open("test.jpg").convert("RGB")
rgb = np.array(image.resize(IMG, Image.LANCZOS), np.float32)[np.newaxis] / 255.0
pred = float(model.predict([rgb, ela(image)[np.newaxis]], verbose=0)[0][0])
print("FORGED" if pred > 0.5 else "AUTHENTIC", f"(score={pred:.4f})")