const faceapi = require('face-api.js');
const canvas = require('canvas');
const {
Canvas,
Image,
ImageData
} = canvas;
faceapi.env.monkeyPatch({
Canvas,
Image,
ImageData
});
const MySqlDb = require('./../MysqlDb.js');
const fs = require('fs');
const path = require('path');
const FileHandler = require('./FileHandler.js');
const fileHandler = new FileHandler();
const mysqlDb = new MySqlDb();
class FaceRecognition {
constructor() {
this.faceMatcher = null;
//tf.enableProdMode();
}
async loadModel() {
await faceapi.nets.ssdMobilenetv1.loadFromDisk('models');
await faceapi.nets.faceLandmark68Net.loadFromDisk('models');
await faceapi.nets.faceRecognitionNet.loadFromDisk('models');
}
async isDetectFace(imagePath) {
await this.loadModel();
const img = await canvas.loadImage(imagePath);
const detections = await faceapi.detectAllFaces(img)
.withFaceLandmarks()
.withFaceDescriptors()
return detections.length > 0;
}
async detectFaces(imagePath) {
await this.loadModel();
const img = await canvas.loadImage(imagePath);
// Detect faces in the image
const detections = await faceapi.detectAllFaces(img)
.withFaceLandmarks()
.withFaceDescriptors()
const croppedFaces = [];
// Crop and save the face images
detections.forEach(detection => {
const box = detection.detection.box;
const face = faceapi.createCanvasFromMedia(img).getContext('2d');
// Adjust the face region to include some padding
const padding = 20;
const startX = Math.max(0, box.x - padding);
const startY = Math.max(0, box.y - padding);
const width = Math.min(img.width - startX, box.width + padding * 2);
const height = Math.min(img.height - startY, box.height + padding * 2);
// Crop the face region from the original image
face.canvas.width = width;
face.canvas.height = height;
face.drawImage(img, startX, startY, width, height, 0, 0, width, height);
// Convert the cropped face image to a data URL
const croppedFaceImage = face.canvas.toDataURL();
croppedFaces.push(croppedFaceImage);
});
return croppedFaces;
}
async generateFaceDescriptor(imagePath) {
await this.loadModel();
const img = await canvas.loadImage(imagePath);
// Detect faces in the image
const detections = await faceapi.detectAllFaces(img)
.withFaceLandmarks()
.withFaceDescriptors();
const faceDescriptors = detections.map(detection => ({
descriptor: detection.descriptor,
label: 'Label for the detected face' // Provide a label for the face descriptor
}));
return faceDescriptors;
}
async findMatchingDescriptionDb(imagePath) {
const faceDescriptors = await this.generateFaceDescriptor(imagePath);
if (faceDescriptors.length === 0) {
return [{
matched: false,
matchedImgpath: null,
contact: null,
similarityScore: null,
message: `The faces do not match.`
}];
}
const distanceThreshold = 0.48; // Define a threshold value to determine if the faces are a match
const folderPath = 'C:/Users/mehfatitem/Downloads/yuzler'; // Provide the folder path where the face images are stored
const result = [];
await new Promise((resolve, reject) => {
mysqlDb.runQuery(`SELECT * FROM facedescriptions ORDER BY id`, async (err, results) => {
if (err) {
console.log('Error executing query:', err);
reject(err);
} else {
for (const item in results) {
const description = results[item]['description'];
const contact = results[item]['contact'];
const imgPath = path.join(folderPath, `${contact}.png`);
const desc = Object.values(JSON.parse(description));
const distance = faceapi.euclideanDistance(faceDescriptors[0].descriptor, desc);
const similarityScore = 1 - distance; // Calculate the similarity score
if (similarityScore > distanceThreshold) {
const similarityPercentage = Math.round(similarityScore * 100);
const matchedImg = 'data:image/png;base64,' + await fileHandler.imageToBase64(imgPath);
result.push({
matched: true,
matchedImgpath: matchedImg,
contact: contact,
similarityScore: similarityPercentage,
message: `The faces are a match. Similarity Score: ${similarityPercentage}%`
});
} else {
result.push({
matched: false,
matchedImgpath: null,
contact: null,
similarityScore: null,
message: `The faces do not match.`
});
}
}
resolve();
}
});
});
return result;
}
async findMatchingDescription(imagePath, folderPath) {
const faceDescriptors = await this.generateFaceDescriptor(imagePath);
if (faceDescriptors.length == 0)
return [{
matched: false,
matchedImgpath: null,
contact: null,
similarityScore: null,
message: `The faces are not match.`
}];
const distanceThreshold = 0.48; // Define a threshold value to determine if the faces are a match
const fileNames = fs.readdirSync(folderPath);
let paths = 'C:/Users/mehfatitem/Downloads/yuzler';
let result = [];
for (const fileName of fileNames) {
const filePath = path.join(folderPath, fileName);
const description = fs.readFileSync(filePath, 'utf8');
const desc = Object.values(JSON.parse(description));
const distance = faceapi.euclideanDistance(faceDescriptors[0].descriptor, desc);
const similarityScore = 1 - distance; // Calculate the similarity score
if (similarityScore > distanceThreshold) {
const similarityPercentage = Math.round(similarityScore * 100);
const matchedImgpath = `data:image/png;base64,${fileHandler.imageToBase64(path.join(paths, fileName.replace('.txt', '.png')))}`
result.push({
matched: true,
matchedImgpath: matchedImgpath,
contact: fileName.replace('.txt', ''),
similarityScore: similarityPercentage,
message: `The faces are a match. Similarity Score: ${similarityPercentage}%`
});
} else {
result.push({
matched: false,
matchedImgpath: null,
contact: null,
similarityScore: null,
message: `The faces are not match.`
});
}
}
return result;
}
async compareImages(imagePath1, imagePath2) {
const faceDescriptors1 = await this.generateFaceDescriptor(imagePath1);
const faceDescriptors2 = await this.generateFaceDescriptor(imagePath2);
const distanceThreshold = 0.6; // Define a threshold value to determine if the faces are a match
let contact = path.parse(imagePath2).name; // Move the contact variable outside the loop
// Compare each face descriptor from imagePath1 with each face descriptor from imagePath2
for (const faceDescriptor1 of faceDescriptors1) {
for (const faceDescriptor2 of faceDescriptors2) {
const distance = faceapi.euclideanDistance(faceDescriptor1.descriptor, faceDescriptor2.descriptor);
const similarityScore = 1 - distance; // Calculate the similarity score
if (similarityScore > distanceThreshold) {
const similarityPercentage = Math.round(similarityScore * 100);
return {
matched: true,
matchedImgpath: `data:image/png;base64,${fileHandler.imageToBase64(imagePath2)}`,
contact: contact,
similarityScore: similarityPercentage,
message: `${imagePath2} The faces are a match. Similarity Score: ${similarityPercentage}%`
};
} else {
return {
matched: false,
matchedImgpath: null,
contact: null,
similarityScore: null,
message: null
};
}
}
}
}
async processImagesInFolder(folderPath, outputFolder) {
await this.loadModel();
const fileNames = fs.readdirSync(folderPath);
for (const fileName of fileNames) {
const imagePath = path.join(folderPath, fileName);
const faceDescriptors = await this.generateFaceDescriptor(imagePath);
for (const faceDescriptor of faceDescriptors) {
const faceLabel = faceDescriptor.label;
const faceOutputPath = path.join(outputFolder, `${path.parse(fileName).name}.txt`);
const faceDescriptorText = JSON.stringify(faceDescriptor.descriptor);
fs.writeFileSync(faceOutputPath, faceDescriptorText);
}
}
}
async processImagesInFolderToDB(folderPath) {
await this.loadModel();
const fileNames = fs.readdirSync(folderPath);
for (const fileName of fileNames) {
const imagePath = path.join(folderPath, fileName);
const faceDescriptors = await this.generateFaceDescriptor(imagePath);
console.dir(faceDescriptors);
const contact = path.parse(fileName).name
for (const faceDescriptor of faceDescriptors) {
const faceDescriptorText = JSON.stringify(faceDescriptor.descriptor);
const currentUnixTime = Math.floor(new Date().getTime() / 1000);
mysqlDb.runQuery(`Insert into facedescriptions (description, contact, operationtime) values('${faceDescriptorText}' , '${contact}' , ${currentUnixTime} )`, (err, results) => {
if (err) {
console.log('Error executing query:', err);
res.status(500).send('Error occurred inserting detected face');
return;
} else {
console.log(`Face description eklendi ${contact}`);
}
});
}
}
}
}
module.exports = FaceRecognition;
This is my face recognition class. I want to make some face matching and face searching with using face-api library in nodeJs. But the output says me like that
"Hi there . Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA)
at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details." but I couldn't install tensorflow tfs gpu. I wait for your helps.
I make some efforts , but it didn't lead me on any right way.