opennsfw2

Keras implementation of the Yahoo Open-NSFW model

https://github.com/bhky/opennsfw2

Science Score: 44.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (17.7%) to scientific vocabulary

Keywords

image-classification image-preprocessing jax keras nsfw-classifier tensorflow2
Last synced: 6 months ago · JSON representation ·

Repository

Keras implementation of the Yahoo Open-NSFW model

Basic Info
  • Host: GitHub
  • Owner: bhky
  • License: mit
  • Language: Python
  • Default Branch: main
  • Homepage:
  • Size: 47.5 MB
Statistics
  • Stars: 439
  • Watchers: 10
  • Forks: 58
  • Open Issues: 2
  • Releases: 26
Topics
image-classification image-preprocessing jax keras nsfw-classifier tensorflow2
Created over 4 years ago · Last pushed 6 months ago
Metadata Files
Readme Funding License Citation

README.md

logo

ci License MIT 1.0

Introduction

Detecting Not-Suitable-For-Work (NSFW) content is a high demand task in computer vision. While there are many types of NSFW content, here we focus on the pornographic images and videos.

The Yahoo Open-NSFW model originally developed with the Caffe framework has been a favourite choice, but the work is now discontinued and Caffe is also becoming less popular. Please see the description on the Yahoo project page for the context, definitions, and model training details.

This Open-NSFW 2 project provides a Keras implementation of the Yahoo model, with references to its previous third-party TensorFlow 1 implementation. Note that Keras 3 is compatible with TensorFlow, JAX, and PyTorch. However, currently this model is only guaranteed to work with TensorFlow and JAX.

A simple API is provided for making predictions on images and videos.

Installation

Tested with TensorFlow and JAX, for Python 3.9 to 3.12.

A note on PyTorch:

The OpenNSFW 2 model can in fact be run on PyTorch, but the biggest issue is that the inference output on PyTorch is quite different from that on TensorFlow and JAX. The reason is still unknown. In addition, inference is much slower on PyTorch probably because of the issues discussed here, i.e., PyTorch uses channels_first for its image data format, but this model uses channels_last (as in TensorFLow and JAX), hence Keras has to convert the channel order back and forth at each layer. Therefore, at the moment it is not recommended to use PyTorch for this model.

The best way to install Open-NSFW 2 with its dependencies is from PyPI: shell python3 -m pip install --upgrade opennsfw2 Alternatively, to obtain the latest version from this repository: shell git clone git@github.com:bhky/opennsfw2.git cd opennsfw2 python3 -m pip install .

Usage

Quick examples for getting started are given below. For more details, please refer to the API section.

Images

```python import opennsfw2 as n2

To get the NSFW probability of a single image, provide your image file path,

or a PIL.Image.Image object.

image_handle = "path/to/your/image.jpg"

nsfwprobability = n2.predictimage(image_handle)

To get the NSFW probabilities of a list of images, provide a list of file paths,

or a list of PIL.Image.Image objects.

Using this function is better than looping with predict_image as the model

will only be instantiated once and batching is done during inference.

image_handles = [ "path/to/your/image1.jpg", "path/to/your/image2.jpg", # ... ]

nsfwprobabilities = n2.predictimages(image_handles) ```

Video

```python import opennsfw2 as n2

The video can be in any format supported by OpenCV.

video_path = "path/to/your/video.mp4"

Return two lists giving the elapsed time in seconds and the NSFW probability of each frame.

elapsedseconds, nsfwprobabilities = n2.predictvideoframes(video_path) ```

Lower level with Keras

```python import numpy as np import opennsfw2 as n2 from PIL import Image

Load and preprocess image.

imagepath = "path/to/your/image.jpg" pilimage = Image.open(imagepath) image = n2.preprocessimage(pil_image, n2.Preprocessing.YAHOO)

The preprocessed image is a NumPy array of shape (224, 224, 3).

Create the model.

By default, this call will search for the pre-trained weights file from path:

$HOME/.opennsfw2/weights/opennsfwweights.h5

If not exists, the file will be downloaded from this repository.

The model is a keras_core.Model object.

model = n2.makeopennsfw_model()

Make predictions.

inputs = np.expand_dims(image, axis=0) # Add batch axis (for single image). predictions = model.predict(inputs)

The shape of predictions is (num_images, 2).

Each row gives [sfwprobability, nsfwprobability] of an input image, e.g.:

sfwprobability, nsfwprobability = predictions[0] ```

