Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

censor

Automated anime NSFW mosaic/blur/scanline censorship pipeline.

censor runs an anime-trained YOLO instance-segmentation model over a folder of images, turns the per-instance masks into a censored region, and renders a mosaic (or blur / scanlines / pixelate) only over the anatomy you choose — leaving the rest of the picture intact. It is model-agnostic: drop any Ultralytics -seg checkpoint into .models/ and it works.

Responsible use. This tool exists to add censorship for platform compliance (e.g. Pixiv, Japanese Article 175 mosaic conventions). Use it only on adult content you have the right to process. You are responsible for the legality of your source material.


Why segmentation-first

Earlier iterations reconstructed a censor region from bounding boxes + SAM2 + morphology. A purpose-built anime segmentation model returns the exact shape directly, which removed an entire fragile subsystem. The pipeline is now:

Load → Segment → Mask union → QA / fail-closed gate → Render → Export
  • Pluggable detector honoring a simple load / detect / release contract.
  • Canonical label normalization so different models' class names (pussy, Pussy, vagina, cleft of venus, …) all map to one vocabulary.
  • Per-run output folders with a provenance manifest.
  • Fail-closed approval gate — an image with an empty mask is blocked, never exported raw.

Pipeline stages

Stage Name Hardware Artifacts
1 Asset Loader CPU metadata/<id>.json
2 ROI Segmentation (YOLO-seg) GPU stage2/<id>.json
3 Mask Generation / Union (+ erosion, censor_fully) CPU stage4/<id>.png
4 QA Preview + Fail-Closed Approval CPU stage5/preview_<id>.png, stage5/approved.json
5 Render (mosaic / pixelate / blur / scanlines) CPU stage6/<id>.png
6 Post-Processing / Export (metadata strip) CPU output/<id>.png

(Internal artifact directories keep historical stageN names; the segmentation path uses one GPU stage and loads → processes → releases VRAM so it fits a 6 GB card.)


Requirements

  • Python 3.11+
  • NVIDIA GPU with ≥ 6 GB VRAM (RTX 3050 or better) recommended; CPU works but is slow.
  • Core deps: ultralytics, opencv-python, pillow, numpy, pyyaml (Ultralytics pulls torch).

Install

python -m venv .venv
# Windows: .venv\Scripts\activate   |   Linux/macOS: source .venv/bin/activate
pip install -e ".[dev,gui]"
pytest            # optional: run the test suite (CPU-only, models are mocked)

# Optional: install extras for legacy detectors (anime, nudenet, gdino)
pip install -e ".[anime,nudenet,gdino]"

Place your segmentation checkpoint(s) in .models/:

.models/
└── animeNSFWSegm_xlRes1280.pt

Models

censor loads any Ultralytics YOLO -seg checkpoint. Verify a model with:

from ultralytics import YOLO
m = YOLO(".models/your_model.pt")
print(m.task)          # must print "segment"

Class names vary between models; censor/detectors/labels.py normalizes them:

Canonical Recognized raw labels
vagina vagina, pussy, cleft of venus
penis penis
anus anus
nipple nipple, nipples, nipple_f

Add a new model's labels by extending ALIASES in labels.py. Unmapped labels are ignored (fail-safe against over-coverage) — so audit a new model's class list before trusting it, since an unmapped genitalia class would go uncensored.

A photoreal (real-life-trained) YOLO-seg model works too — just drop it in .models/ and point model_path at it. Add any new class names to ALIASES.


Quick start

# Run with defaults from config.yaml
censor

# Custom input / output directories
censor -i my_pics -w out

# Censor only specific classes, tighter masks, custom confidence
censor --classes vagina penis --erode 8 --threshold 0.35

# Different effects
censor --effect blur
censor --effect pixelate --scale 0.005
censor --effect scanlines --gap 24 --thickness 6

# Swap the model
censor -m .models/ntd11_anime_nsfw_segm_v5.pt

# Verbose (see per-image detections) / preview-only
censor -v
censor --dry-run -v

run.py is a thin wrapper if you prefer: python run.py --classes vagina penis.


CLI reference

