From open sourced deface script, easy use with comments. Wish you'll find it helpful.
Can't upload .py file so I'll just copy and paste.
Can't upload .py file so I'll just copy and paste.
Python:
import math
from typing import List, Tuple
from PIL import Image # pip install pillow
from nudenet import NudeDetector # pip install nudenet
# NudeNet is a deep learning model for nudity detection and it is based on TensorFlow. It is trained on a large-scale \
# dataset and it is able to detect nudity in images with high accuracy. It is also able to detect different types of \
# nudity
# Original Repo for NudeNet: https://github.com/notAI-tech/NudeNet
# You can take a look at this for further information.
# The model checkpoint file will be downloaded at the first time of running.
detector = NudeDetector()
def _area_mosaic(image_: Image.Image, unit: int = 8) -> Image.Image:
"""
Just zooming it, and then squeezing it back.
:param image_: PIL Image object of the part to be censored.
:param unit: Granularity of mosaic squares, in pixels.
"""
width, height = image_.size
image_ = image_.resize((width // unit, height // unit))
image_ = image_.resize((width, height))
return image_
def mosaic(image_: Image.Image, fx, fy, tx, ty, unit: int = 8) -> Image.Image:
"""
:param image_: PIL Image object to censor.
:param fx: Left-upper horizontal position, in pixels.
:param fy: Left-upper vertical position, in pixels.
:param tx: Right-lower horizontal position, in pixels.
:param ty: Right-lower vertical position, in pixels.
:param unit: Granularity of mosaic squares, in pixels.
"""
c = image_.crop((fx, fy, tx, ty))
c = _area_mosaic(c, unit)
image_.paste(c, (fx, fy, tx, ty))
return image_
def get_censoring_boxes(filename: str, min_score: float = 0.6, scale_ratio: float = 0.85,
no_pussy: bool = True, no_penis: bool = True,
no_nipples: bool = False) -> List[Tuple[int, int, int, int]]:
"""
Get the areas to be censored with nudenet detection.
:param filename: Filename of the image file (Unfortunately, PIL.Image is not supported. If you want to do \
do, maybe you need to save the Image object to a temporary file and pass the file's path into here).
:param min_score: Min confidence of the detection. The higher the value, the less false positives will be, \
but it also means higher true negatives.
:param scale_ratio: The scaling factor of the censor area, 1 means using the original detected area. \
A lower value means less area will be censored, and vice versa.
:param no_pussy: Detect the female's pussy, default is `True`.
:param no_penis: Detect the male's penis, default is `True`.
:param no_nipples: Detect the female's nipples, default is `False`.
"""
result = detector.detect(filename)
boxes = []
for box in result:
if (no_penis and box['class'] == 'EXPOSED_GENITALIA_M') or \
(no_pussy and box['class'] == 'EXPOSED_GENITALIA_F') or \
(no_nipples and box['class'] == 'EXPOSED_BREAST_F'):
fx, fy, tx, ty = box['box']
width, height = tx - fx, ty - fy
cx, cy = int((fx + tx) / 2), int((fy + ty) / 2)
nfx, ntx = int(cx - width / 2 * scale_ratio), int(cx + width / 2 * scale_ratio)
nfy, nty = int(cy - height / 2 * scale_ratio), int(cy + height / 2 * scale_ratio)
boxes.append((nfx, nfy, ntx, nty))
return boxes
def censor_image(filename, min_score: float = 0.6, scale_ratio: float = 0.7, censor_unit: int = None,
no_pussy: bool = True, no_penis: bool = True, no_nipples: bool = False) -> Image.Image:
"""
Censor the given image.
:param filename: Filename of the image file (Unfortunately, PIL.Image is not supported. If you want to do \
do, maybe you need to save the Image object to a temporary file and pass the file's path into here).
:param min_score: Min confidence of the detection. The higher the value, the less false positives will be, \
but it also means higher true negatives.
:param scale_ratio: The scaling factor of the censor area, 1 means using the original detected area. \
A lower value means less area will be censored, and vice versa.
:param censor_unit: Granularity of mosaic squares, in pixels.
:param no_pussy: Detect the female's pussy, default is `True`.
:param no_penis: Detect the male's penis, default is `True`.
:param no_nipples: Detect the female's nipples, default is `False`.
"""
image_ = Image.open(filename)
width, height = image_.size
censor_unit = int(math.ceil(censor_unit or ((width + height) / 2 / 160)))
for fx, fy, tx, ty in get_censoring_boxes(filename, min_score, scale_ratio, no_pussy, no_penis,
no_nipples):
image_ = mosaic(image_, fx, fy, tx, ty, unit=censor_unit)
return image_
# Here is the usage
if __name__ == '__main__':
censored_image: Image.Image = censor_image(r'D:\\OneDrive - Huafan University\\Python_scripts\\123\\asdf\\20240414_083120.jpg')
censored_image.save(r'D:\\OneDrive - Huafan University\\Python_scripts\\123\\asdf\\asdfasdf.jpg')