Skip to content

About

fake image buster

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

40 Commits

Folders and files

Repository files navigation

AI Image Detector (CIFAKE – REAL vs FAKE)


Project Overview

This project builds a system to detect AI-generated images using the CIFAKE dataset, which contains:

  • REAL images: sampled from CIFAR-10
  • FAKE images: generated by Stable Diffusion

We compare a classical computer vision baseline (HOG + Linear SVM) against a deep learning approach (CNN), then extend the CNN with adversarial robustness and expose it via a FastAPI backend that accepts image uploads and returns REAL/FAKE predictions. A React + TypeScript frontend provides a modern upload UI with model selection, explanations, and lightweight analytics (history + session stats).

Tech stack:

  • ML / Training: Python, PyTorch, scikit-learn
  • Backend: FastAPI, Uvicorn
  • Frontend: React + TypeScript (single-page upload UI)
  • Infrastructure / Deployment: Docker, Docker Compose, MongoDB Atlas, AWS EC2 (hosting), optional S3 for model storage

Quickstart – Run the Full App Locally

This will start both the FastAPI backend and the React frontend so you can upload any image and get a REAL/FAKE prediction.

  1. Create & activate virtualenv

    From the project root:

    python -m venv .venv
    source .venv/bin/activate        # macOS / Linux
    # .venv\Scripts\activate         # Windows
  2. Install Python dependencies

    pip install -r ml/requirements-ml.txt
  3. Download CIFAKE dataset

    export KAGGLE_API_TOKEN="KGAT_..."   # your Kaggle token
    python ml/download_cifake.py

    This prints a Path to dataset files: .... Optionally:

    export CIFAKE_ROOT="/full/path/printed/by/download_cifake.py"
  4. Start the FastAPI backend

    From the project root:

    uvicorn backend.main:app --reload
    • Health check: open http://127.0.0.1:8000/health in your browser.
  5. Start the React frontend

    In a new terminal (backend still running):

    cd frontend
    npm install        # first time only
    npm run dev

    Then open the URL shown in the terminal, typically:

    http://localhost:5173/
    
  6. Use the app

    • Click "Choose File" or drag-and-drop an image into the upload area.
    • (Optional) Select which model to use (adversarially trained cnn_adv or baseline cnn_v1).
    • Click "Analyze Image".
    • The app calls POST /predict (for the label + confidence) and then POST /explain (for an LLM-backed or rule-based explanation, depending on your config) and shows:
      • Label: REAL or FAKE
      • Confidence: model probability
      • Why this result? short explanation based on label + confidence
      • Recent predictions: a small history list
      • Session stats: counts by label and by model used

Repo Structure

AI-Image-Detection/
  ml/
    baseline_hog_svm.py     # classical HOG + SVM baseline on CIFAKE
    dataset.py              # PyTorch dataset + dataloaders for CIFAKE
    download_cifake.py      # download CIFAKE via kagglehub
    train_cnn.py            # train SimpleCNN on CIFAKE, saves cnn_v1.pth
    eval_cnn.py             # evaluate baseline CNN on test set
    train_cnn_adv.py        # adversarially train CNN with FGSM examples
    eval_cnn_adv.py         # evaluate adversarially trained CNN
    fgsm_attack.py          # FGSM attack on baseline CNN
    fgsm_attack_adv.py      # FGSM attack on adversarially trained CNN
    inference.py            # shared inference helpers for backend
    test_inference.py       # quick check for inference
    requirements-ml.txt     # Python deps for ML + backend
  backend/
    main.py                 # FastAPI inference service (REST API)
  frontend/                 # React + TS web app (image upload UI)
  weights/                  # model checkpoints (cnn_v1.pth, cnn_adv.pth) – gitignored
  .gitignore
  README.md

Setup

1. Create and activate virtualenv

From the project root:

python -m venv .venv
source .venv/bin/activate        # macOS / Linux
# .venv\Scripts\activate        # Windows

2. Install dependencies

pip install -r ml/requirements-ml.txt

(Contains: torch, torchvision, numpy, scikit-learn, matplotlib, Pillow, scikit-image, kagglehub, fastapi, uvicorn, etc.)


Dataset (CIFAKE)

1. Set Kaggle API token

In shell:

export KAGGLE_API_TOKEN="KGAT_..."

2. Download CIFAKE

From the project root:

python ml/download_cifake.py

This uses kagglehub to download CIFAKE and prints something like:

Path to dataset files: /Users/<user>/.cache/kagglehub/datasets/birdy654/cifake-real-and-ai-generated-synthetic-images/versions/3

