UNPKG

ai-face-detection

Version:

This is simple face detection using face-api.js and tensorflow.js

103 lines 11.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.faceDetect = void 0; const fs_1 = __importDefault(require("fs")); const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); const canvas_1 = __importStar(require("canvas")); const faceapi = __importStar(require("@vladmandic/face-api")); const crypto_1 = require("crypto"); const logger_1 = __importDefault(require("./helpers/logger")); const processDetection_1 = require("./processDetection"); const axios_1 = __importDefault(require("axios")); const modelPathRoot = path_1.default.resolve(__dirname + '../../../weights'); const minConfidence = 0.15; const maxResults = 5; async function faceDetect(imagePath) { const inFile = await processInput(imagePath); faceapi.env.monkeyPatch({ Canvas: canvas_1.default.Canvas, Image: canvas_1.default.Image, ImageData: canvas_1.default.ImageData, }); // @ts-expect-error await faceapi.tf.setBackend('tensorflow'); // @ts-expect-error await faceapi.tf.enableProdMode(); // @ts-expect-error await faceapi.tf.ready(); faceapi.tf.ENV.set('DEBUG', false); logger_1.default.info( // @ts-expect-error `Version: TensorFlow/JS ${faceapi.tf?.version_core} FaceAPI ${faceapi.version // @ts-expect-error } Backend: ${faceapi.tf?.getBackend()}`); logger_1.default.info('Loading FaceAPI models'); const modelPath = modelPathRoot; await faceapi.nets.ssdMobilenetv1.loadFromDisk(modelPath); await faceapi.nets.ageGenderNet.loadFromDisk(modelPath); await faceapi.nets.faceLandmark68Net.loadFromDisk(modelPath); await faceapi.nets.faceRecognitionNet.loadFromDisk(modelPath); await faceapi.nets.faceExpressionNet.loadFromDisk(modelPath); const optionsSSDMobileNet = new faceapi.SsdMobilenetv1Options({ minConfidence, maxResults, }); const junkDir = path_1.default.resolve(path_1.default.join(__dirname, '../junk')); if (!fs_1.default.existsSync(junkDir)) { await promises_1.default.mkdir(junkDir); } const exitImage = path_1.default.resolve(path_1.default.join(junkDir, `./${(0, crypto_1.randomUUID)()}.jpg`)); const outFile = fs_1.default.createWriteStream(exitImage); const canvasImage = await (0, canvas_1.loadImage)(inFile, outFile); const result = await (0, processDetection_1.processDetection)(canvasImage, optionsSSDMobileNet); outFile.on('finish', () => { promises_1.default.unlink(path_1.default.resolve(exitImage)); }); outFile.close(); return result; } exports.faceDetect = faceDetect; const processInput = async (input) => { if (typeof input !== 'string' && !(input instanceof Buffer)) { throw new Error('Input type should be instance of Buffer or string'); } if (input instanceof Buffer) { return input; } // check if string is url if (input.startsWith('http')) { // read from url const response = await axios_1.default.get(input, { responseType: 'arraybuffer' }); return Buffer.from(response.data, 'binary'); } const inFile = await promises_1.default.readFile(input); return inFile; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjZURldGVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvZmFjZURldGVjdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDRDQUFtQjtBQUNuQiwyREFBb0M7QUFDcEMsZ0RBQXVCO0FBQ3ZCLGlEQUEwQztBQUMxQyw4REFBK0M7QUFDL0MsbUNBQW1DO0FBQ25DLDhEQUFxQztBQUNyQyx5REFBcUQ7QUFDckQsa0RBQXlCO0FBRXpCLE1BQU0sYUFBYSxHQUFHLGNBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxHQUFHLGtCQUFrQixDQUFDLENBQUE7QUFDbEUsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFBO0FBQzFCLE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQTtBQUViLEtBQUssVUFBVSxVQUFVLENBQUMsU0FBMEI7SUFDekQsTUFBTSxNQUFNLEdBQUcsTUFBTSxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFNUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUM7UUFDdEIsTUFBTSxFQUFFLGdCQUFNLENBQUMsTUFBTTtRQUNyQixLQUFLLEVBQUUsZ0JBQU0sQ0FBQyxLQUFLO1FBQ25CLFNBQVMsRUFBRSxnQkFBTSxDQUFDLFNBQVM7S0FDNUIsQ0FBQyxDQUFBO0lBRUYsbUJBQW1CO0lBQ25CLE1BQU0sT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDekMsbUJBQW1CO0lBQ25CLE1BQU0sT0FBTyxDQUFDLEVBQUUsQ0FBQyxjQUFjLEVBQUUsQ0FBQTtJQUNqQyxtQkFBbUI7SUFDbkIsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFBO0lBQ3hCLE9BQU8sQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFFbEMsZ0JBQU0sQ0FBQyxJQUFJ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O0lBQ0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxrQkFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUMvQyxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tICdmcydcbmltcG9ydCBmc1Byb21pc2VzIGZyb20gJ2ZzL3Byb21pc2VzJ1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcbmltcG9ydCBjYW52YXMsIHsgbG9hZEltYWdlIH0gZnJvbSAnY2FudmFzJ1xuaW1wb3J0ICogYXMgZmFjZWFwaSBmcm9tICdAdmxhZG1hbmRpYy9mYWNlLWFwaSdcbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nXG5pbXBvcnQgbG9nZ2VyIGZyb20gJy4vaGVscGVycy9sb2dnZXInXG5pbXBvcnQgeyBwcm9jZXNzRGV0ZWN0aW9uIH0gZnJvbSAnLi9wcm9jZXNzRGV0ZWN0aW9uJ1xuaW1wb3J0IGF4aW9zIGZyb20gJ2F4aW9zJ1xuXG5jb25zdCBtb2RlbFBhdGhSb290ID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSArICcuLi8uLi8uLi93ZWlnaHRzJylcbmNvbnN0IG1pbkNvbmZpZGVuY2UgPSAwLjE1XG5jb25zdCBtYXhSZXN1bHRzID0gNVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmFjZURldGVjdChpbWFnZVBhdGg6IHN0cmluZyB8IEJ1ZmZlcikge1xuICBjb25zdCBpbkZpbGUgPSBhd2FpdCBwcm9jZXNzSW5wdXQoaW1hZ2VQYXRoKVxuXG4gIGZhY2VhcGkuZW52Lm1vbmtleVBhdGNoKHtcbiAgICBDYW52YXM6IGNhbnZhcy5DYW52YXMsXG4gICAgSW1hZ2U6IGNhbnZhcy5JbWFnZSxcbiAgICBJbWFnZURhdGE6IGNhbnZhcy5JbWFnZURhdGEsXG4gIH0pXG5cbiAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICBhd2FpdCBmYWNlYXBpLnRmLnNldEJhY2tlbmQoJ3RlbnNvcmZsb3cnKVxuICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gIGF3YWl0IGZhY2VhcGkudGYuZW5hYmxlUHJvZE1vZGUoKVxuICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gIGF3YWl0IGZhY2VhcGkudGYucmVhZHkoKVxuICBmYWNlYXBpLnRmLkVOVi5zZXQoJ0RFQlVHJywgZmFsc2UpXG5cbiAgbG9nZ2VyLmluZm8oXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgIGBWZXJzaW9uOiBUZW5zb3JGbG93L0pTICR7ZmFjZWFwaS50Zj8udmVyc2lvbl9jb3JlfSBGYWNlQVBJICR7XG4gICAgICBmYWNlYXBpLnZlcnNpb25cbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICB9IEJhY2tlbmQ6ICR7ZmFjZWFwaS50Zj8uZ2V0QmFja2VuZCgpfWBcbiAgKVxuXG4gIGxvZ2dlci5pbmZvKCdMb2FkaW5nIEZhY2VBUEkgbW9kZWxzJylcbiAgY29uc3QgbW9kZWxQYXRoID0gbW9kZWxQYXRoUm9vdFxuICBhd2FpdCBmYWNlYXBpLm5ldHMuc3NkTW9iaWxlbmV0djEubG9hZEZyb21EaXNrKG1vZGVsUGF0aClcbiAgYXdhaXQgZmFjZWFwaS5uZXRzLmFnZUdlbmRlck5ldC5sb2FkRnJvbURpc2sobW9kZWxQYXRoKVxuICBhd2FpdCBmYWNlYXBpLm5ldHMuZmFjZUxhbmRtYXJrNjhOZXQubG9hZEZyb21EaXNrKG1vZGVsUGF0aClcbiAgYXdhaXQgZmFjZWFwaS5uZXRzLmZhY2VSZWNvZ25pdGlvbk5ldC5sb2FkRnJvbURpc2sobW9kZWxQYXRoKVxuICBhd2FpdCBmYWNlYXBpLm5ldHMuZmFjZUV4cHJlc3Npb25OZXQubG9hZEZyb21EaXNrKG1vZGVsUGF0aClcbiAgY29uc3Qgb3B0aW9uc1NTRE1vYmlsZU5ldCA9IG5ldyBmYWNlYXBpLlNzZE1vYmlsZW5ldHYxT3B0aW9ucyh7XG4gICAgbWluQ29uZmlkZW5jZSxcbiAgICBtYXhSZXN1bHRzLFxuICB9KVxuXG4gIGNvbnN0IGp1bmtEaXIgPSBwYXRoLnJlc29sdmUocGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2p1bmsnKSlcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGp1bmtEaXIpKSB7XG4gICAgYXdhaXQgZnNQcm9taXNlcy5ta2RpcihqdW5rRGlyKVxuICB9XG4gIGNvbnN0IGV4aXRJbWFnZSA9IHBhdGgucmVzb2x2ZShwYXRoLmpvaW4oanVua0RpciwgYC4vJHtyYW5kb21VVUlEKCl9LmpwZ2ApKVxuICBjb25zdCBvdXRGaWxlID0gZnMuY3JlYXRlV3JpdGVTdHJlYW0oZXhpdEltYWdlKVxuXG4gIGNvbnN0IGNhbnZhc0ltYWdlID0gYXdhaXQgbG9hZEltYWdlKGluRmlsZSwgb3V0RmlsZSlcbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcHJvY2Vzc0RldGVjdGlvbihjYW52YXNJbWFnZSwgb3B0aW9uc1NTRE1vYmlsZU5ldClcblxuICBvdXRGaWxlLm9uKCdmaW5pc2gnLCAoKSA9PiB7XG4gICAgZnNQcm9taXNlcy51bmxpbmsocGF0aC5yZXNvbHZlKGV4aXRJbWFnZSkpXG4gIH0pXG4gIG91dEZpbGUuY2xvc2UoKVxuXG4gIHJldHVybiByZXN1bHRcbn1cblxuY29uc3QgcHJvY2Vzc0lucHV0ID0gYXN5bmMgKGlucHV0OiBzdHJpbmcgfCBCdWZmZXIpOiBQcm9taXNlPEJ1ZmZlcj4gPT4ge1xuICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJyAmJiAhKGlucHV0IGluc3RhbmNlb2YgQnVmZmVyKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgdHlwZSBzaG91bGQgYmUgaW5zdGFuY2Ugb2YgQnVmZmVyIG9yIHN0cmluZycpXG4gIH1cbiAgaWYgKGlucHV0IGluc3RhbmNlb2YgQnVmZmVyKSB7XG4gICAgcmV0dXJuIGlucHV0XG4gIH1cbiAgLy8gY2hlY2sgaWYgc3RyaW5nIGlzIHVybFxuICBpZiAoaW5wdXQuc3RhcnRzV2l0aCgnaHR0cCcpKSB7XG4gICAgLy8gcmVhZCBmcm9tIHVybFxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXhpb3MuZ2V0KGlucHV0LCB7IHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJyB9KVxuICAgIHJldHVybiBCdWZmZXIuZnJvbShyZXNwb25zZS5kYXRhLCAnYmluYXJ5JylcbiAgfVxuICBjb25zdCBpbkZpbGUgPSBhd2FpdCBmc1Byb21pc2VzLnJlYWRGaWxlKGlucHV0KVxuICByZXR1cm4gaW5GaWxlXG59XG4iXX0=