Slopscan-Anime / README.md
Dominik72's picture
Update README.md
262219a verified
|
Raw History Blame Contribute Delete
6.86 kB
---
license: cc-by-nc-4.0
library_name: timm
pipeline_tag: image-classification
base_model: timm/convnextv2_base.fcmae_ft_in22k_in1k_384
tags:
- image-classification
- anime
- ai-generated-image-detection
- convnextv2
---
<div align="center">
<h1>Slopscan-Anime</h1>
<p><b>Detects if an anime image was generated by AI or drawn by a human.</b></p>
<p>
<a href="https://creativecommons.org/licenses/by-nc/4.0/"><img src="https://img.shields.io/badge/License-CC%20BY--NC%204.0-lightgrey.svg" alt="License: CC BY-NC 4.0"></a>
<a href="https://github.com/Dominik7272/Slopscan"><img src="https://img.shields.io/badge/GitHub-Slopscan-181717?logo=github&logoColor=white" alt="GitHub"></a>
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.11-blue?logo=python&logoColor=white" alt="Python 3.11"></a>
<a href="https://pytorch.org/"><img src="https://img.shields.io/badge/PyTorch-2.11-ee4c2c?logo=pytorch&logoColor=white" alt="PyTorch 2.11"></a>
</p>
</div>
---
## 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
```bash
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 .
```
```python
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:
```python
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_generated` tag 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:
```bibtex
@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}}
}
```