File size: 5,072 Bytes
d007ed6 12b037e d007ed6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
// 导入experss模块
const express=require("express");
let fs = require('fs');
// 创建服务器对象
let app = express();
// 导入body-parser插件
const bodyparser = require("body-parser");;
// 配置body-parser模块
app.use(bodyparser.urlencoded({extended:false}));
app.use(bodyparser.json());
// 导入系统模块path
const path = require("path");
const afs = require('fs-extra');
let multiparty = require('multiparty');
let imgJS = require("image-js");
const nsfw = require('nsfwjs');
const tf = require('@tensorflow/tfjs-node');
const safeContent = ['Drawing', 'Neutral']; // 设置图片内容安全的类型
// https://github.com/alex000kim/nsfw_data_scraper
let imgTypeoObj = {
Drawing: '艺术性的',
Neutral: '中性的',
Sexy: '性感的',
Porn: '色情的',
Hentai: '变态的',
};
//转换图片格式
const convert = async file => {
const image = await imgJS.Image.load(file.path);
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');
};
// 初始化模型
let model;
(async function() {
model = await nsfw.load('file://./web_model/', {
type: 'graph'
});
})();
const isSafeContent = predictions => {
let safeProbability = 0;
let imgTypeValArr = [];
for (let index = 0; index < predictions.length; index++) {
const item = predictions[index];
const className = item.className;
const probability = item.probability;
if (safeContent.includes(className)) {
safeProbability += probability;
};
}
imgTypeValArr = predictions.sort((a, b) => b.probability - a.probability);
// console.log('imgTypeValArr:', imgTypeValArr);
let myimgType = '';
if (imgTypeValArr.length && imgTypeValArr[0]) {
myimgType = imgTypeoObj[imgTypeValArr[0].className];
}
return {
isSafe: safeProbability > 0.5,
imgType: myimgType
};
};
app.post('/checkImg',async (req, res) => {
try {
// 删除指定文件夹下面的所有文件或文件夹
try {
await afs.emptyDirSync('./tempImgs');
console.log('清空tempImgs成功');
} catch (error) {
console.log('清空tempImgs失败');
}
let form = new multiparty.Form();
// 设置文件存储路径,以当前编辑的文件为相对路径
form.uploadDir = './tempImgs';
form.parse(req, async (err, fields, files) => {
if (!files || !files.file[0]) {
return res.send({
code: -1,
msg: '请上传file图片资源(form-data格式)',
data: {}
})
}
// console.log('files.file[0]:', files.file[0]);
// 图片最大尺寸
if (files.file[0].size > 1024 * 1024 * 3) {
return res.send({
code: -2,
msg: '被检测图片最大3M',
data: {}
})
};
// 支持的图片类型
let imgReg = /\S+\.(png|jpeg|jpg)$/g;
let originImgName = files.file[0].originalFilename || files.file[0].path;
if (!imgReg.test(originImgName)) {
return res.send({
code: -3,
msg: '仅仅支持(png、jpeg、jpg)类型图片检测',
data: {}
})
}
let img = await convert(files.file[0]);
let predictions = await model.classify(img);
const {isSafe, imgType} = isSafeContent(predictions);
// console.log('是否安全:', predictions, isSafe);
res.send({
code: 0,
msg: isSafe ? '图片合规' : '图片可能存在不合规的风险,请核查',
data: {
isSafe,
imgType,
predictions,
}
})
});
} catch (error) {
res.send({
code: -9,
msg: '图片核查失败,请重试',
data: {}
})
}
});
// {
// "code": 0,
// "msg": "图片合规",
// "data": {
// "isSafe": true,
// "imgType": "艺术性的",
// "predictions": [
// {
// "className": "Drawing",
// "probability": 0.9533441662788391
// },
// {
// "className": "Neutral",
// "probability": 0.015517046675086021
// },
// {
// "className": "Sexy",
// "probability": 0.013940851204097271
// },
// {
// "className": "Porn",
// "probability": 0.012532410211861134
// },
// {
// "className": "Hentai",
// "probability": 0.004665587563067675
// }
// ]
// }
// }
// 监听端口
app.listen(7860,()=>{
console.log("图片鉴黄服务器启动成功!port:7860");
}); |