Instructions to use Dominik72/Slopscan-Anime with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- timm
How to use Dominik72/Slopscan-Anime with timm:
import timm model = timm.create_model("hf_hub:Dominik72/Slopscan-Anime", pretrained=True) - Notebooks
- Google Colab
- Kaggle
Highlights
Slopscan-Anime is a binary image classifier that separates AI-generated anime art (Stable Diffusion / NovelAI / Midjourney / Flux / ...) from human-drawn art. It is a fine-tune of ConvNeXt V2 Base at 1024×1024, tuned for high precision on in-the-wild booru content.
- 0.9961 accuracy / 0.9998 AUROC on a 29,390-image held-out test set
- Trained on 235,130 images with automatic label cleaning
- Runs on a consumer GPU (~1.2 GB VRAM, ~70 ms/image on an RTX 4070 Super) or CPU
- Single-file inference code, no framework dependencies beyond timm + torchvision
Note on scores: training used label smoothing and mixup, so probabilities are compressed. AI images rarely score above ~0.92. Rank ordering is what matters. The recommended cutoff is 0.42, lower it for more sensitivity, raise it for less false positives.
Model Overview
| Architecture | ConvNeXt V2 Base (convnextv2_base.fcmae_ft_in22k_in1k_384, 88.7M params) |
| Head | Linear, 2 logits |
| Input | RGB, resize to 1056px (shorter side), center crop 1024×1024 |
| Normalization | ImageNet mean [0.485, 0.456, 0.406], std [0.229, 0.224, 0.225] |
| Output | P(AI generated), 0..1 |
Weights in best.pt |
EMA of the final fine-tune (1024px stage) |
| Recommended threshold | 0.42 |
Evaluation Results
Held-out test set, n = 29,390 (~50/50 class balance):
| Accuracy | Precision | Recall | F1 | AUROC | ECE |
|---|---|---|---|---|---|
| 0.9961 | 0.9951 | 0.9970 | 0.9961 | 0.9998 | 0.064 |
The threshold is set for F1 on validation; precision is slightly below recall by design, so the tool errs toward catching AI images at the cost of a few false positives.
Training Recipe
Data scraped from rule34.xxx via its public API:
| Split | Images | Source |
|---|---|---|
| Train | 235,130 | ai_generated tag (AI) vs. -ai_generated -stable_diffusion -novelai -midjourney -flux -sdxl -dall-e -pixai -yodayo -comfyui sort:random (human) |
| Val | 29,390 | same pipeline, stratified |
| Test | 29,390 | same pipeline, stratified |
All images were validated with Pillow and deduplicated by MD5 before splitting.
Fine-tuning warm-started from an earlier 512px checkpoint, then three progressive stages:
| Stage | Resolution | Batch size | LR | Epochs | Best val AUROC |
|---|---|---|---|---|---|
| 1 | 384 | 32 | 1.5e-5 | 20 | 0.9997 |
| 2 | 512 | 16 | 1e-5 | 5 | 0.9997 |
| 3 | 1024 | 4 | 1e-5 | 4 | 0.9999 |
Recipe: RandAugment, mixup 0.2, label smoothing 0.1, soft-target loss, EMA 0.999, cosine LR with 5% warmup, bf16 autocast. A 384/512/1024 ensemble was evaluated and did not beat the single 1024px model.
Quickstart
git clone https://github.com/Dominik7272/Slopscan
cd Slopscan
pip install -r requirements.txt
pip install huggingface_hub
hf download Dominik72/Slopscan-Anime best.pt --local-dir .
from slopscan import Slopscan
model = Slopscan("best.pt") # loads the model once, GPU if available
prob = model.classify("image.png") # P(AI generated), 0..1
classify accepts a path or an already-open PIL.Image. CUDA is used when
available; expect ~70 ms/image on an RTX 4070 Super and ~1.2 GB VRAM.
ONNX
best.onnx from the same repo has the same weights and output (1024×1024 input,
raw logits) and runs without PyTorch, on onnxruntime alone:
import numpy as np
import onnxruntime as ort
from PIL import Image
MEAN = np.array([0.485, 0.456, 0.406], dtype=np.float32)
STD = np.array([0.229, 0.224, 0.225], dtype=np.float32)
image = Image.open("image.png").convert("RGB")
w, h = image.size
scale = 1056 / min(w, h)
image = image.resize((round(w * scale), round(h * scale)), Image.BILINEAR)
left, top = (image.width - 1024) // 2, (image.height - 1024) // 2
image = image.crop((left, top, left + 1024, top + 1024))
x = np.asarray(image, dtype=np.float32) / 255.0
x = (x - MEAN) / STD
x = x.transpose(2, 0, 1)[None] # NCHW
session = ort.InferenceSession("best.onnx", providers=["CPUExecutionProvider"])
logits = session.run(None, {"image": x})[0][0]
e = np.exp(logits - logits.max())
prob = float(e[1] / e.sum()) # P(AI generated), 0..1
Limitations and Disclaimer
- Domain: trained on anime illustration art. It will not generalize to photos, photorealistic renderings, or non-anime styles.
- 3D renders: human-made 3D work (Blender / MMD / SFM / Daz) is sometimes flagged as AI. This is a known weakness and the target of the next model version.
- Label noise: the
ai_generatedtag is applied by uploaders; untagged AI uploads land in the human set. The ~0.4% test error roughly bounds this noise. - Distribution shift: new generators and artist mimicry can be misclassified.
- A prediction is a hint, not proof about a creator's process. Do not use this model to harass artists or to make definitive accusations.
License
CC BY-NC 4.0 non-commercial use only. This model is a fine-tune of FAIR's ConvNeXt V2 weights, which are released under CC BY-NC 4.0, so the derivative inherits the same restriction. Training images were scraped from publicly viewable rule34.xxx pages and are not redistributed here.
Citation
If you use this model, please cite the backbone it is built on:
@article{Woo2023ConvNeXtV2,
title={ConvNeXt V2: Co-designing and Scaling ConvNets with Masked Autoencoders},
author={Sanghyun Woo, Shoubhik Debnath, Ronghang Hu, Xinlei Chen, Zhuang Liu, In So Kweon and Saining Xie},
year={2023},
journal={arXiv preprint arXiv:2301.00808},
}
@misc{rw2019timm,
author = {Ross Wightman},
title = {PyTorch Image Models},
year = {2019},
publisher = {GitHub},
journal = {GitHub repository},
doi = {10.5281/zenodo.4414861},
howpublished = {\url{https://github.com/huggingface/pytorch-image-models}}
}
- Downloads last month
- -
Model tree for Dominik72/Slopscan-Anime
Base model
timm/convnextv2_base.fcmae_ft_in22k_in1k_384