API

preprocess_image

Apply necessary preprocessing to the input image. - Parameters: - pil_image (PIL.Image.Image): Input as a Pillow image. - preprocessing (Preprocessing enum, default Preprocessing.YAHOO): See preprocessing details. - Return: - NumPy array of shape (224, 224, 3).

Preprocessing

Enum class for preprocessing options. - Preprocessing.YAHOO - Preprocessing.SIMPLE

make_open_nsfw_model

Create an instance of the NSFW model, optionally with pre-trained weights from Yahoo. - Parameters: - input_shape (Tuple[int, int, int], default (224, 224, 3)): Input shape of the model, this should not be changed. - weights_path (Optional[str], default $HOME/.opennsfw/weights/open_nsfw_weights.h5): Path to the weights in HDF5 format to be loaded by the model. The weights file will be downloaded if not exists. If None, no weights will be downloaded nor loaded to the model. Users can provide path if the default is not preferred. The environment variable OPENNSFW2_HOME can also be used to indicate where the .opennsfw2/ directory should be located. - name (str, default opennsfw2): Model name to be used for the Keras model object. - Return: - tf.keras.Model object.

predict_image

End-to-end pipeline function from the input image to the predicted NSFW probability. - Parameters: - image_handle (Union[str, PIL.Image.Image]): Path to the input image file with a format supported by Pillow, or a PIL.Image.Image object. - preprocessing: Same as that in preprocess_image. - weights_path: Same as that in make_open_nsfw_model. - grad_cam_path (Optional[str], default None): If not None, e.g., cam.jpg, a Gradient-weighted Class Activation Mapping (Grad-CAM) overlay plot will be saved, which highlights the important region(s) of the (preprocessed) input image that lead to the prediction. Note that this feature is currently only supported by the TensorFlow backend. - alpha (float, default 0.8): Opacity of the Grad-CAM layer of the plot, only valid if grad_cam_path is not None. - Return: - nsfw_probability (float): The predicted NSFW probability of the image.

predict_images

End-to-end pipeline function from the input images to the predicted NSFW probabilities. - Parameters: - image_handles (Union[Sequence[str], Sequence[PIL.Image.Image]]): List of paths to the input image files with formats supported by Pillow, or list of PIL.Image.Image objects. - batch_size (int, default 8): Batch size to be used for model inference. Choose a value that works the best with your device resources. - preprocessing: Same as that in preprocess_image. - weights_path: Same as that in make_open_nsfw_model. - grad_cam_paths (Optional[Sequence[str]], default None): If not None, the corresponding Grad-CAM plots for the input images will be saved. See the description in predict_image. Note that this feature is currently only supported by the TensorFlow backend. - alpha: Same as that in predict_image. - Return: - nsfw_probabilities (List[float]): Predicted NSFW probabilities of the images.

Aggregation

Enum class for aggregation options in video frames prediction. - Aggregation.MEAN - Aggregation.MEDIAN - Aggregation.MAX - Aggregation.MIN

predict_video_frames

End-to-end pipeline function from the input video to predictions. - Parameters: - video_path (str): Path to the input video source. The video format must be supported by OpenCV. - frame_interval (int, default 8): Prediction will be done on every this number of frames, starting from frame 1, i.e., if this is 8, then prediction will only be done on frame 1, 9, 17, etc. - aggregation_size (int, default 8): Number of frames for which their predicted NSFW probabilities will be aggregated. For instance, if a prediction will be done "on" frame 9 (decided by frame_interval), then it actually means prediction will be done on aggregation_size frames starting from frame 9, e.g., frames 9 to 16 if the size is 8. The predicted probabilities will be aggregated. After aggregation, each of these frames in that interval will be assumed the same aggregated probability. - aggregation (Aggregation enum, default Aggregation.MEAN): The aggregation method. - batch_size (int, default 8, upper-bounded by aggregation_size): Batch size to be used for model inference. Choose a value that works the best with your device resources. - output_video_path (Optional[str], default None): If not None, e.g., out.mp4, an output MP4 video with the same frame size and frame rate as the input video will be saved via OpenCV. The predicted NSFW probability is printed on the top-left corner of each frame. Be aware that the output file size could be much larger than the input file size. This output video is for reference only. - preprocessing: Same as that in preprocess_image. - weights_path: Same as that in make_open_nsfw_model. - progress_bar (bool, default True): Whether to show the progress bar. - Return: - Tuple of List[float], each with length equals to the number of video frames. - elapsed_seconds: Video elapsed time in seconds at each frame. - nsfw_probabilities: NSFW probability of each frame. For any frame_interval > 1, all frames without a prediction will be assumed to have the NSFW probability of the previous predicted frame.

