소개
안녕하세요,이 기사를 통해 Node.js, Express, MongoDB 및 face-api.js로 얼굴 인식 API를 만드는 방법을 보여 드리겠습니다. 이것들은 주요 패키지이지만 나중에 기사에서 보여줄 패키지도 더 필요합니다.
작동 방식을 보여 드리기 위해 코드를 작성하겠습니다.이 API의 주요 목적은 얼굴 데이터를 데이터베이스에 지속적으로 저장하여 서버가 다운 되더라도 데이터를 데이터베이스에 저장하는 것입니다.
따라서 모든 이미지를 사용하여 모델을 다시 훈련 할 필요가 없습니다. 시작하기 전에 다음 주제를 이해했는지 확인하십시오.
express
mongoose
express-fileupload
face-api.js
canvas
const express = require("express");
const faceapi = require("face-api.js");
const mongoose = require("mongoose");
const { Canvas, Image } = require("canvas");
const canvas = require("canvas");
const fileUpload = require("express-fileupload");
faceapi.env.monkeyPatch({ Canvas, Image });
const app = express();
app.use(
fileUpload({useTempFiles: true})
);
// add your mongo key instead of the ***
mongoose.connect(
`***`,
{
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);
});
async function LoadModels() {
// Load the models
// __dirname gives the root directory of the server
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,
},
descriptions: {
type: Array,
required: true,
},
});
const FaceModel = mongoose.model("Face", faceSchema);
async function uploadLabeledImages(images, label) {
try {
const descriptions = [];
// Loop through the images
for (let i = 0; i < images.length; i++) {
const img = await canvas.loadImage(images[i]);
// Read each face and save the face descriptions in the descriptions array
const detections = await faceapi.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor();
descriptions.push(detections.descriptor);
}
// Create a new face document with the given label and save it in DB
const createFace = new FaceModel({
label: label,
descriptions: descriptions,
});
await createFace.save();
return true;
} catch (error) {
console.log(error);
return (error);
}
}
이 함수의 입력으로 이미지와 레이블을 가져옵니다. 그런 다음 함수를 try-catch로 래핑하여 프로세스에 오류가 있어도 앱이 충돌하지 않도록 합니다. 그 후 데이터베이스에 업로드하기 전에 모든 설명을 저장하는 배열을 정의하고 각 이미지를 통해 canvas.loadImage() 함수로 이미지를 읽습니다. 그런 다음 이미지 데이터를 face-api 메서드에 전달하고 얼굴 특징을 감지합니다. 그런 다음 설명은 기능에서 추출되어 설명 배열로 푸시됩니다. 따라서 모든 이미지 기능이 추출 된 후 스키마에 따라 데이터베이스에 데이터를 저장하고 작업이 완료되면 true를 반환합니다.
메인 메서드가 준비되었으므로 이제 경로를 시작할 수 있습니다. 다음은 경로에 대한 코드입니다.
app.post("/post-face",async (req,res)=>{
const File1 = req.files.File1.tempFilePath
const File2 = req.files.File2.tempFilePath
const File3 = req.files.File3.tempFilePath
const label = req.body.label
let result = await uploadLabeledImages([File1, File2, File3], label);
if(result){
res.json({message:"Face data stored successfully"})
}else{
res.json({message:"Something went wrong, please try again."})
}
})
경로는 매우 간단합니다. 파일과 레이블을 받은 다음 앞에서 정의한 함수에 전달합니다. 그런 다음 저장 여부에 따라 사용자에게 응답을 보냅니다.
req.files는 앞서 언급 한 express-fileupload 패키지를 사용하는 경우에만 작동합니다. 그렇지 않으면 다른 방법을 사용하여 이미지를 업로드 해야 합니다. 또한 이 예에서는 얼굴 이미지를 3 개만 업로드하는 것을 보여 주었지만 정확도를 높이려면 더 많이 사용할 수 있습니다. *
/face-check 경로 및 얼굴 인식
async function getDescriptorsFromDB(image) {
// Get all the face data from mongodb and loop through each of them to read the data
let faces = await FaceModel.find();
for (i = 0; i < faces.length; i++) {
// Change the face data descriptors from Objects to Float32Array type
for (j = 0; j < faces[i].descriptions.length; j++) {
faces[i].descriptions[j] = new Float32Array(Object.values(faces[i].descriptions[j]));
}
// Turn the DB face docs to
faces[i] = new faceapi.LabeledFaceDescriptors(faces[i].label, faces[i].descriptions);
}
// Load face matcher to find the matching face
const faceMatcher = new faceapi.FaceMatcher(faces, 0.6);
// Read the image using canvas or other method
const img = await canvas.loadImage(image);
let temp = faceapi.createCanvasFromMedia(img);
// Process the image for the model
const displaySize = { width: img.width, height: img.height };
faceapi.matchDimensions(temp, displaySize);
// Find matching faces
const detections = await faceapi.detectAllFaces(img).withFaceLandmarks().withFaceDescriptors();
const resizedDetections = faceapi.resizeResults(detections, displaySize);
const results = resizedDetections.map((d) => faceMatcher.findBestMatch(d.descriptor));
return results;
}
이 부분은 매우 중요하며 매우 조심해야 합니다. 먼저 데이터베이스에서 모든 얼굴 데이터를 가져옵니다. 그러나 우리가 얻는 데이터는 배열의 객체 일뿐입니다. 모델이 각 이미지에 대한 설명을 읽으려면 LabeledFaceDescriptors 객체 여야 합니다.
그러나 그렇게 하려면 설명을 Float32Array로 전달해야 합니다. 따라서 각 얼굴 데이터에 대해 객체 인 각 설명을 반복합니다. 이러한 Object 유형을 Array로 바꾼 다음 Float32Array로 바꿉니다. 그런 다음 facematcher를 시작하고 인식을 수행하기 위해 함수에 전달 된 이미지를 읽습니다. Face API 문서를 기반으로 처리 및 감지 기능을 실행하고 결과를 반환합니다.
이제 얼굴을 확인할 경로를 정의 할 수 있습니다. 다음은 경로입니다.
app.post("/check-face", async (req, res) => {
const File1 = req.files.File1.tempFilePath;
let result = await getDescriptorsFromDB(File1);
res.json({ result });
});
경로에서 이미지를 전달하고 getDescriptorsFromDB 함수가 얼굴 인식을 수행하고 결과를 반환 할 때까지 기다립니다.
Testing
API를 사용할 준비가 되었습니다. 이제 Postman으로 테스트 해 보겠습니다. Postman은 API를 무료로 테스트 할 수 있는 훌륭한 도구입니다. 여기에서 다운로드 할 수 있습니다.
먼저 이렇게 라벨이 붙은 같은 사람의 이미지 3 장을 업로드했습니다.
뾰족한 세부 사항에 주의하십시오. 코드가 일치하지 않으면 서버에서 오류로 응답합니다. 일이 잘되면 이런 응답을 받아야 합니다.
데이터베이스에는 업로드 된 각 얼굴에 대해 다음과 같은 문서가 있어야 합니다.
이제 테스트 이미지를 업로드하고 API가 얼굴을 인식 할 수 있는지 확인할 수 있습니다.
내가 얻는 결과는 이것입니다.
기사가 너무 길면 죄송 합니다만 이것이 제 첫 기사였습니다. 콘텐츠를 즐기 셨기를 바랍니다. 이것이 도움이 되었다면 내 github에 별표를 남기고 이 블로그를 다른 사람들과 공유하십시오. 이 코드에 문제가 있는 경우 트위터 @ Zulkarn30860075에서 저에게 연락 할 수 있습니다.
https://blog.mdzulkarnine.com/building-face-recognition-api-with-nodejs-expressjs-mongodb-face-apijs
등록된 댓글이 없습니다.