Phineas1500/sieve-ai-image-detector

A locally running AI image blocker for Chrome

See the code

README

Sieve logo

Sieve — Local AI Image Detector for Chrome

A Manifest V3 Chrome extension that detects AI-generated images entirely on-device. No cloud inference, no external APIs, no local server. Images never leave your browser.

Winner of the poidh local-AI challenge. MIT licensed, and actively improved from user reports — see the issue tracker.

Results

Held-out proxy benchmark: 36,384 images — SynthBuster (9 commercial 2023 generators, never trained on), OpenFake test (2026 frontier: GPT Image 2, Midjourney v7, Nano Banana Pro, Flux.2, …), OpenFake reddit (in-the-wild, never trained on), COCO val2017 + OpenFake reals. Scored at the fixed 0.65 confidence threshold.

conditionbalanced accuracyAI recallreal-photo accuracy
clean91.3%85.8%96.8%
web (≤768px, JPEG q60)87.5%79.1%95.9%
hard (≤512px, JPEG q40)86.2%77.4%95.0%

The v0.14 model holds the v0.12 benchmark numbers (−0.3 clean, ±0 web/hard) while fixing what the benchmark could not see: it false-flagged ~25% of ordinary lifestyle photography (Pexels held-out reals 74.9% → 97.4%), and the 2021–22 generator cohort, FLUX.1-dev at small sizes, faces and press photos all move up — the audit-slice table is in docs/accuracy-v0.14.md (v0.12: docs/accuracy-v0.12.md).

For reference, the stock Community Forensics base model scores 75.8 / 65.9 / 56.5 under the same protocol (its detection rate on GPT Image 2 is 7%; ours is >90%). Inference: ~91ms/image end-to-end (WebGPU, Apple Silicon), ~30ms model time.

Scores are a property of the bytes a page delivers, not of the underlying scene: the same photo re-shipped as a heavy recompression, a tiny upscaled thumbnail, or a collage can score very differently (the web/hard rows above bound the common cases; extreme degradation is not fully covered). Treat "AI n%" as evidence to weight, not a verdict — see issues #41/#42 for the measured failure modes.

How it works

  • A content script finds images on the page as they approach the viewport (IntersectionObserver + MutationObserver for dynamic content).
  • The extension service worker orchestrates a queue with caching; an offscreen document fetches image bytes (host permissions bypass CORS, usually a browser cache hit), decodes, and preprocesses them.
  • Preprocessing is deterministic and browser-independent: images decode 1:1 (a startup probe verifies the canvas readback byte-exactly and switches to WebCodecs if the browser injects fingerprinting noise), and resizing uses Sieve's own Pillow-exact resampler — so scores match the Python benchmark pipeline on every browser.
  • Inference runs in ONNX Runtime Web on WebGPU, falling back to WASM (SIMD) — including automatically when a numerical self-test detects a GPU stack computing the model incorrectly. The model is a ViT-S/16 initialized from Community Forensics (Park & Owens, CVPR 2025, MIT), fine-tuned on modern generator outputs (GPT Image, Midjourney v7, Flux, Nano Banana, …) with web-realistic degradation augmentation (JPEG/WebP recompression, rescaling, thumbnail regime), dedicated small-resolution copies of scale-fragile generators, and hard-real categories sourced from user reports and audits (screenshots, cartoon frames, game art, YouTube thumbnail composites, movie posters, product photos, degraded/low-quality photos, retouched portraits), in-the-wild Nano Banana Pro / GPT-Image-2 renders as posted on social media, AI edits of real photos, face swaps, 2021–22 generators (BigGAN, GLIDE, ADM, VQDM) and small-resolution copies of both fakes and reals. Shipped weights are a weight average of fine-tuning rounds (each itself an average of two identically trained runs), which stabilizes borderline scores and lets a new data round add coverage without giving back the previous round's accuracy.
  • Borderline images (calibrated 25–85%) get a second inference pass (selective TTA) and average the two views: a native-resolution crop for large images, a scale-jittered view for images below the crop size (thumbnails and avatars, the regime where single-view scores are least reliable — measured effect on 2,400 small held-out images is within ±0.6 points, see docs/degradation-gate.md).
  • Inputs delivered in a degraded regime — heavy recompression (JPEG block energy far beyond q40) or content upscaled far beyond its true resolution — are never flagged red: a verdict there isn't evidence-backed, so the badge shows unsure with the reason (how the gate is calibrated and why: docs/degradation-gate.md). Images that can't be analysed at all (too small, flat fills, noise) get a quiet grey not analysed chip instead of silence.
  • Every analyzed image gets a confidence badge: red AI n% at or above the threshold (default 65%, optionally blurred — click to toggle), amber unsure n% just below it, quiet gray otherwise.
  • Wrong verdict? Right-click → Sieve: report misclassification pre-fills a GitHub issue with the image URL and Sieve's score — reported images become regression tests and training categories for the next model.
  • Model weights (~45 MB) are downloaded once during setup from a pinned, checksummed URL and stored in OPFS; the extension then runs fully offline. When an update ships a newer pinned model, Sieve prompts — downloads are always user-initiated. The popup shows exactly which weights are installed.

