'use strict' let os = require("os"); let isWindows = os.platform().startsWith("win"); let path = require("path"); // import nodejs bindings to native tensorflow, // not required, but will speed up things drastically (python required) let process = require("process"); process.env.TF_CPP_MIN_LOG_LEVEL=2 const shell = require("shelljs") if(!isWindows){ // 仅在Linux下启动内存加速和GPU加速 let nvidiaSmi = shell.exec("nvidia-smi",{silent:true}) if(nvidiaSmi?.stdout.indexOf("CUDA")>-1){ console.log("facetf gpu mode") require('@tensorflow/tfjs-node-gpu'); }else{ console.log("facetf cpu mode") require('@tensorflow/tfjs-node'); } } // implements nodejs wrappers for HTMLCanvasElement, HTMLImageElement, ImageData let canvas = require('canvas'); // import * as faceapi from 'face-api.js'; let faceapi = require('@vladmandic/face-api/dist/face-api.node.js'); const baseDir = path.resolve(__dirname, './tmp') // 设置识别参数 // mokey pathing the faceapi canvas const { Canvas, Image, ImageData } = canvas faceapi.env.monkeyPatch({ Canvas, Image, ImageData }) const faceDetectionNet = faceapi.nets.ssdMobilenetv1 // SsdMobilenetv1Options const minConfidence = 0.5 // TinyFaceDetectorOptions const inputSize = 408 const scoreThreshold = 0.5 // MtcnnOptions const minFaceSize = 50 const scaleFactor = 0.8 const faceDetectionOptions = getFaceDetectorOptions(faceDetectionNet) var FACE_TFJS_WEIGHTS_LOADED = false; async function loadModel(){ // load weights 首次调用加载模型 if(!FACE_TFJS_WEIGHTS_LOADED){ await faceDetectionNet.loadFromDisk(path.join(__dirname,'./model')) await faceapi.nets.faceLandmark68Net.loadFromDisk(path.join(__dirname,'./model')) await faceapi.nets.faceRecognitionNet.loadFromDisk(path.join(__dirname,'./model')) FACE_TFJS_WEIGHTS_LOADED = true } } loadModel() class FacetfSDK{ constructor(){ } async getPhotoFeat68(photoUrl){ let detections = await this.detectFaceWithLandmarksAndDescriptor(photoUrl); if(detections?.length>0){ let feat68 = Array.from(detections[0]?.descriptor); return feat68 } return null } async setReportFeat68(report){ if(report?.className && !report?.get("feat68")){ let detections = await this.detectFaceWithLandmarksAndDescriptor(report.get("photo")); if(detections?.length>0){ let feat68 = Array.from(detections[0]?.descriptor); report.set("feat68",feat68) } } await report.save(); return report } async detectFaceWithLandmarksAndDescriptor(img1){ await loadModel(); let referenceImage try{ referenceImage = await canvas.loadImage(img1) }catch(err){ throw "图片地址有误无法加载" } if(!(referenceImage)){ throw "图片不够清晰请重新上传" } let detections = await faceapi.detectAllFaces(referenceImage, faceDetectionOptions) .withFaceLandmarks() .withFaceDescriptors() if(!detections){ throw "图片不够清晰请重新上传" } if(detections.length==0){ // openapi.goWrong(response,"照片未上传或不清晰,请重新上传"); let imgstr = "" if(detections.length==0){ imgstr += "<1>" } throw `图${imgstr}无法识别人脸` } // 获取特征向量 68关键点 以及128特征向量 return detections } } function getFaceDetectorOptions(net) { return net === faceapi.nets.ssdMobilenetv1 ? new faceapi.SsdMobilenetv1Options({ minConfidence }) : (net === faceapi.nets.tinyFaceDetector ? new faceapi.TinyFaceDetectorOptions({ inputSize, scoreThreshold }) : new faceapi.MtcnnOptions({ minFaceSize, scaleFactor }) ) } module.exports.FacetfSDK = FacetfSDK