Preprocessing details

This implementation provides the following preprocessing options. - YAHOO: The default option which was used in the original Yahoo's Caffe and the later TensorFlow 1 implementations. The key steps are: - Resize the input Pillow image to (256, 256). - Store the image as JPEG in memory and reload it again to a NumPy image (this step is mysterious, but somehow it really makes a difference). - Crop the centre part of the NumPy image with size (224, 224). - Swap the colour channels to BGR. - Subtract the training dataset mean value of each channel: [104, 117, 123]. - SIMPLE: A simpler and probably more intuitive preprocessing option is also provided, but note that the model output probabilities will be different. The key steps are: - Resize the input Pillow image to (224, 224). - Convert to a NumPy image. - Swap the colour channels to BGR. - Subtract the training dataset mean value of each channel: [104, 117, 123].

Owner

  • Name: Bosco Yung
  • Login: bhky
  • Kind: user

Machine Learning Engineer

Citation (CITATION.cff)

cff-version: 1.2.0
message: "If you use this software, please cite it using the following metadata."
title: "Open-NSFW 2"
version: "0.13.7"
url: "https://github.com/bhky/opennsfw2"
license: "MIT"
authors:
  - family-names: "Yung"
    given-names: "Bosco"
    orcid: "https://orcid.org/0000-0002-3776-1589"
date-released: "2023-12-28"

GitHub Events

Total
  • Issues event: 1
  • Watch event: 83
  • Push event: 21
  • Pull request event: 1
  • Fork event: 13
  • Create event: 1
Last Year
  • Issues event: 1
  • Watch event: 83
  • Push event: 21
  • Pull request event: 1
  • Fork event: 13
  • Create event: 1

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 218
  • Total Committers: 1
  • Avg Commits per committer: 218.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 25
  • Committers: 1
  • Avg Commits per committer: 25.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Bosco Yung 1****y 218

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 16
  • Total pull requests: 10
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 2 days
  • Total issue authors: 13
  • Total pull request authors: 1
  • Average comments per issue: 2.88
  • Average comments per pull request: 0.0
  • Merged pull requests: 9
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 1
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 1
  • Average comments per issue: 0
  • Average comments per pull request: 0.0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • henryruhs (4)
  • yasersakkaf (1)
  • DankMemeGuy (1)
  • NasaKHw (1)
  • fog88 (1)
  • Flori00123 (1)
  • shuangmei (1)
  • MisakaMikoto-o (1)
  • lukywangwang (1)
  • hldh214 (1)
  • FunkyMuse (1)
  • Clasher31HD (1)
  • ardst1 (1)
Pull Request Authors
  • bhky (12)
Top Labels
Issue Labels
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 66,397 last-month
  • Total docker downloads: 55
  • Total dependent packages: 0
  • Total dependent repositories: 68
  • Total versions: 35
  • Total maintainers: 1
pypi.org: opennsfw2

TensorFlow 2 implementation of the Yahoo Open-NSFW model

  • Versions: 35
  • Dependent Packages: 0
  • Dependent Repositories: 68
  • Downloads: 66,397 Last month
  • Docker Downloads: 55
Rankings
Downloads: 0.6%
Dependent repos count: 1.8%
Docker downloads count: 2.8%
Average: 4.0%
Stargazers count: 4.4%
Forks count: 6.9%
Dependent packages count: 7.3%
Maintainers (1)
Last synced: 6 months ago

Dependencies

requirements.txt pypi
  • Pillow >=9.0.0
  • gdown >=4.2.0
  • matplotlib >=3.0.0
  • numpy >=1.22.0
  • opencv-python >=4.0.0.0
  • scikit-image >=0.18.0
  • tensorflow >=2.0.0
  • tqdm >=4.62
.github/workflows/ci.yml actions
  • actions/checkout main composite
  • actions/setup-python main composite
pyproject.toml pypi