We call this CIFAKE_ROOT. It should contain:

CIFAKE_ROOT/
  train/
    REAL/
    FAKE/
  test/
    REAL/
    FAKE/

Optionally set:

export CIFAKE_ROOT="/Users/<user>/.cache/kagglehub/datasets/birdy654/cifake-real-and-ai-generated-synthetic-images/versions/3"

ml/dataset.py reads CIFAKE_ROOT (or falls back to the kagglehub cache path).


1. Classical Baseline – HOG + Linear SVM

Script: ml/baseline_hog_svm.py

This script implements a classical HOG + SVM baseline:

  • Loads images from CIFAKE_ROOT/train/REAL and CIFAKE_ROOT/train/FAKE
  • Converts to grayscale and resizes to 64×64
  • Extracts Histogram of Oriented Gradients (HOG) features
  • Splits data into 80% train / 20% test
  • Trains a LinearSVC on the HOG features
  • Prints:
    • precision, recall, F1, accuracy per class
    • confusion matrix

To run:

python ml/baseline_hog_svm.py

Approximate performance:

  • Accuracy ≈ 74%
  • Balanced F1-scores for REAL and FAKE

This is our interpretable classical benchmark.


2. Deep Baseline – SimpleCNN on CIFAKE

2.1 Data Pipeline

Script: ml/dataset.py

Uses torchvision.datasets.ImageFolder to read:

  • CIFAKE_ROOT/train/REAL and CIFAKE_ROOT/train/FAKE
  • CIFAKE_ROOT/test/REAL and CIFAKE_ROOT/test/FAKE

Transforms:

  • Resize to 32×32
  • Random horizontal flip (train only)
  • Convert to tensor
  • Normalize RGB channels to roughly zero mean / unit-ish variance

Provides:

from ml.dataset import get_dataloaders

train_loader, test_loader = get_dataloaders(batch_size=256)

You can confirm dataset loading with:

python ml/dataset.py

2.2 CNN Training (Baseline)

Script: ml/train_cnn.py

Trains a small CNN (SimpleCNN) on CIFAKE:

  • 3 convolutional layers with ReLU + max pooling
  • Adaptive average pooling to a 128-d feature vector
  • Final linear layer → 2 logits (FAKE vs REAL)
  • Loss: cross-entropy
  • Optimizer: Adam (lr = 1e-3)
  • Device: cuda / mps / CPU

To run:

cd ml
python train_cnn.py

During training, it prints train/test loss and accuracy per epoch and saves the best-performing model weights to:

weights/cnn_v1.pth

On our full run (50 epochs), the best epoch reached:

  • Test accuracy ≈ 96.5% on 20k test images

3. Adversarial Robustness – FGSM and Adversarial Training

3.1 FGSM Attack on Baseline CNN

Script: ml/fgsm_attack.py

This script evaluates how vulnerable the baseline CNN (cnn_v1.pth) is to a Fast Gradient Sign Method (FGSM) attack.

High-level steps:

  • Load the trained baseline CNN (cnn_v1.pth)
  • Evaluate clean test accuracy
  • Generate FGSM adversarial examples with perturbation epsilon = 0.03:
    • Enable gradients on the input images
    • Take gradient of loss w.r.t. inputs
    • Add epsilon * sign(gradient) to each pixel, then clamp back to valid range
  • Re-evaluate accuracy on adversarial examples

To run:

cd ml
python fgsm_attack.py

Representative results:

  • Clean accuracy ≈ 0.9648
  • FGSM (eps=0.03) accuracy ≈ 0.29
  • Accuracy drop ≈ 0.67

This shows the baseline CNN is highly vulnerable to even small, structured noise.

3.2 Adversarial Training (FGSM-based)

Script: ml/train_cnn_adv.py

We perform adversarial training to improve robustness:

  • For each minibatch, generate FGSM examples on the fly (same epsilon)
  • Compute loss on both clean and adversarial images and backpropagate
  • Train for 10 epochs and track validation accuracy on clean data
  • Save best model as cnn_adv.pth

Representative training log (summarized):

  • Clean train accuracy grows from ~80% → ~93%
  • Adversarial train accuracy from ~65% → ~79%
  • Validation accuracy ends around 92–93%

To run:

cd ml
python train_cnn_adv.py

3.3 Evaluation of Adversarially Trained CNN

Script: ml/eval_cnn_adv.py

Loads cnn_adv.pth and evaluates on the clean test set:

cd ml
python eval_cnn_adv.py

