客户端不雅内容检查
这是一个简单的JavaScript库,可以帮助您在客户端浏览器中快速识别不雅图像。NSFWJS并不完美,但它相当准确(小型模型约90%,中型模型约93%的准确率)...而且它正在变得越来越准确。
为什么这会有用?查看公告博文。
注意
如果您尝试访问Cloudfront托管的模型并遇到错误,很可能是因为模型已被移动到新位置。请查看我们的自行托管模型部分。在处理一些热链接问题后,我们将恢复模型的访问。
目录
该库将图像概率分为以下5个类别:
Drawing
- 适合工作场合的绘画(包括动漫)Hentai
- 色情动漫和色情绘画Neutral
- 适合工作场合的中性图像Porn
- 色情图像,性行为Sexy
- 性感露骨的图像,非色情
演示是持续部署源 - 试一试:http://nsfwjs.com
快速:如何使用该模块
支持async/await
:
import * as nsfwjs from "nsfwjs";
const img = document.getElementById("img");
// 如果您想自行托管模型或使用不同于可用模型的模型,请参阅"自行托管模型"部分。
const model = await nsfwjs.load();
// 对图像进行分类
const predictions = await model.classify(img);
console.log("预测结果:", predictions);
不支持async/await
:
import * as nsfwjs from "nsfwjs";
const img = document.getElementById("img");
// 如果您想自行托管模型或使用不同于可用模型的模型,请参阅"自行托管模型"部分。
nsfwjs
.load()
.then(function (model) {
// 对图像进行分类
return model.classify(img);
})
.then(function (predictions) {
console.log("预测结果:", predictions);
});
库API
加载
模型
在分类任何图像之前,您需要加载模型。
const model = nsfwjs.load(); // 默认:"MobileNetV2"
您可以使用可选的第一个参数来指定要使用的模型,从三个捆绑在一起的模型中选择。默认为:"MobileNetV2"
。这支持在Webpack等支持的打包工具上进行树摇优化,因此您只会加载您正在使用的模型。
const model = nsfwjs.load("MobileNetV2Mid"); // "MobileNetV2" | "MobileNetV2Mid" | "InceptionV3"
您还可以使用相同的参数从您的网站/服务器加载模型,如自行托管模型部分所解释的那样。这样做可以将加载模型的包大小减少约1.33倍(33%),因为您可以直接使用二进制文件而不是与包一起捆绑的base64。例如,捆绑到包中的"MobileNetV2"
模型为3.5MB,而托管的二进制文件为2.6MB。这只会在客户端浏览器上每次加载模型时(不使用缓存)产生差异,因为在服务器端,您只会在服务器启动时加载一次模型。
MobileNetV2模型 - 224x224
const model = nsfwjs.load("/path/to/model/directory/");
如果您使用的模型需要224x224以外的图像尺寸,您可以在选项参数中传递大小。
MobileNetV2Mid模型 - 299x299
const model = nsfwjs.load("/path/to/model/", { size: 299 });
/* 您可能需要使用图形类型加载此模型 */
const model = nsfwjs.load("/path/to/model/", { type: 'graph' });
如果您使用的是图形模型,则无法使用推断方法,并且需要在选项中告诉模型加载您正在处理的是图形模型。
InceptionV3模型 - 图形
const model = nsfwjs.load("/path/to/different/model/", { type: "graph" });
缓存
如果您在浏览器中使用,并希望随后从IndexedDB或本地存储加载(注意:模型大小可能太大,无法存储在本地存储中!),您可以使用适当的方案保存底层模型,并从那里加载。
const initialLoad = await nsfwjs.load(
"/path/to/different/model/" /*, { ...options }*/
);
await initialLoad.model.save("indexeddb://exampleModel");
const model = await nsfwjs.load("indexeddb://exampleModel" /*, { ...options }*/);
参数
初始加载:
- 包含
model.json
的文件夹的URL或路径。 - 可选对象,包含您的模型期望的大小或类型属性。
后续加载:
- IndexedDB路径。
- 可选对象,包含您的模型期望的大小或类型属性。
返回值
- 准备使用的NSFWJS模型对象
故障排除
- 在加载模型的标签页上,检查元素并导航到"应用程序"标签。在左侧窗格的"存储"部分下,有一个名为"IndexedDB"的子部分。在这里您可以查看模型是否正在保存。
分类
图像
此函数可以接受任何基于浏览器的图像元素(<img>
、<video>
、<canvas>
),并返回最可能的预测及其置信度水平的数组。
// 返回前3个猜测(而不是所有5个)
const predictions = await model.classify(img, 3);
参数
- 张量、图像数据、图像元素、视频元素或画布元素进行检查
- 要返回的结果数量(默认为所有5个)
返回值
- 包含
className
和probability
的对象数组。数组大小由classify
函数的第二个参数决定。
生产环境
Tensorflow.js提供了两个标志,enableProdMode
和enableDebugMode
。如果您要在生产环境中使用NSFWJS,请确保在加载NSFWJS模型之前启用生产模式。
import * as tf from "@tensorflow/tfjs";
import * as nsfwjs from "nsfwjs";
tf.enableProdMode();
//...
let model = await nsfwjs.load(`${urlToNSFWJSModel}`);
注意: 在转移到生产环境之前,请考虑下载并自行托管模型,如自行托管模型部分所述。这可能会改善模型的初始加载时间。此外,如果您在浏览器中使用,请考虑缓存模型。
安装
NSFWJS以TensorFlow.js作为对等依赖。如果您的项目尚未包含TFJS,您需要添加它。
# 对等依赖
$ yarn add @tensorflow/tfjs
# 安装NSFWJS
$ yarn add nsfwjs
对于脚本标签,请包含所有捆绑包,如此处所示。然后简单地访问nsfwjs全局变量。这要求您已经导入了TensorFlow.js。
自行托管模型
NSFWJS的魔力来自NSFW检测模型。默认情况下,模型已被打包到这个包中。但你可能想在自己的服务器上托管模型,以通过加载原始二进制文件来减少包大小,或者托管你自己的自定义模型。如果你想托管自己版本的模型文件,可以按照以下步骤操作。然后你可以在load
函数中传递托管文件的相对URL,必要时还可以传递options
。
以下是如何在网站上安装默认模型:
- 通过下载zip文件或克隆
git clone https://github.com/infinitered/nsfwjs.git
来下载项目。如果下载zip文件不起作用,请使用克隆。 - 从项目根目录提取
models
文件夹,并将其放入网络应用程序的public
目录中,以便与你的网站一起作为静态文件提供服务。(你可以将其托管在任何地方,比如S3存储桶,只要你可以通过URL访问它即可)。 - 获取URL并将其放入
nsfwjs.load()
中。例如:nsfwjs.load(https://yourwebsite.com/models/mobilenet_v2/model.json)
。
运行示例
浏览器中的Tensorflow.js
为https://nsfwjs.com/提供支持的演示可在`examples/nsfw_demo`文件夹中找到。
要运行演示,请执行yarn prep
,这将把最新代码复制到演示中。完成后,你可以cd
进入演示文件夹并使用yarn start
运行。
Browserify
使用纯promises和脚本标签的browserify版本可在minimal_demo
文件夹中找到。
<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>
你应该将nsfwjs.min.js
文件和所有你想使用的模型包托管在你的项目旁边,并在脚本标签中使用src
属性引用它们。
React Native
加载模型的本地副本以减少网络负载,并利用TFJS-React-Native。博客文章
Node JS应用
使用NPM,你也可以在服务器端使用该模型。
$ npm install nsfwjs
$ npm install @tensorflow/tfjs-node
const axios = require("axios"); //你可以使用任何http客户端
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(); // 加载本地模型,nsfw.load('file://./path/to/model/')
// 图像必须是tf.tensor3d格式
// 你可以使用tf.node.decodeImage(Uint8Array,channels)将图像转换为tf.tensor3d
const image = await tf.node.decodeImage(pic.data, 3);
const predictions = await model.classify(image);
image.dispose(); // 必须显式管理Tensor内存(让tf.Tensor超出作用域不足以释放其内存)。
console.log(predictions);
}
fn();
这里是另一个使用Express的multipart/form-data POST的完整示例,假设你使用的是JPG格式。
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) => {
// UInt8字节数组中解码的图像
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("缺少图像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();
};
// 将模型保存在内存中,确保它只加载一次
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'
你还可以使用lovell/sharp
进行预处理任务和处理更多文件格式。
NSFW过滤器
NSFW过滤器是一个使用NSFWJS从浏览器中过滤掉NSFW图像的网络扩展。
它目前可用于Chrome和Firefox,完全开源。
在这里查看该项目。
学习TensorFlow.js
通过我的O'Reilly书籍"Learning TensorFlow.js"学习如何编写像NSFWJS这样的库,可在O'Reilly和亚马逊上购买。
更多!
提供了一个FAQ页面。
更多关于NSFWJS和TensorFlow.js的信息 - https://youtu.be/uzQwmZwy3yw
该模型在Keras中经过几天的训练,使用了60多GB的数据。请务必查看模型代码,该模型使用Alexander Kim的nsfw_data_scraper提供的数据进行训练。
开源
NSFWJS作为开源软件,现在和将来都是免费使用的:heart:。它采用MIT许可,我们将始终尽最大努力提供帮助并快速解决问题。如果你想联系我们,请加入我们的社区slack。
需要专家?为你的下一个项目聘请Infinite Red
如果你的项目需要React Native方面的专家,Infinite Red随时为你提供帮助!我们经验丰富的软件工程师团队曾与微软、Zoom和Mercari等公司合作,成功实现了一些最复杂的项目。
无论是运行整个项目还是培训团队使用React Native,我们都可以帮助你解决公司最棘手的工程挑战 – 同时让这个过程成为一次美好的体验。 准备好看看我们如何合作了吗?给我们发送消息
贡献者
感谢这些优秀的人(表情符号说明):
本项目遵循all-contributors规范。欢迎各种形式的贡献!