Install (from source)

Requirements: Node.js ≥ 20, Chrome ≥ 124.

cd extension
npm install       # pulls onnxruntime-web (pinned)
npm run build     # copies the ORT runtime into extension/vendor/ort/

Then:

  1. Open chrome://extensions, enable Developer mode.
  2. Load unpacked → select the extension/ directory.
  3. The setup tab opens automatically (or click the extension icon → Model setup). Press Download model and wait for "Sieve is active".
  4. Browse. Badges appear on analyzed images; the popup shows per-page stats and lets you adjust the threshold (bounty evaluation: 65%).

Reproducing the model

The pipeline is plain PyTorch and runs on any CUDA machine (training/standalone/, no cloud service required):

python -m venv venv && . venv/bin/activate
pip install torch torchvision timm pillow numpy pyarrow huggingface_hub requests onnx
cd training/standalone
export DATA=~/data SCRATCH=/scratch
python materialize_eval.py          # benchmark: SynthBuster, COCO, OpenFake test/reddit
python materialize_train.py         # OpenFake train subset, COCO train, WikiArt
python materialize_screenshots.py   # hard-real screenshots (+ --synth-url tar)
python materialize_cartoons.py      # hard-real categories (cartoons, posters, product, degraded) + AI-art positives
python materialize_small.py         # downscaled copies of scale-fragile generator positives
python materialize_edits.py materialize_commons.py materialize_zip.py materialize_goku.py   # ft6+ sources
python materialize_small2.py        # downscaled copies of the newer AI sources and of reals
python train.py --run-name ft --max-steps 6500 --thumb-p 0.35 --exclude-sources '^edit_source_photo$' \
    --train-manifests openfake_train,coco_train,wikiart,screenshots_train,cartoons_train,small_pos,small_pos2,small_neg
python soup_pt.py --ckpts a/best.pt,b/best.pt --out soup/best.pt   # average two runs (and, for a release, the previous release's soup)
python eval_logits.py --ckpt soup/best.pt --tag ft                 # clean/web/hard logits
python export_fp16.py --ckpt soup/best.pt --out model_fp16.onnx    # fp16, fp32 I/O