Representative results:

  • Clean accuracy ≈ 93%
  • Balanced precision/recall for REAL and FAKE

Script: ml/fgsm_attack_adv.py

Runs the same FGSM attack on the adversarially trained model:

cd ml
python fgsm_attack_adv.py

Representative results:

  • Clean accuracy ≈ 0.93
  • FGSM (eps=0.03) accuracy ≈ 0.78
  • Accuracy drop ≈ 0.15

So the adversarially trained CNN sacrifices a bit of clean accuracy but is much more robust under attack.


4. Inference Wrapper (Shared by Scripts + Backend)

Script: ml/inference.py

Provides a clean, reusable interface for running inference with our models.

Main pieces:

  • get_device() – picks cuda / mps / CPU
  • load_model(model_version="cnn_adv") – rebuilds SimpleCNN and loads weights/cnn_v1.pth or weights/cnn_adv.pth
  • preprocess_image(pil_image) – resizes to 32×32, converts to tensor, normalizes channels
  • predict_image(pil_image, model=None, model_version="cnn_adv") – returns:
{
  "label": "REAL" or "FAKE",
  "probability": float,     # softmax confidence for predicted class
  "model_version": "cnn_v1" or "cnn_adv"
}

You can confirm this with:

cd ml
python test_inference.py

which loads a REAL and FAKE test image and prints predictions.


5. FastAPI Backend

File: backend/main.py

We expose the model via a simple REST API powered by FastAPI + Uvicorn.

5.1 Endpoints

  • GET /health – health check

    { "status": "ok", "model_version": "cnn_adv" }
  • POST /predict – image upload and prediction

    • Expects form-data field file with an image (PNG/JPEG, etc.)
    • Uses ml.inference.predict_image under the hood
    • Returns JSON:
    {
      "label": "REAL",
      "probability": 0.86,
      "model_version": "cnn_adv"
    }

    You can choose the model version (e.g. cnn_adv vs cnn_v1) from the frontend UI; the backend will respect that selection when running inference.

  • POST /explain – image upload + explanation

    • Accepts the same image file field (file) as /predict, plus query params for model and optional LLM provider.
    • Returns label, probability, model version, a confidence bucket, a human-readable explanation, and (when applicable) which LLM/provider generated it.

5.3 Explanation endpoint (LLM + rule-based fallback)

  • POST /explain – generate a human-readable explanation directly from an uploaded image.

    • Accepts form-data:

      curl -X POST "http://127.0.0.1:8000/explain?model=cnn_adv&llm_provider=openai" \
        -F "file=@/full/path/to/some/test_image.png"
    • Query parameters:

      • model – which CNN to use: cnn_v1 (baseline) or cnn_adv (adversarially trained). Defaults to the backend MODEL_VERSION env var.
      • llm_provider (optional) – openai or gemini. If omitted, the backend will choose a default provider based on environment variables.
    • Response shape (Pydantic ExplanationResponse):

      {
        "label": "FAKE",
        "probability": 0.9957,
        "model_version": "cnn_adv",
        "confidence_bucket": "very_high",
        "explanation": "…human-readable paragraph…",
        "llm_provider": "openai",
        "llm_model": "gpt-4o-mini"
      }
    • Under the hood, the backend:

      • Runs the same CNN inference as /predict.
      • Buckets the confidence into very_high, high, medium, or low.
      • Tries to generate an explanation with LangChain + an LLM (OpenAI or Gemini) when API keys are configured.
      • Falls back to a rule-based explanation if no LLM is available or if the LLM call fails.

5.4 LLM / LangChain configuration

The backend uses LangChain to optionally call an LLM for explanations. Configuration is driven by environment variables:

  • OPENAI_API_KEY – if set, enables OpenAI via ChatOpenAI.
  • GOOGLE_API_KEY – if set, enables Gemini via ChatGoogleGenerativeAI.
  • EXPLAIN_DEFAULT_LLM – default provider when the frontend does not pass llm_provider:
    • openai – prefer OpenAI when available.
    • gemini – prefer Gemini (if allowed/enabled).
    • none – never call an LLM by default; always use rule-based explanations.
  • EXPLAIN_ENABLE_GEMINI – feature flag (true/false) to allow Gemini usage in this deployment.
  • OPENAI_MODEL – OpenAI model name (default: gpt-4o-mini).
  • GEMINI_MODEL – Gemini model name (default: gemini-2.5-flash).

If no provider is usable (no keys configured or none is specified), /explain always returns the rule-based explanation but still includes the confidence bucket and model metadata.

