require("@tensorflow/tfjs-node"); const fs= require ('fs'); const express = require("express"); const moment = require("moment"); // 配置 cors 这个中间件 const cors = require('cors') // const faceapi = require("face-api.js"); const faceapi = require('@vladmandic/face-api'); const mongoose = require("mongoose"); const canvas = require("canvas"); const { Canvas, Image } = require("canvas"); const fileUpload = require("express-fileupload"); const multer = require('multer') console.log('----') faceapi.env.monkeyPatch({ Canvas, Image }); const app = express(); // 设置存放格式 const storage = multer.diskStorage({ destination(req, file, cb) { cb(null, './uploads') }, filename(req, file, cb) { cb(null, Date.now() + '-' + file.originalname) } }) // 加载文件存储 const upload = multer({ storage }) // app.use( // fileUpload({ // useTempFiles: true, // }) // ); app.use(cors()) app.use(express.static('./dist')) app.use('/uploads', express.static('./uploads')); async function LoadModels() { await faceapi.nets.faceRecognitionNet.loadFromDisk(__dirname + "/models"); await faceapi.nets.faceLandmark68Net.loadFromDisk(__dirname + "/models"); await faceapi.nets.ssdMobilenetv1.loadFromDisk(__dirname + "/models"); } LoadModels(); const faceSchema = new mongoose.Schema({ label: { type: String, required: true, unique: true, }, images:{ type:Array, required:true }, descriptions: { type: Array, required: true, }, }); const FaceModel = mongoose.model("Face", faceSchema); /** * * @param {图片} images * @param {图片标记:张三} label * @returns */ async function uploadLabeledImages(images, label) { try { let counter = 0; const descriptions = []; const imgs=[] // 循环图片 for (let i = 0; i < images.length; i++) { const img = await canvas.loadImage(images[i]); counter = (i / images.length) * 100; console.log(`Progress = ${counter}%`); // Read each face and save the face descriptions in the descriptions array const detections = await faceapi.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor(); descriptions.push(detections.descriptor); imgs.push(images[i]) } //用给定的标签创建一个新的面文档,并将其保存在数据库中 const createFace = new FaceModel({ label: label, descriptions: descriptions, images:imgs }); try{ await createFace.save(); console.log('人脸录入成功!') return true }catch(error){ return error; } } catch (error) { console.log(error); return (error); } } /** * 清空 人脸库 * @param {人物标记} label * @returns */ async function deleteLabelImages(label) { try{ await FaceModel.deleteMany({ label: label }) return true }catch(error){ return error } } /** * 清空 人脸库 * @param {人物标记} label * @returns */ async function selectLabelImages(label) { try{ await FaceModel.findOne({ label: label }) return true }catch(error){ return error } } async function getDescriptorsFromDB(image) { // 从mongodb获取所有的面部数据,并循环遍历每个面部数据以读取数据 let faces = await FaceModel.find(); for (i = 0; i < faces.length; i++) { // 将面数据描述符从obiects更改为Float32Array类型 for (j = 0; j < faces[i].descriptions.length; j++) { faces[i].descriptions[j] = new Float32Array(Object.values(faces[i].descriptions[j])); } // 将DB面文档改为 faces[i] = new faceapi.LabeledFaceDescriptors(faces[i].label, faces[i].descriptions); } // 加载面匹配器以查找匹配面 const faceMatcher = new faceapi.FaceMatcher(faces, 0.45); // 使用画布或其他方法读取图像 const img = await canvas.loadImage(image); let temp = faceapi.createCanvasFromMedia(img); // 处理模型的图像 const displaySize = { width: img.width, height: img.height }; faceapi.matchDimensions(temp, displaySize); const currentTime = moment().format("YYYY-MM-DD HH:mm:ss"); // 查找匹配的人脸 const detections = await faceapi.detectAllFaces(img).withFaceLandmarks().withFaceDescriptors(); const currentTime2 = moment().format("YYYY-MM-DD HH:mm:ss"); const resizedDetections = faceapi.resizeResults(detections, displaySize); const results = resizedDetections.map((d) => faceMatcher.findBestMatch(d.descriptor)); return results; } /** * 上传人脸信息 */ app.post("/post-face",upload.array('files',6),async (req,res)=>{ let imgs=[] for (let i = 0; i < req.files.length; i++) { imgs.push(req.files[i].path) } let label = req.body.label let result = await uploadLabeledImages(imgs, label); console.log(result) if(result===true){ res.json({code:200, message:"录入成功"}) }else{ res.json({code:400, message:"人脸模型录入失败,请重新录入"}) } }) /**验证人脸对比 */ app.post("/check-face",upload.single('file'), async (req, res) => { console.log(req.file) const File1 = req.file.path; let result = await getDescriptorsFromDB(File1); fs.unlink(File1,(err)=>{ if(err){ console.log('删除失败') }else{ console.log('删除成功') } }) res.json({code:200,result }); }); // 获取人脸模型 app.post('/get-face',upload.single('file'),async (req, res) => { console.log('------------') console.log(req.body) const label = req.body.label const result=await FaceModel.findOne({ "label": label }) res.json({code:200,result}) }) // 清除人脸模型 app.post("/del-face",upload.single('file'),async(req,res)=>{ console.log('------------') console.log(req.body) const label = req.body.label console.log('删除人脸库',label) let result= deleteLabelImages(label) if(result){ res.json({message:'success'}) }else{ res.json({message:"err"}) } }) app.post("/test",async(req,res)=>{ console.log('---测试--------') res.json({message:"err"}) }) // add your mongo key instead of the *** mongoose .connect( `mongodb://localhost/test`, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, } ) .then(() => { app.listen(process.env.PORT || 5000); console.log("DB connected and server us running."); }) .catch((err) => { console.log(err); });