Gathering detailed insights and metrics for nsfwjs
Gathering detailed insights and metrics for nsfwjs
Gathering detailed insights and metrics for nsfwjs
Gathering detailed insights and metrics for nsfwjs
npm install nsfwjs
v4.2.1
Published on 11 Nov 2024
Updating ESM Bundling
Published on 11 Oct 2024
Making sure `/dist/models/` is included in build
Published on 06 Mar 2024
Bundling Models
Published on 05 Mar 2024
Version bumps, removing GIF support, warning is using IR model, and many other fun stuff
Published on 09 Feb 2024
Secure NSFWJS
Published on 26 Jun 2021
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
8,123 Stars
707 Commits
547 Forks
85 Watching
25 Branches
53 Contributors
Updated on 29 Nov 2024
TypeScript (78.27%)
JavaScript (21.73%)
Cumulative downloads
Total Downloads
Last day
13.9%
1,170
Compared to previous day
Last week
30.1%
8,876
Compared to previous week
Last month
-5.1%
28,418
Compared to previous month
Last year
32.6%
346,952
Compared to previous year
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.
If you're trying to access the Cloudfront hosted model and are running into an error, it's likely due to the fact that the model has been moved to a new location. Please take a look at our Host your own model section. We will be returning the model after some hotlinkers have been dealt with.
The library categorizes image probabilities in the following 5 classes:
Drawing
- safe for work drawings (including anime)Hentai
- hentai and pornographic drawingsNeutral
- safe for work neutral imagesPorn
- pornographic images, sexual actsSexy
- sexually explicit images, not pornographyThe demo is a continuous deployment source - Give it a go: http://nsfwjs.com
With async/await
support:
1import * as nsfwjs from "nsfwjs"; 2 3const img = document.getElementById("img"); 4 5// If you want to host models on your own or use different model from the ones available, see the section "Host your own model". 6const model = await nsfwjs.load(); 7 8// Classify the image 9const predictions = await model.classify(img); 10console.log("Predictions: ", predictions);
Without async/await
support:
1import * as nsfwjs from "nsfwjs"; 2 3const img = document.getElementById("img"); 4 5// If you want to host models on your own or use different model from the ones available, see the section "Host your own model". 6nsfwjs 7 .load() 8 .then(function (model) { 9 // Classify the image 10 return model.classify(img); 11 }) 12 .then(function (predictions) { 13 console.log("Predictions: ", predictions); 14 });
load
the modelBefore you can classify any image, you'll need to load the model.
1const model = nsfwjs.load(); // Default: "MobileNetV2"
You can use the optional first parameter to specify which model you want to use from the three that are bundled together. Defaults to: "MobileNetV2"
. This supports tree-shaking on supported bundlers like Webpack, so you will only be loading the model you are using.
1const model = nsfwjs.load("MobileNetV2Mid"); // "MobileNetV2" | "MobileNetV2Mid" | "InceptionV3"
You can also use same parameter and load the model from your website/server, as explained in the Host your own model section. Doing so could reduce the bundle size for loading the model by approximately 1.33 times (33%) since you can directly use the binary files instead of the base64 that are bundled with the package. i.e. The "MobileNetV2"
model bundled into the package is 3.5MB instead of 2.6MB for hosted binary files. This would only make a difference if you are loading the model every time (without Caching) on the client-side browser since on the server-side, you'd only be loading the model once at the server start.
Model MobileNetV2 - 224x224
1const model = nsfwjs.load("/path/to/mobilenet_v2/");
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 MobileNetV2Mid - Graph
1/* You may need to load this model with graph type */ 2const model = nsfwjs.load("/path/to/mobilenet_v2_mid/", { type: 'graph' });
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 InceptionV3 - 299x299
1const model = nsfwjs.load("/path/to/inception_v3/", { size: 299 });
If you're using in the browser and you'd like to subsequently load from indexed db or local storage (NOTE: model size may be too large for local storage!) you can save the underlying model using the appropriate scheme and load from there.
1const initialLoad = await nsfwjs.load( 2 "/path/to/different/model/" /*, { ...options }*/ 3); 4await initialLoad.model.save("indexeddb://exampleModel"); 5const model = await nsfwjs.load("indexeddb://exampleModel" /*, { ...options }*/);
Parameters
Initial Load:
model.json
.Subsequent Load:
Returns
Troubleshooting
classify
an imageThis function can take any browser-based image elements (<img>
, <video>
, <canvas>
) and returns an array of most likely predictions and their confidence levels.
1// Return top 3 guesses (instead of all 5) 2const predictions = await model.classify(img, 3);
Parameters
Returns
className
and probability
. Array size is determined by the second parameter in the classify
function.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.
1import * as tf from "@tensorflow/tfjs"; 2import * as nsfwjs from "nsfwjs"; 3tf.enableProdMode(); 4//... 5let model = await nsfwjs.load(`${urlToNSFWJSModel}`);
NOTE: Consider downloading and hosting the model yourself before moving to production as explained in the Host your own model section. This could potentially improve the initial load time of the model. Furthermore, consider Caching the model, if you are using it in the browser.
NSFWJS is powered by TensorFlow.js as a peer dependency. If your project does not already have TFJS you'll need to add it.
1# peer dependency 2$ yarn add @tensorflow/tfjs 3# install NSFWJS 4$ yarn add nsfwjs
For script tags include all the bundles as shown here. Then simply access the nsfwjs global variable. This requires that you've already imported TensorFlow.js as well.
The magic that powers NSFWJS is the NSFW detection model. By default, the models are bundled into this package. But you may want to host the models on your own server to reduce bundle size by loading them as raw binary files or to host your own custom model. If you want to host your own version of the model files, you can do so by following the steps below. You can then pass the relative URL to your hosted files in the load
function along with the options
if necessary.
Here is how to install the default model on a website:
git clone https://github.com/infinitered/nsfwjs.git
. If downloading as zip does not work use cloning.models
folder from the root of the project and drop it in the public
directory of your web application to serve them as static files along side your website. (You can host it anywhere such as on a s3 bucket as long as you can access it via URL).nsfwjs.load()
. For example: nsfwjs.load(https://yourwebsite.com/models/mobilenet_v2/model.json)
.The demo that powers https://nsfwjs.com/ is available in the examples/nsfw_demo
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
.
A browserified version using nothing but promises and script tags is available in the minimal_demo
folder.
1<script src="/path/to/model/directory/model.min.js"></script> 2<script src="/path/to/model/directory/group1-shard1of2.min.js"></script> 3<script src="/path/to/model/directory/group1-shard2of2.min.js"></script> 4<script src="/path/to/bundle/nsfwjs.min.js"></script>
You should host the nsfwjs.min.js
file and all the model bundles that you want to use alongside your project, and reference them using the src
attribute in the script tags.
Loads a local copy of the model to reduce network load and utilizes TFJS-React-Native. Blog Post
Using NPM, you can also use the model on the server side.
1$ npm install nsfwjs 2$ npm install @tensorflow/tfjs-node
1const axios = require("axios"); //you can use any http client 2const tf = require("@tensorflow/tfjs-node"); 3const nsfw = require("nsfwjs"); 4async function fn() { 5 const pic = await axios.get(`link-to-picture`, { 6 responseType: "arraybuffer", 7 }); 8 const model = await nsfw.load(); // To load a local model, nsfw.load('file://./path/to/model/') 9 // Image must be in tf.tensor3d format 10 // you can convert image to tf.tensor3d with tf.node.decodeImage(Uint8Array,channels) 11 const image = await tf.node.decodeImage(pic.data, 3); 12 const predictions = await model.classify(image); 13 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). 14 console.log(predictions); 15} 16fn();
Here is another full example of a multipart/form-data POST using Express, supposing you are using JPG format.
1const express = require("express"); 2const multer = require("multer"); 3const jpeg = require("jpeg-js"); 4 5const tf = require("@tensorflow/tfjs-node"); 6const nsfw = require("nsfwjs"); 7 8const app = express(); 9const upload = multer(); 10 11let _model; 12 13const convert = async (img) => { 14 // Decoded image in UInt8 Byte array 15 const image = await jpeg.decode(img, { useTArray: true }); 16 17 const numChannels = 3; 18 const numPixels = image.width * image.height; 19 const values = new Int32Array(numPixels * numChannels); 20 21 for (let i = 0; i < numPixels; i++) 22 for (let c = 0; c < numChannels; ++c) 23 values[i * numChannels + c] = image.data[i * 4 + c]; 24 25 return tf.tensor3d(values, [image.height, image.width, numChannels], "int32"); 26}; 27 28app.post("/nsfw", upload.single("image"), async (req, res) => { 29 if (!req.file) res.status(400).send("Missing image multipart/form-data"); 30 else { 31 const image = await convert(req.file.buffer); 32 const predictions = await _model.classify(image); 33 image.dispose(); 34 res.json(predictions); 35 } 36}); 37 38const load_model = async () => { 39 _model = await nsfw.load(); 40}; 41 42// Keep the model in memory, make sure it's loaded only once 43load_model().then(() => app.listen(8080)); 44 45// 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 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 how to write your own library like NSFWJS with my O'Reilly book "Learning TensorFlow.js" available on O'Reilly and Amazon.
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.
NSFWJS, as open source, is free to use and always will be :heart:. 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.
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
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
No vulnerabilities found.
Reason
7 commit(s) and 5 issue activity found in the last 90 days -- score normalized to 10
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 8/12 approved changesets -- score normalized to 6
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
security policy file not detected
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
38 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More