Flag Purpose
-i, --input Input image directory (default images)
-w, --work Work/output root (default work)
-c, --config Path to config.yaml
-m, --model Override detector.model_path
-t, --threshold Detection confidence (0–1)
--classes Canonical labels to censor, e.g. --classes vagina penis
--censor-fully Classes censored without erosion (full coverage), e.g. --censor-fully penis
--imgsz Inference resolution (default 1280; auto-degrades on VRAM OOM)
--ignore-left-visible Silence "detected but LEFT VISIBLE" warnings
--renderer segmask / effect / mosaic / blur
--effect mosaic / pixelate / blur / scanlines
--scale Mosaic/pixelate block scale (× reference edge)
--minimum, --maximum Block-size floor / ceiling (px)
--interpolation nearest / bilinear / bicubic
--blur-radius Blur strength
--gap, --thickness Scanline spacing / bar thickness
--erode Shrink mask inward (px); higher = less coverage
--feather Soften mask edge (px)
--run-id Name this run's folder (default: timestamp)
-v, -vv Per-stage info / per-detection debug
--dry-run Detect + log only; skip render/export

CLI flags override config.yaml; the resolved config is recorded in each run's run.json.


Web GUI (Interactive Editor)

censor includes a Gradio-based interactive web editor for real-time model tuning, live previewing, manual mask editing with brush tools, and session-wise exporting.

# Launch the web editor (opens automatically in browser at http://127.0.0.1:7860)
censor-gui

# Custom port or public Gradio share link
censor-gui --port 8080 --share

GUI Features

  • Tabbed Layout:
    • 1. Setup & Detect: Load single or multiple images, configure detector checkpoints, target classes (vagina, penis, anus, nipple), confidence thresholds, and execute GPU segmentation across the batch.
    • 2. Effect & Tuning: Dynamically adjust parameters for mosaic, pixelate, blur, or scanlines (block scale, blur radius, line gap/thickness, erosion, and feathering) with sticky real-time visual previews.
  • Manual Mask Editing (Brush):
    • Select Add or Erase mode to draw directly on the image editor canvas.
    • Manual brush edits seamlessly composite with detected model masks, allowing quick fixes for under-censored regions or false positives.
  • Session-wise Export:
    • Export the current image or all processed images into a session output folder (work/gui_runs/session_<timestamp>/output/).
    • Session grouping keeps outputs organized during interactive editing sessions.

Configuration

config.yaml holds defaults, including per-effect profiles merged at render time:

detector:
  primary: segmentation
  model_path: .models/animeNSFWSegm_xlRes1280.pt
  threshold: 0.25
  classes: [vagina, penis, anus]
  ignore_left_visible: false
  censor_fully: [anus, penis]      # full coverage (no erosion) for these

renderer:
  type: effect
  effect: mosaic                   # mosaic | pixelate | blur | scanlines
  minimum: 4
  maximum: null
  reference: long_edge
  color: [0, 0, 0]
  mosaic:    { scale: 0.004, erode: 15, minimum: 4, maximum: 16, feather: 0 }
  pixelate:  { scale: 0.001, erode: 10, feather: 0, interpolation: bilinear }
  blur:      { blur_radius: 2, erode: 4, feather: 0 }
  scanlines: { gap: 30, thickness: 5, erode: 14, feather: 0 }

output:
  compression: 9
runtime:
  vram_lifecycle: load_process_release
  batch_size: 2

Effects

  • mosaic / pixelate — block pixelation. scale sets block size relative to the image edge (block = scale × long_edge, floored/clamped by minimum/maximum). Lower scale = finer.
  • blur — Gaussian blur (blur_radius).
  • scanlines — horizontal bars (gap, thickness, color); region stays visible but censored, which sidesteps mask-undershoot on tricky poses.

Tuning notes

  • erode shrinks the mask inward (tighter coverage); censor_fully disables erosion for a class (full coverage). Small masks are auto-protected from over-erosion.
  • Censorship strength is content-dependent — different images may want different settings. Use CLI overrides per batch; each run is isolated in its own folder.

Output structure

work/
└── runs/
    ├── 2026-07-18_16-07-09_<pid>/
    │   ├── run.json          # config + timestamp + input dir (provenance)
    │   ├── metadata/ stage2/ stage4/ stage5/ stage6/
    │   └── output/           # final censored images for THIS run
    └── latest                # symlink/pointer to the newest run

Each run is self-contained — no stale state, and you can diff two runs' run.json to see what changed. Final deliverables are always in <run>/output/.


Development

ruff check .        # lint
ruff format .       # format
pytest              # tests (model calls are mocked; no GPU needed)

Architecture: detectors implement the Detector protocol (censor/detectors/base.py); renderers apply an effect within a mask (censor/render/). Add a detector by dropping a class in censor/detectors/ and registering it in Pipeline._get_detector.


License

MIT © 2026 Ishan Dev Shakya