Views
No views yet
Domain / intended use. Trained on booru-tagged anime/illustration (a domain that includes explicit content) for content tagging and moderation triage. It is a detector only — it does not generate, modify, remove, or reconstruct censored content.
output, shape (batch, 4), all independent sigmoids, in this order:| col | head | meaning |
|---|---|---|
| 0 | censored | p(image is censored) — the binary gate |
| 1 | bar | bar censorship |
| 2 | ineffective | ineffective / see-through censorship — disabled (see below) |
| 3 | mosaic | mosaic / pixelation |
| head | F1 | AUROC | threshold |
|---|---|---|---|
| censored (binary) | 0.924 | 0.964 | 0.47 |
| bar | 0.916 | 0.968 | 0.59 |
| mosaic | 0.922 | 0.972 | 0.53 |
| ineffective | 0.259 | 0.547 | disabled |
ineffective head doesn't reach a usable quality bar (the concept is fuzzy in booru
tagging), so it is disabled by setting its threshold to 1.01 — it never fires. On the
bar/mosaic heads the student essentially matches its EVA-02 teacher.pip install onnxruntime numpy pillow # or onnxruntime-gpu for CUDAinfer.py (reproduces the exact preprocessing + decision rules the metrics
were measured with):1import sys
2from huggingface_hub import snapshot_download
3
4path = snapshot_download("Maltox/anime-censorship-tagger-mnv3-384")
5sys.path.insert(0, path) # so the bundled infer.py / censor_infer_core.py import
6from infer import CensorTagger
7tagger = CensorTagger(model_dir=path)
8r = tagger.predict("image.jpg")
9print(r.censored, r.p_censored, r.tags)
10# -> True 0.97 ['censored', 'censorship:bar']
11
12results = tagger.predict_batch(paths, batch_size=16)config.json):1import numpy as np, onnxruntime as ort
2from PIL import Image
3
4sess = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
5img = Image.open("image.jpg").convert("RGB").resize((384, 384), Image.BILINEAR) # squash
6x = ((np.asarray(img, np.float32) / 255.0 - 0.5) / 0.5).transpose(2, 0, 1)[None]
7p_cens, bar, ineff, mosaic = sess.run(None, {"input": x})[0][0]
8
9tags = []
10if p_cens > 0.47: # binary gate
11 tags.append("censored")
12 if bar > 0.59: tags.append("censorship:bar")
13 if mosaic > 0.53: tags.append("censorship:mosaic")
14 # 'ineffective' is disabled (threshold 1.01)(N, 3, 384, 384), RGB./255 → (x − 0.5) / 0.5.censor_infer_core.preprocess_squash_numpy does this with a robust decode (EXIF transpose,
alpha-composited on white). This is the same 384 view used by deepghs anime aux taggers.ineffective requires a co-active base type (and is disabled regardless).censor_infer_core.apply_modifier_gating implements this. Treating the output as a flat
"sigmoid > 0.5" tag vector will be wrong (it ignores the gate and per-head thresholds).b70_R2) of SmilingWolf/wd-eva02-large-tagger-v3 (EVA-02-Large, 504px).mobilenetv3_large_100 (timm, Apache-2.0).ineffective concept is too inconsistent
to ship and is disabled.1@misc{maltox_anime_censorship_mnv3_384_2026,
2 title = {Anime Censorship Tagger --- MobileNetV3 (shared-384)},
3 author = {Maltox},
4 year = {2026},
5 howpublished = {\url{https://huggingface.co/Maltox/anime-censorship-tagger-mnv3-384}},
6 note = {Distilled from SmilingWolf/wd-eva02-large-tagger-v3}
7}LICENSE and NOTICE).SmilingWolf/wd-eva02-large-tagger-v3 — Apache-2.0.timm MobileNetV3-Large (Apache-2.0) student.model.onnx, meta.json, config.json, infer.py, censor_infer_core.py,
selected_tags.csv, requirements.txt.