Giter Club home page Giter Club logo

nsfwjs's Introduction

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

NOTE

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.

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");

// If you want to host models on your own or use different model from the ones available, see the section "Host your own model".
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");

// If you want to host models on your own or use different model from the ones available, see the section "Host your own model".
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.

const 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.

const 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

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 MobileNetV2Mid - 299x299

const model = nsfwjs.load("/path/to/model/", { size: 299 });
/* You may need to load this model with graph type */
const model = nsfwjs.load("/path/to/model/", { 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 - Graph

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

Caching

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.

const initialLoad = await nsfwjs.load(
  "/path/to/different/model/" /*, { ...options }*/
);
await initialLoad.model.save("indexeddb://exampleModel");
const model = await nsfwjs.load("indexeddb://exampleModel" /*, { ...options }*/);

Parameters

Initial Load:

  1. URL or path to folder containing model.json.
  2. Optional object with size or type property that your model expects.

Subsequent Load:

  1. IndexedDB path.
  2. Optional object with size or type property that your model expects.

Returns

  • Ready to use NSFWJS model object

Troubleshooting

  • On the tab where the model is being loaded, inspect element and navigate to the the "Application" tab. On the left pane under the "Storage" section, there is a subsection named "IndexedDB". Here you can view if the model is being saved.

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.

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}`);

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.

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 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.

Host your own model

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:

  1. Download the project by either downloading as zip or cloning git clone https://github.com/infinitered/nsfwjs.git. If downloading as zip does not work use cloning.
  2. Extract the 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).
  3. Retrieve the URL and put it into nsfwjs.load(). For example: nsfwjs.load(https://yourwebsite.com/models/mobilenet_v2/model.json).

Run the Examples

Tensorflow.js in the browser

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.

Browserify

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

<script src="/path/to/model/directory/model.min.js"></script>
<script src="/path/to/model/directory/group1-shard1of2.min.js"></script>
<script src="/path/to/model/directory/group1-shard2of2.min.js"></script>
<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.

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
Gant Laborde

๐Ÿ’ฌ ๐Ÿ“ ๐Ÿ’ป ๐Ÿ’ก ๐Ÿค” ๐Ÿš‡ ๐Ÿ‘€ โš ๏ธ
Jamon Holmgren
Jamon Holmgren

๐Ÿ“– ๐Ÿค” ๐Ÿ’ป ๐Ÿ–‹
Mazen Chami
Mazen Chami

๐Ÿ“– ๐Ÿ’ป ๐Ÿ‘€ โš ๏ธ
Jeff Studenski
Jeff Studenski

๐ŸŽจ
Frank von Hoven III
Frank von Hoven III

๐Ÿ“– ๐Ÿค”
Sandesh Soni
Sandesh Soni

๐Ÿ’ป
Sean Nam
Sean Nam

๐Ÿ“–
Gilbert Emerson
Gilbert Emerson

๐Ÿ’ป
Oleksandr Kozlov
Oleksandr Kozlov

๐Ÿš‡ โš ๏ธ ๐Ÿ’ป
Morgan
Morgan

๐Ÿ’ป ๐Ÿค”
Michel Hua
Michel Hua

๐Ÿ’ป ๐Ÿ“–
Kevin VanGelder
Kevin VanGelder

๐Ÿ’ป ๐Ÿ“–
Jesse Nicholson
Jesse Nicholson

๐Ÿ”ฃ ๐Ÿค”
camhart
camhart

๐Ÿ“–
Cameron Burkholder
Cameron Burkholder

๐ŸŽจ
qwertyforce
qwertyforce

๐Ÿ“–
Yegor <3
Yegor <3

๐Ÿ’ป โš ๏ธ
Navendu Pottekkat
Navendu Pottekkat

๐Ÿ“–
Vladislav
Vladislav

๐Ÿ’ป ๐Ÿ“–
Nacht
Nacht

๐Ÿ’ป
kateinkim
kateinkim

๐Ÿ’ป ๐Ÿ“–
jan
jan

๐Ÿ“–
Rohan Mukherjee
Rohan Mukherjee

๐Ÿ’ฌ ๐Ÿš‡ ๐Ÿšง ๐Ÿ’ป
Hasitha Wickramasinghe
Hasitha Wickramasinghe

๐Ÿ’ป ๐Ÿ“– ๐Ÿ’ก ๐Ÿค” ๐Ÿš‡ โš ๏ธ

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

nsfwjs's People

Contributors

camhart avatar cdanwards avatar chungmire avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar derekgreenberg avatar emer7 avatar gantman avatar hazya avatar jacklangerman avatar jamonholmgren avatar janpoonthong avatar jpoehnelt avatar jstudenski avatar kateinkim avatar kevinvangelder avatar madriix avatar mazenchami avatar mycaule avatar pottekkat avatar qwertyforce avatar roerohan avatar romanzrv avatar sandeshsoni avatar snyk-bot avatar suikodev avatar vladstepanov avatar xilaraux avatar yzevm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nsfwjs's Issues

Nice Feature Idea - Scrub GIF

It would be pretty cool if when you scubbed the victory bar for a GIF, the associated GIF frame was shown. This can happen by having an option passed in for a reference to the SuperGIF and then using move_to(index). If you don't want the supergif, it's set to NULL in memory like it is currently.

I'd love to see why a particular frame is misclassified!

Cannot read property 'filterHeight' of undefined

hello~ i'm new to nsfwjs. when i run minimal_demo program on chrome, i got the following error.

Uncaught (in promise) TypeError: Cannot read property 'filterHeight' of undefined.

Anyone can help me?

Allowing for pre gzip the 6 model files

The 6 model files are quite large. If the nsfwjs are to be used by many clients, there might be others out there who see the need to pre compress the model files - and just serve the pre compressed files to the client. This way saving bandwidth and CPU usage on the server - as well as the user has quicker access to the web page.
Found a solution on how to serve pre compressed files from Apache here:
https://gist.github.com/bhollis/2200790
So there obviously is no need to change anything in model.json file to make this work, since it all can be solved in a .htaccess file.
Originally this was formed as a question, since I believed there had to be some changes to the model.json file to make this work. But there is no need for that. I'm not an expert in Apache and code in .htaccess - but the information below has been tested on a live server (web hotel), and does work (you just have to get the new lines correct though - they got messed up by some reason when displayed here).

Here is how I did it:

First I compressed the 6 files in the model directory (the files starting with "group1-", using 7-zip.
So the original file named group1-shard1of6 ended up
with this filename: group1-shard1of6.gz
After compressing the 6 files, deleted the 6 corresponding uncompressed files, and added a .htaccess file (in same directory where I have the model files) with the content below (new lines is removed by the editor here, so they have to be fixed if using this code):

Options +SymLinksIfOwnerMatch RewriteEngine On AddEncoding gzip .gz ExpiresActive On ExpiresDefault "access plus 2 months" RewriteCond %{HTTP:Accept-encoding} gzip RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)1of6 group1-shard1of6.gz [QSA,L] RewriteRule ^(.*)2of6 group1-shard2of6.gz [QSA,L] RewriteRule ^(.*)3of6 group1-shard3of6.gz [QSA,L] RewriteRule ^(.*)4of6 group1-shard4of6.gz [QSA,L] RewriteRule ^(.*)5of6 group1-shard5of6.gz [QSA,L] RewriteRule ^(.*)6of6 group1-shard6of6.gz [QSA,L] <Files *.gz> ForceType text/javascript </Files>


With and without gzip compression for the first model file:
group1-shard1of6 = 4096 KB
group1-shard1of6.gz = 2698 KB

Just by compressing the 5 largest files the
client will "save" approximately 5 * 1400 KB = 7000 KB in the download process.

Classifying Image data?

I was curious about the capabilities of NSFWJS, when it came to classifying Image data, instead of an actual element. In the Parameters of ClassifyImage, it states:

Tensor, Image data, Image element, video element, or canvas element to check

So does that mean I could potentially pass an images base64 data to NSFWJS, and it would render the results, or does it have to be the actual image element itself?

I'm just curious about the applications of this, and how it could be used server side.

5-6 seconds - or more, before model load and client (user) can use the page - how to improve?

I'm currently testing this interesting nsfwjs module on a live server.

I activate this code:
pdModel = await nsfwjs.load('model/');

via a call to an async function triggered by the onLoad event.
The 6 model files are fetched from the disk and is using approximately 960ms to load (I see this using Chrome inspector - Network tab).
After this I have to wait approx. 5-6 seconds before I get any response from the page. From what happens in the Memory tab in Inspector, it looks like the nsfwjs load is using this time to do something.

After the 5-6 seconds. I can select an image. When that is done, this code (in another async function):
var img = new Image();
img.src = document.getElementById('img_url').src;
var predictions = await pdModel.classify(img);
console.log('Predictions', predictions);

is using about 1,5 - 2 seconds to finish.
This is acceptable time for me.
This time usage of about 1.5 -2 seconds - is consistent.

But the usage of 5-6 seconds nsfwjs use to do something - before anything else can happen in the page (e.g. select an image to analyze), is quite a long time - for an end user which want to do something as soon as possible.

So... is there a way to speed up the time nsfwjs uses to finish this part:
pdModel = await nsfwjs.load('model/');
and whatever it does before the page is ready for handling user triggered events in the page?

Could the preparation work done by nsfwjs (these first 5-6 seconds) maybe be split up in 2 parts, and then do half the job - onLoad, and then the second part - which is triggered to happen when an image actually is selected by the user?

nodejs execution

Hello! Is possibile to use with nodejs in a backend environment? Because i have seen only client-side javascript example.

Thank you

Add hovercard call to action

People finding fals positives can actually help this project pretty easily. Help them help the project with a hovercard.

Buffer support [assistance]

Hello, I need to fetch images and pass them to .classify().
The images i'll be fetching have .png format.

const tf = require('@tensorflow/tfjs-node');
const fetch = require("node-fetch");
const nsfw = require('nsfwjs');
const model = await nsfw.load();
let r = await fetch(IMAGE)
let buffer = await r.buffer();
const readImage = tf.node.decodeImage(buffer)
const predictions = await model.classify(readImage)
return predictions

I used https://js.tensorflow.org/api_node/1.7.0/#node.decodePng
Because it's stated that // Image must be in tf.tensor3d format.

readImage does return:

Tensor {
  kept: false,
  isDisposedInternal: false,
  shape: [ 128, 128, 4 ],
  dtype: 'int32',
  size: 65536,
  strides: [ 512, 4 ],
  dataId: {},
  id: 4402,
  rankType: '3',
  scopeId: 2430
}

but model.classify(readImage) returns:
Error: Size(200704) must match the product of shape 1,224,224,3

What am I doing wrong?

Add simple tests

Currently, this is a simple node module so manual testing is easy but add some basic tests anyway.

Using s3 bucket works but when I switch to local model I get an error

Error: Error when checking : expected input_1 to have shape [null,299,299,3] but got array with shape [1,224,224,3].
    at new t (tf-layers.esm.js?271e:17)
    at checkInputData (tf-layers.esm.js?271e:17)
    at t.predict (tf-layers.esm.js?271e:17)
    at eval (index.js?9368:92)
    at eval (tf-core.esm.js?45ef:17)
    at t.scopedRun (tf-core.esm.js?45ef:17)
    at t.tidy (tf-core.esm.js?45ef:17)
    at Module.je (tf-core.esm.js?45ef:17)
    at NSFWJS.eval (index.js?9368:91)
    at step (index.js?9368:33)
<template>
  <div>
    <img ref="img" src="@/assets/img.jpg">
  </div>
</template>
<script>
import * as nsfwjs from "nsfwjs";

export default {
  async mounted () {
    // const model = await nsfwjs.load();
    // "/static/model/" is mapped as "/model/" using Nuxt.js
    const model = await nsfwjs.load("/model/");
    const predictions = await model.classify(this.$refs.img);
    console.log("Predictions: ", predictions);
  }
};
</script>

Fix deprecation warnings

loadModel seems to be deprecated, use the latest TF functions and get everything legit for futureproofing.

Bias in model

There seems to be a bias of when an image contains a woman with any skin showing, the model will mark those as porn, even when they clearly aren't.

There's some examples in this twitter post, but I could reproduce it with different images too.

Using without third-party server?

Is there any way to use this offline aka do not use from your S3 server? Maybe there is a way to download the existing trained data on your server which can be used at offline.

Why? It could be complicated due DSGVO and the less there are third party servers, the less complicated it gets. ๐Ÿ˜„ or am I missing here?

Some new ideas

  1. Able to detect what regions are NSFW within the image
  2. Able to detect video, GIF, APNG and WebM.

Load the retrained model

I assume you were trying to classify on node?

Have you looked at how to convert a PNG to a tensor? https://stackoverflow.com/questions/53231699/converting-png-to-tensor-tensorflow-js


@GantMan Thank you very much for your reply, this issue has been resolved.

I am now experiencing another problem. I trained a batch of images with nsfw_model / train_all_model.sh (using https://tfhub.dev/google/imagenet/mobilenet_v2_140_224/classification/4) and then I used tensorflowjs- The converter converted from keras or keras_saved_model to tfjs_layer_model and succeeded. But when I reference the model in nsfwjs-node, I get an error message:

2020-04-02 15:45:40,085 ERROR 70582 nodejs.unhandledRejectionError: Unknown layer: KerasLayer. This may be due to one of the following reasons:
1. The layer is defined in Python, in which case it needs to be ported to TensorFlow.js or your JavaScript code.
2. The custom layer is defined in JavaScript, but is not registered properly with tf.serialization.registerClass().
1. The layer is defined in Python, in which case it needs to be ported to TensorFlow.js or your JavaScript code.
2. The custom layer is defined in JavaScript, but is not registered properly with tf.serialization.registerClass().
    at new ValueError (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/errors.js:68:28)
    at Object.deserializeKerasObject (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/utils/generic_utils.js:260:19)
    at Object.deserialize (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/layers/serialization.js:29:28)
    at Sequential.fromConfig (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/models.js:958:41)
    at Object.deserializeKerasObject (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/utils/generic_utils.js:294:29)
    at Object.deserialize (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/layers/serialization.js:29:28)
    at /Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/models.js:290:45
    at step (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/models.js:54:23)
    at Object.next (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/models.js:35:53)
    at fulfilled (/Users/wuguofeng/www/nodejs/classify/node_modules/nsfwjs-node/node_modules/@tensorflow/tfjs-layers/dist/models.js:26:58)
name: "unhandledRejectionError"
pid: 70582
hostname: bogon

How should I train the models that nsfwjs-node can use?
Looking forward to your reply, thank you again!

Originally posted by @wunamesst in #274 (comment)

Training on Submitted Images

IDK if this is already taking place but maybe you could use images submitted to help train the Neural Network?
Also maybe there could also be a people category.

error TS2348

any idea?

C:\Users\Jae Jin\Desktop\HUB\nsfwjs>yarn prep
yarn run v1.15.2
$ yarn && yarn build && cd example/nsfw_demo/ && yarn add ../../ && cd -
[1/4] Resolving packages...
success Already up-to-date.
$ tsc --skipLibCheck
src/index.ts:103:47 - error TS2348: Value of type 'typeof Model' is not callable. Did you mean to include 'new'?

103           this.intermediateModels[endpoint] = tf.Model({
                                                  ~~~~~~~~~~
104             inputs: this.model.inputs,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105             outputs: layer.output
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106           })
    ~~~~~~~~~~~~


Found 1 error.

sliding frame

I'd love to be able to add support for a sliding frame. I know I could do this outside the library, by cropping the image multiple times, or potentially at the buffer level. My gut says the performance would be significantly improved if I pushed it down into tensorflow though (is that possible? Is https://js.tensorflow.org/api/latest/#signal.frame the right way to do it?).

I'm willing to put some leg-work in--but I'd really appreciate some guidance or if anyone has resources describing how to do it with a tensorflow.js implementation.

Pre-trained model link is dead

When downloading the model through the s3 at https://s3.amazonaws.com/ir_public/nsfwjscdn/TFJS_nsfw_mobilenet/tfjs_quant_nsfw_mobilenet/

The following error code is thrown:

<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>
nsfwjscdn/TFJS_nsfw_mobilenet/tfjs_quant_nsfw_mobilenet/
</Key>
<RequestId>8ECD5C58025A96EC</RequestId>
<HostId>
0wNKLqrKG2SyXYZ4d//i3otFu2uOq+OE7xEQkACROa/HRY/+vfIINBlAqG3oYATZbUVxtFoz44A=
</HostId>
</Error>

Invalid mode.json file

To host model on our own server in readme.md you've provided link to https://github.com/infinitered/nsfwjs/tree/master/example/nsfw_demo/public/model

I was trying to host these on my server and was facing issues but working absolutely fine with the default files then figured out that model.json from demo folder is different from the one you're using as default here https://s3.amazonaws.com/ir_public/nsfwjscdn/TFJS_nsfw_mobilenet/tfjs_quant_nsfw_mobilenet/model.json

happy to send pull request, if you can confirm that is the issue.

Build with webpack

Hello,

Has anyone succeeded building NSFW.js with Webpack, that would be able to provide me with a working config?

Unfortunately, when building I get some warnings, which I'm not sure whether I can fix or not (no errors I get), but then, when I run "node index.min.js", I get a huge output which is a partial minified JS, and then the following error:

*/var n=Object.getOwnPropertySymbols,i=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},r=0;r<10;r++)t["_"+String.fromCharCode(r)]=r;if("0123456789"!==Object.getOwnPropertyNames(t)
(there's a lot more code, but I truncated it for this issue)

Error: package.json does not exist at F:\package.json
at Object.t.find (F:\path\to\proj\build\index.min.js:169:11682)
at Object. (F:\path\to\proj\build\index.min.js:472:426)
at Object. (F:\path\to\proj\build\index.min.js:472:916)
at r (F:\path\to\proj\build\index.min.js:1:110)
at Object. (F:\path\to\proj\build\index.min.js:289:44677)
at r (F:\path\to\proj\build\index.min.js:1:110)
at F:\path\to\proj\build\index.min.js:1:902
at Object. (F:\path\to\proj\build\index.min.js:1:913)
at Module._compile (internal/modules/cjs/loader.js:1151:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1171:10)

I can't understand why a production build is looking for "package.json" in the root of the F:\ drive.

My webpack config:

module.exports = [
	{
		name: 'server',
		context: __dirname,
		entry: './index.js',
		target: 'node',
		mode: 'production',
		output: {
			path: path.resolve(__dirname, 'build'),
			filename: 'index.min.js',
		},
		module: {
			rules : [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				use: ['babel-loader'],
			},
			]
		},
		resolve: {
			modules: [
				path.join(__dirname, "node_modules"),
			]
		},
		node: {
			fs: 'empty', // Module not found: Error: Can't resolve 'fs'
			child_process: 'empty', // Module not found: Error: Can't resolve 'child_process'
		},
		plugins: [],
	}
];

Example - classifyGif

classifyGif was added in #57

Add code to demo app that will properly prompt user to wait while gif is being processed, and then show the user the output in a meaningful way. I'm thinking graph, possibly with D3.

React Native Support

How hard will be to use or port this to React Native? Right now, the content analyzed is based on a DOM node. But maybe there's a way to pass an image/video URL or a base64 to analyze?

Pre-trained model for Keras?

We're looking to try the model with Keras in Python. The problem is that the current pre-trained model is in the tfjs_graph_model format and there doesn't seem to be a way to convert it for Keras. Is there a chance for releasing a Keras version?

video support

Hi! Are you planning to release video support?
thanks

How to classify video?

Hello. I have a video uploader.
I want to classify more than first video frame. Is it possible?

Thanks.

Crash on Mobile Safari

When taking a picture to check on iOS 12.1.3, the webpage crashes.

Loading from the camera roll works fine.

Add CI

There are tests. Let's add CI for verification on PRs

How to classify PNG?

Hello, I tried to classify a png image in nodejs, but it throws an exception: Size (357604) must match the product of 1,299,299,3 shapes.
How can this be resolved?

Blocked ui

I found ui been blocked for few seconds when execute โ€nsfwjs.load('/path/to/model/directory/') โ€œ. How to optimize it?

Memory Leaking

Hey, every image that I classify it, the more memory consumes it.
Is there any way to reduce it like deleting cache or something? It's really weird.

Memory issues

I'm noticing some serious memory issues when using NSFWJS with tfjs-node. The memory footprint increases over time. Here's some code to test and see what I mean:

./lib/nsfwjs-inputs.js

const tf = require('@tensorflow/tfjs-node')
const fs = require('fs')
const jpeg = require('jpeg-js')
const fetch = require('node-fetch')

const readImageFile = path => {
	return new Promise((resolve, reject) => {
		fs.readFile(path, (err, buf) => {
			if (err) return reject(err)
			const pixels = jpeg.decode(buf, true)
			resolve(pixels)
		})
	})
}

const readImageUrl = async url => {
	let res = await fetch(url)

	let buf = await res.arrayBuffer()

	const pixels = jpeg.decode(buf, true)

	return pixels
}

const imageByteArray = (image, numChannels = 3) => {
	const pixels = image.data
	const numPixels = image.width * image.height
	const values = new Int32Array(numPixels * numChannels)

	for (let i = 0; i < numPixels; i++) {
		for (let channel = 0; channel < numChannels; ++channel) {
			values[i * numChannels + channel] = pixels[i * 4 + channel]
		}
	}

	return values
}

const imageToInput = (image, numChannels = 3) => {
	const values = imageByteArray(image, numChannels)
	const outShape = [image.height, image.width, numChannels]
	const input = tf.tensor3d(values, outShape, 'int32')

	return input
}

const inputFromFile = async (path, numChannels = 3) => {
	const image = await readImageFile(path)
	const input = imageToInput(image, numChannels)

	return input
}

const inputFromUrl = async (url, numChannels = 3) => {
	const image = await readImageUrl(url)
	const input = imageToInput(image, numChannels)

	return input
}

module.exports = {
	inputFromFile,
	inputFromUrl,
}

./nsfwjs-resource-test.js

process.title = 'NSFWJS Resource Test'

const fs = require('fs')
const nsfwjs = require('nsfwjs')
const nsfwjsInputs = require('./lib/nsfwjs-inputs.js')
const pathJoin = require('path').join

const IMG_DIR = pathJoin(__dirname, 'test-imgs')

try {
	fs.accessSync(IMG_DIR)
} catch (err) {
	fs.mkdirSync(IMG_DIR)
}

async function main() {
	let nsfw = await nsfwjs.load('file://./nsfwjs_model/')

	let files = fs.readdirSync(IMG_DIR)

	let outputFile = fs.createWriteStream('./analysis.txt')

	let counter = 0

	for (let file of files) {
		const filepath = pathJoin(IMG_DIR, file)

		let input = await nsfwjsInputs.inputFromFile(filepath)

		let predictions = await nsfw.classify(input)
		let predictionMap = predictions.reduce(
			(map, prediction) => ({
				...map,
				[prediction.className]: prediction.probability,
			}),
			{}
		)

		outputFile.write(`${file} = ${JSON.stringify(predictionMap)}\n`, 'utf8')

		console.log(++counter)
	}
}

main().catch(err => console.error(err) && process.exit(1))

You'll need to have images in a ./test-imgs directory ready for this test. After only 100 images, I see the "NSFWJS Resource Test" process at 1 GB of memory. I'm noticing 5 GB at only 500 images processed. The longer the program runs, the more memory is consumed.

This leads me to believe there is a memory leak somewhere. Either it's in the nsfwjs-inputs.js file, tensorflow, or NSWFJ.

Where is the javascript code to put on the web-server?

About the nsfwjs we can read the following:
"A simple JavaScript library to help you quickly identify unseemly images; all in the client's browser."

So, where is the actual javascript that we can upload to our web-server, and then use on the client side, to "identify unseemly images"?
It would be nice if that particular javascript was easily accessible from this github page. That way it would be a lot quicker to implement in various web applications.

I have tested the demo page, which is to be found here:
https://nsfwjs.com/
Have tested it with several images which contain e.g. various sexy and porn content. It works like expected. So far so good. But the javascript code used on that demo page, is not usable in my web-application.

So where is the actual javascript code that I can implement in my web-application?
Does this module require node.js to work?
What did I miss?

Support TensorflowJS 1.x

Currently we are using Tensorflow 0.15.x, but we should support latest tensorflow.

Update and fix to work with latest.

tensorflow .pb model wanted

I have found some nsfw's trained model or Demo, but yours perform best.
Could you upload the trained .pb model to help me develop my java Demo?
Thanks a lot.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.