5.5 MongoDB logging & analytics

When configured with a MongoDB connection string (e.g. a MongoDB Atlas cluster), the backend logs each explanation request to a predictions collection. Each document records:

  • model_version – which model handled the request (cnn_v1 or cnn_adv)
  • label and probability – the prediction and confidence
  • confidence_bucket – one of very_high, high, medium, low
  • llm_provider / llm_model – which LLM (if any) generated the explanation
  • timestamps and basic request metadata

This makes it easy to compute offline metrics (accuracy over time, model drift, per-model comparisons) and to debug individual predictions without storing the raw image data.

5.2 Running the Backend

From the project root (with virtualenv activated):

uvicorn backend.main:app --reload

Then:

  • Visit http://127.0.0.1:8000/health in a browser → should return status OK
  • Call the predict endpoint with curl:
curl -X POST "http://127.0.0.1:8000/predict" \
  -F "file=@/full/path/to/some/test_image.png"

Expected output (example):

{"label":"REAL","probability":0.8645,"model_version":"cnn_adv"}

This backend is what the React frontend consumes.


6. React Frontend – Upload & Prediction UI

Folder: frontend/

This is a Vite-powered React + TypeScript single-page app that lets a user:

  • Upload an image via file picker or drag-and-drop
  • Choose which model to use (adversarially trained Adv-CNN vs baseline CNN)
  • Send the image to the FastAPI backend /predict endpoint
  • Call /explain to get a short explanation for the result
  • View a list of recent predictions for the current session
  • See lightweight session stats (total images, REAL vs FAKE counts, usage per model)

By default, the frontend expects the backend to be running at:

http://127.0.0.1:8000

and calls:

POST /predict

with the uploaded file in a file form field.

Running the frontend dev server

Requirements:

  • Node.js 20.19+ or 22.12+ (Vite 7 requirement)
  • npm (comes with Node)

From the project root:

cd frontend
npm install        # if you haven't already
npm run dev

Then open the URL printed in the terminal, typically:

http://localhost:5173/

Make sure the backend is running first (uvicorn backend.main:app --reload), so the Analyze button can reach /predict.


7. Current Frontend / UX Features

Already implemented on top of the core ML + backend work:

  • Modern upload UI
    • Glassmorphism-style card with a soft glow that follows the cursor
    • Drag-and-drop or file picker upload
    • Inline image preview before sending to the backend
  • Model selection
    • Toggle between adversarially trained cnn_adv and baseline cnn_v1
  • Result explanation (LLM + rule-based fallback)
    • "Why this result?" panel driven by the /explain endpoint.
    • When an LLM provider is configured and selected, the explanation comes from LangChain + an LLM (OpenAI or Gemini); otherwise it falls back to the rule-based text.
  • LLM provider selector
    • Dropdown to choose between OpenAI, Gemini, or a purely rule-based explanation.
    • UI displays a small "generated by …" line under the explanation showing which provider/model was used.
  • Prediction history
    • Recent predictions list (label, confidence, model version, timestamp), persisted in localStorage so it survives refreshes.
  • Session stats
    • Total images analyzed this session
    • REAL vs FAKE counts
    • How many times each model was used

8. Dockerized Deployment (Local + AWS)

In addition to the local dev workflow (uvicorn + Vite), the app can be run end-to-end via Docker.

8.1 Local Docker Compose

From the project root (after ensuring weights/ contains cnn_v1.pth and cnn_adv.pth):

docker compose build backend frontend
docker compose up backend frontend

This will start:

  • FastAPI backend on http://localhost:8000
  • React frontend on http://localhost:5173

The frontend is configured to talk to the backend via the VITE_BACKEND_URL environment variable (set in frontend/.env.local for local dev or via a Docker environment file such as .env.docker).

8.2 AWS EC2

For a cloud deployment, you can:

  1. Launch an Ubuntu EC2 instance with Docker and the Docker Compose plugin installed.

  2. Clone this repository onto the instance and copy the trained weights into weights/.

  3. Create an .env.docker file at the project root with your OPENAI_API_KEY, GOOGLE_API_KEY, MongoDB connection string, and any other config.

  4. Run:

    docker compose build backend frontend
    docker compose up -d backend frontend

The app will then be accessible via the EC2 instance’s public IP on ports 8000 (backend API) and 5173 (frontend UI), subject to your security group configuration.

This README serves as both a project log and a guide to running and extending AI Image Detector (CIFAKE – REAL vs FAKE).

About

fake image buster

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages