--- 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 ---

Slopscan-Anime

Detects if an anime image was generated by AI or drawn by a human.

License: CC BY-NC 4.0 GitHub Python 3.11 PyTorch 2.11

--- ## 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}} } ```