Calibration (the manifest's bias) is fit offline from the logit CSVs: maximize worst-tier balanced accuracy at the fixed 0.65 threshold subject to real-photo accuracy ≥ 95%. Datasets are used under their respective licenses and are not redistributed with this repository.

Repository layout

extension/            the Chrome extension (load this directory unpacked)
  src/                service worker, offscreen inference, content script, UI
  vendor/ort/         ONNX Runtime Web (copied by npm run build, not committed)
  model_manifest.json pinned model URL + sha256 + calibration constants
training/standalone/  dataset materializers, fine-tune, soup, eval, ONNX export
training/vendor/      Community Forensics model code (MIT, J. Park)
eval/e2e/             browser end-to-end suites: scoring harness, badge/mode/
                      leak/update tests, PIL-parity regression
tools/                report mining (GitHub issue parser + labeling), PIL reference
                      scorer, per-category accuracy table
docs/                 per-release accuracy-by-category tables

License

MIT. Vendored Community Forensics code is MIT (Copyright Jeongsoo Park). ONNX Runtime Web is MIT (Microsoft).

Phineas1500/sieve-ai-image-detector

A locally running AI image blocker for Chrome

See the code

README

Sieve logo

Sieve — Local AI Image Detector for Chrome

A Manifest V3 Chrome extension that detects AI-generated images entirely on-device. No cloud inference, no external APIs, no local server. Images never leave your browser.

Winner of the poidh local-AI challenge. MIT licensed, and actively improved from user reports — see the issue tracker.

Results

Held-out proxy benchmark: 36,384 images — SynthBuster (9 commercial 2023 generators, never trained on), OpenFake test (2026 frontier: GPT Image 2, Midjourney v7, Nano Banana Pro, Flux.2, …), OpenFake reddit (in-the-wild, never trained on), COCO val2017 + OpenFake reals. Scored at the fixed 0.65 confidence threshold.

conditionbalanced accuracyAI recallreal-photo accuracy
clean91.3%85.8%96.8%
web (≤768px, JPEG q60)87.5%79.1%95.9%
hard (≤512px, JPEG q40)86.2%77.4%95.0%

The v0.14 model holds the v0.12 benchmark numbers (−0.3 clean, ±0 web/hard) while fixing what the benchmark could not see: it false-flagged ~25% of ordinary lifestyle photography (Pexels held-out reals 74.9% → 97.4%), and the 2021–22 generator cohort, FLUX.1-dev at small sizes, faces and press photos all move up — the audit-slice table is in docs/accuracy-v0.14.md (v0.12: docs/accuracy-v0.12.md).

For reference, the stock Community Forensics base model scores 75.8 / 65.9 / 56.5 under the same protocol (its detection rate on GPT Image 2 is 7%; ours is >90%). Inference: ~91ms/image end-to-end (WebGPU, Apple Silicon), ~30ms model time.

Scores are a property of the bytes a page delivers, not of the underlying scene: the same photo re-shipped as a heavy recompression, a tiny upscaled thumbnail, or a collage can score very differently (the web/hard rows above bound the common cases; extreme degradation is not fully covered). Treat "AI n%" as evidence to weight, not a verdict — see issues #41/#42 for the measured failure modes.

How it works

  • A content script finds images on the page as they approach the viewport (IntersectionObserver + MutationObserver for dynamic content).
  • The extension service worker orchestrates a queue with caching; an offscreen document fetches image bytes (host permissions bypass CORS, usually a browser cache hit), decodes, and preprocesses them.
  • Preprocessing is deterministic and browser-independent: images decode 1:1 (a startup probe verifies the canvas readback byte-exactly and switches to WebCodecs if the browser injects fingerprinting noise), and resizing uses Sieve's own Pillow-exact resampler — so scores match the Python benchmark pipeline on every browser.
  • Inference runs in ONNX Runtime Web on WebGPU, falling back to WASM (SIMD) — including automatically when a numerical self-test detects a GPU stack computing the model incorrectly. The model is a ViT-S/16 initialized from Community Forensics (Park & Owens, CVPR 2025, MIT), fine-tuned on modern generator outputs (GPT Image, Midjourney v7, Flux, Nano Banana, …) with web-realistic degradation augmentation (JPEG/WebP recompression, rescaling, thumbnail regime), dedicated small-resolution copies of scale-fragile generators, and hard-real categories sourced from user reports and audits (screenshots, cartoon frames, game art, YouTube thumbnail composites, movie posters, product photos, degraded/low-quality photos, retouched portraits), in-the-wild Nano Banana Pro / GPT-Image-2 renders as posted on social media, AI edits of real photos, face swaps, 2021–22 generators (BigGAN, GLIDE, ADM, VQDM) and small-resolution copies of both fakes and reals. Shipped weights are a weight average of fine-tuning rounds (each itself an average of two identically trained runs), which stabilizes borderline scores and lets a new data round add coverage without giving back the previous round's accuracy.
  • Borderline images (calibrated 25–85%) get a second inference pass (selective TTA) and average the two views: a native-resolution crop for large images, a scale-jittered view for images below the crop size (thumbnails and avatars, the regime where single-view scores are least reliable — measured effect on 2,400 small held-out images is within ±0.6 points, see docs/degradation-gate.md).
  • Inputs delivered in a degraded regime — heavy recompression (JPEG block energy far beyond q40) or content upscaled far beyond its true resolution — are never flagged red: a verdict there isn't evidence-backed, so the badge shows unsure with the reason (how the gate is calibrated and why: docs/degradation-gate.md). Images that can't be analysed at all (too small, flat fills, noise) get a quiet grey not analysed chip instead of silence.
  • Every analyzed image gets a confidence badge: red AI n% at or above the threshold (default 65%, optionally blurred — click to toggle), amber unsure n% just below it, quiet gray otherwise.
  • Wrong verdict? Right-click → Sieve: report misclassification pre-fills a GitHub issue with the image URL and Sieve's score — reported images become regression tests and training categories for the next model.
  • Model weights (~45 MB) are downloaded once during setup from a pinned, checksummed URL and stored in OPFS; the extension then runs fully offline. When an update ships a newer pinned model, Sieve prompts — downloads are always user-initiated. The popup shows exactly which weights are installed.

Install (from source)

Requirements: Node.js ≥ 20, Chrome ≥ 124.

cd extension
npm install       # pulls onnxruntime-web (pinned)
npm run build     # copies the ORT runtime into extension/vendor/ort/

Then:

  1. Open chrome://extensions, enable Developer mode.
  2. Load unpacked → select the extension/ directory.
  3. The setup tab opens automatically (or click the extension icon → Model setup). Press Download model and wait for "Sieve is active".
  4. Browse. Badges appear on analyzed images; the popup shows per-page stats and lets you adjust the threshold (bounty evaluation: 65%).

Reproducing the model

The pipeline is plain PyTorch and runs on any CUDA machine (training/standalone/, no cloud service required):

python -m venv venv && . venv/bin/activate
pip install torch torchvision timm pillow numpy pyarrow huggingface_hub requests onnx
cd training/standalone
export DATA=~/data SCRATCH=/scratch
python materialize_eval.py          # benchmark: SynthBuster, COCO, OpenFake test/reddit
python materialize_train.py         # OpenFake train subset, COCO train, WikiArt
python materialize_screenshots.py   # hard-real screenshots (+ --synth-url tar)
python materialize_cartoons.py      # hard-real categories (cartoons, posters, product, degraded) + AI-art positives
python materialize_small.py         # downscaled copies of scale-fragile generator positives
python materialize_edits.py materialize_commons.py materialize_zip.py materialize_goku.py   # ft6+ sources
python materialize_small2.py        # downscaled copies of the newer AI sources and of reals
python train.py --run-name ft --max-steps 6500 --thumb-p 0.35 --exclude-sources '^edit_source_photo$' \
    --train-manifests openfake_train,coco_train,wikiart,screenshots_train,cartoons_train,small_pos,small_pos2,small_neg
python soup_pt.py --ckpts a/best.pt,b/best.pt --out soup/best.pt   # average two runs (and, for a release, the previous release's soup)
python eval_logits.py --ckpt soup/best.pt --tag ft                 # clean/web/hard logits
python export_fp16.py --ckpt soup/best.pt --out model_fp16.onnx    # fp16, fp32 I/O

Calibration (the manifest's bias) is fit offline from the logit CSVs: maximize worst-tier balanced accuracy at the fixed 0.65 threshold subject to real-photo accuracy ≥ 95%. Datasets are used under their respective licenses and are not redistributed with this repository.

Repository layout

extension/            the Chrome extension (load this directory unpacked)
  src/                service worker, offscreen inference, content script, UI
  vendor/ort/         ONNX Runtime Web (copied by npm run build, not committed)
  model_manifest.json pinned model URL + sha256 + calibration constants
training/standalone/  dataset materializers, fine-tune, soup, eval, ONNX export
training/vendor/      Community Forensics model code (MIT, J. Park)
eval/e2e/             browser end-to-end suites: scoring harness, badge/mode/
                      leak/update tests, PIL-parity regression
tools/                report mining (GitHub issue parser + labeling), PIL reference
                      scorer, per-category accuracy table
docs/                 per-release accuracy-by-category tables

License

MIT. Vendored Community Forensics code is MIT (Copyright Jeongsoo Park). ONNX Runtime Web is MIT (Microsoft).

Significant stargazers

0xSero

2,154 followers · starred Aug 2026

Coy Geek

76 followers · starred Aug 2026

dhruv kejriwal

10 followers · starred Aug 2026