• Stars
    star
    7,194
  • Rank 5,397 (Top 0.2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 6 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

NSFW detection on the client-side via TensorFlow.js

NSFWJS Logo

Client-side indecent content checking

All Contributors CircleCI Netlify Status

A simple JavaScript library to help you quickly identify unseemly images; all in the client's browser. NSFWJS isn't perfect, but it's pretty accurate (~90% with small and ~93% with midsized model)... and it's getting more accurate all the time.

Why would this be useful? Check out the announcement blog post.

demo example

Table of Contents

The library categorizes image probabilities in the following 5 classes:

  • Drawing - safe for work drawings (including anime)
  • Hentai - hentai and pornographic drawings
  • Neutral - safe for work neutral images
  • Porn - pornographic images, sexual acts
  • Sexy - sexually explicit images, not pornography

The demo is a continuous deployment source - Give it a go: http://nsfwjs.com/

QUICK: How to use the module

With async/await support:

import * as nsfwjs from 'nsfwjs'

const img = document.getElementById('img')

// Load model from my S3.
// See the section hosting the model files on your site.
const model = await nsfwjs.load()

// Classify the image
const predictions = await model.classify(img)
console.log('Predictions: ', predictions)

Without async/await support:

import * as nsfwjs from 'nsfwjs'

const img = document.getElementById('img')

// Load model from my S3.
// See the section hosting the model files on your site.
nsfwjs.load()
  .then(function (model) {
    // Classify the image
    return model.classify(img)
  })
  .then(function (predictions) {
    console.log('Predictions: ', predictions)
  })

Library API

load the model

Before you can classify any image, you'll need to load the model. You should use the optional first parameter and load the model from your website, as explained in the install directions.

Model example - 224x224

const model = nsfwjs.load('/path/to/model/directory/')

If you're using a model that needs an image of dimension other than 224x224, you can pass the size in the options parameter.

Model example - 299x299

const model = nsfwjs.load('/path/to/different/model/', { size: 299 })

If you're using a graph model, you cannot use the infer method, and you'll need to tell model load that you're dealing with a graph model in options.

Model example - Graph

const model = nsfwjs.load('/path/to/different/model/', { type: 'graph' })

If you're using in the browser and you'd like to subsequently load from indexed db or local storage you can save the underlying model using the appropriate scheme and load from there.

const initialLoad = await nsfwjs.load('/path/to/different/model')
await initialLoad.model.save('indexeddb://model')
const model = await nsfwjs.load('indexeddb://model')

Parameters

  • optional URL to the model.json folder.
  • optional object with size property that your model expects.

Returns

  • Ready to use NSFWJS model object

classify an image

This function can take any browser-based image elements (<img>, <video>, <canvas>) and returns an array of most likely predictions and their confidence levels.

// Return top 3 guesses (instead of all 5)
const predictions = await model.classify(img, 3)

Parameters

  • Tensor, Image data, Image element, video element, or canvas element to check
  • Number of results to return (default all 5)

Returns

  • Array of objects that contain className and probability. Array size is determined by the second parameter in the classify function.

classifyGif

Gif Example

This function can take a browser-based image element (<img>) that is a GIF, and returns an array of prediction arrays. It breaks a GIF into its frames and runs classify on each with a given configuration. This can take a while, as GIFs are frequently hundreds of frames.

// Returns all predictions of each GIF frame
const framePredictions = await model.classifyGif(img)

If you're looking to update the user on status (e.g. progress bar) or change the number of top results per frame, then you can utilize the configuration parameter.

Example of passing a configuration:

// returns top 1 prediction of each GIF frame, and logs the status to console
const myConfig = {
  topk: 1,
  fps: 1,
  onFrame: ({ index, totalFrames, predictions, image }) => {
    console.log({ index, totalFrames, predictions })
    // document.body.appendChild(image)
    // require('fs').writeFileSync(`./file.jpeg`, require('jpeg-js').encode(image).data)
  }
}
const framePredictions = await classifyGif(img, myConfig)

Parameters

  • Image element to check
  • Configuration object with the following possible key/values:
    • topk - Number of results to return per frame (default all 5)
    • fps - Frames per seconds, frames picks proportionally from the middle (default all frames)
    • onFrame - Function callback on each frame - Param is an object with the following key/values:
      • index - the current GIF frame that was classified (starting at 0)
      • totalFrames - the complete number of frames for this GIF (for progress calculations)
      • predictions - an array of length topk, returning top results from classify
      • image - an image of specific frame

Returns

  • Array of the same order as number of frames in GIF. Each index corresponding to that frame, an returns array of objects that contain className and probability; sorted by probability and limited by topk config parameter.

Production

Tensorflow.js offers two flags, enableProdMode and enableDebugMode. If you're going to use NSFWJS in production, be sure to enable prod mode before loading the NSFWJS model.

import * as tf from '@tensorflow/tfjs'
import * as nsfwjs from 'nsfwjs'
tf.enableProdMode()
//...
let model = await nsfwjs.load(`${urlToNSFWJSModel}`)

Install

NSFWJS is powered by TensorFlow.js as a peer dependency. If your project does not already have TFJS you'll need to add it.

# peer dependency
$ yarn add @tensorflow/tfjs
# install NSFWJS
$ yarn add nsfwjs

For script tags add <script type="text/javascript" src="https://unpkg.com/nsfwjs"></script>. Then simply access the nsfwjs global variable. This requires that you've already imported TensorFlow.js as well.

Host your own model

The magic that powers NSFWJS is the NSFW detection model. By default, this node module is pulling from my S3, but I make no guarantees that I'll keep that download link available forever. It's best for the longevity of your project that you download and host your own version of the model files. You can then pass the relative URL to your hosted files in the load function. If you can come up with a way to bundle the model into the NPM package, I'd love to see a PR to this repo!

Run the Examples

Tensorflow.js in the browser

The demo that powers https://nsfwjs.com/ is available in the nsfw_demo example folder.

To run the demo, run yarn prep which will copy the latest code into the demo. After that's done, you can cd into the demo folder and run with yarn start.

Browserify

A browserified version using nothing but promises and script tags is available in the minimal_demo folder.

Please do not use the script tags hosted in this demo as a CDN. This can and should be hosted in your project along side the model files.

React Native

The NSFWJS React Native app React Native Demo

Loads a local copy of the model to reduce network load and utilizes TFJS-React-Native. Blog Post

Node JS App

Using NPM, you can also use the model on the server side.

$ npm install nsfwjs
$ npm install @tensorflow/tfjs-node
const axios = require('axios') //you can use any http client
const tf = require('@tensorflow/tfjs-node')
const nsfw = require('nsfwjs')
async function fn() {
  const pic = await axios.get(`link-to-picture`, {
    responseType: 'arraybuffer',
  })
  const model = await nsfw.load() // To load a local model, nsfw.load('file://./path/to/model/')
  // Image must be in tf.tensor3d format
  // you can convert image to tf.tensor3d with tf.node.decodeImage(Uint8Array,channels)
  const image = await tf.node.decodeImage(pic.data,3)
  const predictions = await model.classify(image)
  image.dispose() // Tensor memory must be managed explicitly (it is not sufficient to let a tf.Tensor go out of scope for its memory to be released).
  console.log(predictions)
}
fn()

Here is another full example of a multipart/form-data POST using Express, supposing you are using JPG format.

const express = require('express')
const multer = require('multer')
const jpeg = require('jpeg-js')

const tf = require('@tensorflow/tfjs-node')
const nsfw = require('nsfwjs')

const app = express()
const upload = multer()

let _model

const convert = async (img) => {
  // Decoded image in UInt8 Byte array
  const image = await jpeg.decode(img, { useTArray: true })

  const numChannels = 3
  const numPixels = image.width * image.height
  const values = new Int32Array(numPixels * numChannels)

  for (let i = 0; i < numPixels; i++)
    for (let c = 0; c < numChannels; ++c)
      values[i * numChannels + c] = image.data[i * 4 + c]

  return tf.tensor3d(values, [image.height, image.width, numChannels], 'int32')
}

app.post('/nsfw', upload.single('image'), async (req, res) => {
  if (!req.file) res.status(400).send('Missing image multipart/form-data')
  else {
    const image = await convert(req.file.buffer)
    const predictions = await _model.classify(image)
    image.dispose()
    res.json(predictions)
  }
})

const load_model = async () => {
  _model = await nsfw.load()
}

// Keep the model in memory, make sure it's loaded only once
load_model().then(() => app.listen(8080))

// curl --request POST localhost:8080/nsfw --header 'Content-Type: multipart/form-data' --data-binary 'image=@/full/path/to/picture.jpg'

You can also use lovell/sharp for preprocessing tasks and more file formats.

NSFW Filter

NSFW Filter is a web extension that uses NSFWJS for filtering out NSFW images from your browser.

It is currently available for Chrome and Firefox and is completely open-source.

Check out the project here.

Learn TensorFlow.js

Learn how to write your own library like NSFWJS with my O'Reilly book "Learning TensorFlow.js" available on O'Reilly and Amazon.

Learning TensorFlow.js JavaScript Book Red

More!

An FAQ page is available.

More about NSFWJS and TensorFlow.js - https://youtu.be/uzQwmZwy3yw

The model was trained in Keras over several days and 60+ Gigs of data. Be sure to check out the model code which was trained on data provided by Alexander Kim's nsfw_data_scraper.

Open Source

NSFWJS, as open source, is free to use and always will be ❀️. It's MIT licensed, and we'll always do our best to help and quickly answer issues. If you'd like to get a hold of us, join our community slack.

Need the experts? Hire Infinite Red for your next project

If your project's calling for the experts in all things React Native, Infinite Red’s here to help! Our experienced team of software engineers have worked with companies like Microsoft, Zoom, and Mercari to bring even some of the most complex projects to life.

Whether it’s running a full project or training a team on React Native, we can help you solve your company’s toughest engineering challenges – and make it a great experience at the same time. Ready to see how we can work together? Send us a message

Contributors

Thanks goes to these wonderful people (emoji key):


Gant Laborde

πŸ’¬ πŸ“ πŸ’» πŸ’‘ πŸ€” πŸš‡ πŸ‘€ ⚠️

Jamon Holmgren

πŸ“– πŸ€” πŸ’» πŸ–‹

Jeff Studenski

🎨

Frank von Hoven III

πŸ“– πŸ€”

Sandesh Soni

πŸ’»

Sean Nam

πŸ“–

Gilbert Emerson

πŸ’»

Oleksandr Kozlov

πŸš‡ ⚠️ πŸ’»

Morgan

πŸ’» πŸ€”

Michel Hua

πŸ’» πŸ“–

Kevin VanGelder

πŸ’» πŸ“–

Jesse Nicholson

πŸ”£ πŸ€”

camhart

πŸ“–

Cameron Burkholder

🎨

qwertyforce

πŸ“–

Yegor <3

πŸ’» ⚠️

Navendu Pottekkat

πŸ“–

Vladislav

πŸ’» πŸ“–

Nacht

πŸ’»

kateinkim

πŸ’» πŸ“–

jan

πŸ“–

Rohan Mukherjee

πŸ’¬ πŸš‡ 🚧 πŸ’»

This project follows the all-contributors specification. Contributions of any kind welcome!

More Repositories

1

ignite

Infinite Red's battle-tested React Native project boilerplate, along with a CLI, component/model generators, and more!
TypeScript
17,283
star
2

reactotron

A desktop app for inspecting your React JS and React Native projects. macOS, Linux, and Windows.
TypeScript
14,757
star
3

gluegun

A delightful toolkit for building TypeScript-powered command-line apps.
TypeScript
2,937
star
4

apisauce

Axios + standardized errors + request/response transforms.
JavaScript
2,789
star
5

thesis-phoenix

A lightweight, bolt-on, intuitive content editing system for Elixir/Phoenix websites. Star this repo and follow along with our progress!
Elixir
648
star
6

ignite-bowser

Bowser is now re-integrated into Ignite CLI! Head to https://github.com/infinitered/ignite to check it out.
TypeScript
615
star
7

solidarity

Solidarity is an environment checker for project dependencies across multiple machines.
TypeScript
614
star
8

ignite-andross

The original React Native boilerplate from Infinite Red - Redux, React Navigation, & more
JavaScript
475
star
9

ChainReactApp2017

The official Chain React Conf 2017 App
JavaScript
437
star
10

rmq

RMQ - RubyMotionQuery
HTML
307
star
11

redpotion

We believe iPhone development should be clean, scalable, and fast with a language that developers not only enjoy, but actively choose. With the advent of Ruby for iPhone development the RubyMotion community has combined and tested the most active and powerful gems into a single package called RedPotion
Ruby
234
star
12

cdq

Core Data Query for RubyMotion
Ruby
172
star
13

ChainReactApp2019

The Chain React 2019 Conference App
TypeScript
165
star
14

react-native-mlkit

The definitive MLKit wrapper for React Native and Expo
TypeScript
124
star
15

nsfwjs-mobile

NSFWjs in React Native
JavaScript
112
star
16

ChainReactApp2023

The official Chain React App for #ChainReact2023, written in React Native
TypeScript
110
star
17

reactotron-react-native

Reactotron's react-native client.
TypeScript
110
star
18

ruby-xcdm

Ruby XCDM
Ruby
94
star
19

bluepotion

Like RedPotion, but for Android
Ruby
74
star
20

ProMotion-menu

RubyMotion gem allowing you to easily setup a facebook or Path style hidden slide menu easily with the ProMotion gem.
Ruby
74
star
21

ramdasauce

Ramda smothered in saucy helpers.
JavaScript
69
star
22

awesome-react-testing

React and React Native testing tools and strategies
67
star
23

firebird

Template for Phoenix 1.3 projects
Elixir
66
star
24

phoenix_base

Template project for Phoenix
Elixir
65
star
25

flipper-plugin-reactotron

A plugin for the Flipper desktop application
TypeScript
63
star
26

ignite-cookbook

Ignite Cookbook for React Native
CSS
47
star
27

ignite-example-login

This is an example Ignited app that shows how to integrate a login screen with redux-aware react navigation
JavaScript
47
star
28

solidarity-react-native

Solidarity snapshot plugin for React Native projects
JavaScript
47
star
29

ai-lab

Library of components for TensorFlow.js in web frameworks.
TypeScript
46
star
30

ionicons-version-3-search

Quickly identify IonIcons from version 3, with version 2 names as tags!
JavaScript
41
star
31

apex

Apex: the RubyMotion web framework for OS X.
Ruby
31
star
32

ir-docs

Omnibus Documentation for Infinite Red Opensource
CSS
26
star
33

ignite-ir-boilerplate-2016

[Not supported] A boilerplate for Ignite with best practices we've learned from 2015.
JavaScript
26
star
34

ignite-bowser-examples

This repository is out of date and is archived here for historical purposes only. See current Ignite Bowser for more relevant examples.
TypeScript
26
star
35

maybe

Access Elixir maps and structs, protected from `nil`
Elixir
25
star
36

open-source

Information and Guides for Infinite Red Open Source Projects
24
star
37

thesis-rails

Thesis: A Rails CMS that doesn't hijack your development workflow. [Deprecated]
Ruby
23
star
38

authority

Next-gen Elixir authentication specification
Elixir
22
star
39

babel-plugin-ignite-ignore-reactotron

Strips Reactotron from production builds for Ignite-based apps.
JavaScript
21
star
40

ChainReactApp2022

TypeScript
20
star
41

react-navx

[Experimental] Navigation and state management in one place for your React Native projects, featuring React Navigation and MobX / MST
TypeScript
20
star
42

mst-reference-pool

MST Reference Pool is a MobX-State-Tree extension that allows you to use references to a pool of model instances in any store.
TypeScript
20
star
43

ProMotion-iap

In-app purchases for ProMotion!
Ruby
19
star
44

ProMotion-form

Deprecated -- use ProMotion-XLForm
Ruby
19
star
45

ignite-maps

Painlessly add react-native-maps to your React Native app using Ignite and Ignite Maps.
EJS
19
star
46

ProMotion-push

Push notification support for ProMotion.
Ruby
18
star
47

rmq-example-app-image-browser

An example app for RubyMotionQuery (rmq). The user can query, browse, and zoom photos. Uses RMQ and AFMotion
Ruby
18
star
48

Parsistence

A nice wrapper for your Parse models on RubyMotion, complete with querying and much more.
Ruby
17
star
49

reactotron-react-js

Reactotron's react-dom client.
TypeScript
16
star
50

whitepotion

WhitePotion is just like RedPotion, but for OS X
Ruby
15
star
51

ProMotion-map

ProMotion::MapScreen gem. Extracted from ProMotion core.
Ruby
13
star
52

react-native-ai

13
star
53

motion-scene-kit

SceneKit stuff in RubyMotion
Ruby
13
star
54

middleman-template

A nice default project template for Middleman, the fantastic static site building tool.
CSS
12
star
55

harvest-invision-integration

Install this User Script via TamperMonkey to add Harvest Tracker to Invision Enterprise workflow pages
JavaScript
12
star
56

authority_ecto

Ecto integration for Authority https://github.com/infinitered/authority
Elixir
12
star
57

rmq-slide-over-control

A RubyMotion RMQ control that places a draggable view over another view, allowing the user to show more or less of the main view below
Ruby
12
star
58

keras-model-zoo

Ready to go, downloadable models for Keras
11
star
59

ignite-json-server

Ignite plugin that adds json-server to an Ignited project
JavaScript
10
star
60

reactotron-redux

The redux plugin for reactotron that allows tracking redux actions and state
TypeScript
10
star
61

reactotron-redux-saga

The redux saga plugin for reactotron. Allows for tracking of Redux Sagas
TypeScript
10
star
62

reactotron-core-client

The core client for all reactotron clients
TypeScript
10
star
63

ignite-redux-persist

An Ignite CLI plugin for Redux Persist
JavaScript
9
star
64

addon-storyshots

JavaScript
8
star
65

rmq-template

A template for RubyMotionQuery projects
Ruby
8
star
66

DiveIntoNative

Just scratching the surface of jumping into Native
Objective-C
7
star
67

ignite-dev-screens

Ignite DevScreens plugin for ignite-cli
JavaScript
7
star
68

tensorplayground

Playground for visual tensors and interactive code
JavaScript
7
star
69

mithril_pubsub

A PubSub layer for Mithril-architected apps
Elixir
6
star
70

ignite-animatable

An ignite plugin for react-native-animatable.
JavaScript
6
star
71

reactotron-core-server

The core reactotron server used by the reactotron app
TypeScript
6
star
72

redpotion-template

Ruby
5
star
73

bluepotion-template

Ruby
5
star
74

ignite-vector-icons

An ignite plugin for `react-native-vector-icons`.
JavaScript
5
star
75

jest-preset-ignite

Glues together TypeScript, React Native, and Jest.
JavaScript
5
star
76

ignite-redux-devtools

An Ignite CLI plugin for Redux DevTools
JavaScript
5
star
77

reactotron-mst

Reactotron's mobx-state-tree plugin
TypeScript
4
star
78

ignite-i18n

An ignite plugin for react-native-i18n.
JavaScript
4
star
79

reactotron-core-ui

TypeScript
4
star
80

ueberauth_dwolla

Ueberauth Plugin for OAuth through Dwolla
Elixir
3
star
81

ups

Address validation/normalization against UPS API
Elixir
3
star
82

ignite-ir-boilerplate

Boilerplate Index
3
star
83

whack-a-mole

A game to demonstrate lists, lifecycle methods, and fundamentals of React Native
JavaScript
3
star
84

tutorial-movie

A demo CLI app, powered by Gluegun
TypeScript
3
star
85

ignite-next-js

Ignite Next.js website boilerplate with Next.js, MySQL, and Github authentication
JavaScript
3
star
86

elavon-elixir

Native elixir client for USBank Elavon Converge API
Elixir
3
star
87

ignite-plugins

The Official Ignite Plugin Registry
3
star
88

eversign

Elixir wrapper for Eversign API
Elixir
2
star
89

MarqueeMark

Large text displayer.
Objective-C
2
star
90

reactotron-apisauce

Reactotron's apisauce plugin
TypeScript
2
star
91

msterymeat

mobx-state-tree proclivities
TypeScript
2
star
92

motion-conf

motion-conf is an easy to use configuration class generator for your RubyMotion apps.
Ruby
2
star
93

wpf-base

Base React Native Windows WPF project for bare bones use in upstream
C#
2
star
94

mobx-forge

TypeScript
2
star
95

cr-2024-intermediate-workshop-lessons

TypeScript
2
star
96

cr-2024-intermediate-workshop-template

TypeScript
2
star
97

orb-publish-docs

CircleCI Orb for publishing docs
Shell
1
star
98

TrainingAppDec2018

What we covered in the online Infinite Red Academy training on December 12, 2018
JavaScript
1
star
99

rmq-plugin-template

Template Repo for RMQ
HTML
1
star
100

solidarity-stacks

Community Solidarity files for well known software stacks
1
star