infinitered / nsfwjs

NSFW detection on the client-side via TensorFlow.js
https://nsfwjs.com/
MIT License
7.89k stars 524 forks source link

Demo predictions and Node JS App predictions are not the same result #563

Open mronline opened 2 years ago

mronline commented 2 years ago

nsfwjs.com (load model: inceptionv3: ['/model/', { size: 299 }]) image result:

Identified as Porn
Porn - 48.19%
Neutral - 40.21%
Sexy - 10.87%
Hentai - 0.61%
Drawing - 0.12%

NodeJS app (load model: inceptionv3: ['/model/', { size: 299 }]) same image result:

[
    {
        "className": "Neutral",
        "probability": 0.6607071757316589
    },
    {
        "className": "Sexy",
        "probability": 0.18770809471607208
    },
    {
        "className": "Porn",
        "probability": 0.14371605217456818
    },
    {
        "className": "Hentai",
        "probability": 0.004498853348195553
    },
    {
        "className": "Drawing",
        "probability": 0.0033697152975946665
    }
]

My Code:

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, 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('https://nsfwjs.com/model/', {size: 299})
}

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

I tried the model files locally, same result.

GantMan commented 2 years ago

Have you tried tfjs-node to decode the images?

Just for info. Which one of the two was correct? I assume the website was correct, and the node was wrong?

GantMan commented 2 years ago

https://github.com/infinitered/nsfwjs/discussions/540