Перевод статьи Node.js + face-recognition.js: Simple and Robust Face Recognition using Deep Learning.
В этой статье мы расскажем, как реализовать надёжную систему распознавания лиц с использованием face-recognition.js. Мы искали подходящую Node.js-библиотеку, которая умела бы аккуратно распознавать лица, но ничего не нашли. Пришлось писать самостоятельно!
В этом npm-пакете используется библиотека dlib, предоставляющая Node.js-биндинги для очень хорошо зарекомендовавших себя инструментов распознавания внутри этой библиотеки. Dlib использует методы глубокого обучения и поставляется с уже обученными моделями, которые продемонстрировали точность распознавания на уровне 99,38% при прогоне бенчмарка LFW.
npm install
).const path = require('path')
const fs = require('fs')
const fr = require('face-recognition')
const dataPath = path.resolve('./data/faces')
const classNames = ['sheldon', 'lennard', 'raj', 'howard', 'stuart']
const allFiles = fs.readdirSync(dataPath)
const imagesByClass = classNames.map(c =>
allFiles
.filter(f => f.includes(c))
.map(f => path.join(dataPath, f))
.map(fp => fr.loadImage(fp))
)
const numTrainingFaces = 10
const trainDataByClass = imagesByClass.map(imgs => imgs.slice(0, numTrainingFaces))
const testDataByClass = imagesByClass.map(imgs => imgs.slice(numTrainingFaces))
['sheldon', 'lennard', 'raj', 'howard', 'stuart']
fr.loadImage(fp)
вы можете считать изображение, указанное в пути к файлу.const image = fr.loadImage('image.png')
const detector = fr.FaceDetector()
const targetSize = 150
const faceImages = detector.detectFaces(image, targetSize)
faceImages.forEach((img, i) => fr.saveImage(img, `face_${i}.png`))
const recognizer = fr.FaceRecognizer()
trainDataByClass.forEach((faces, label) => {
const name = classNames[label]
recognizer.addFaces(faces, name)
})
numJitters
, вы можете применять вращение, масштабирование и зеркалирование, создавая разные версии каждого из входных лиц. Увеличение количества модификаций может повысить точность распознавания, но при этом нейросеть учится дольше.const modelState = recognizer.serialize()
fs.writeFileSync('model.json', JSON.stringify(modelState))
const modelState = require('model.json')
recognizer.load(modelState)
const errors = classNames.map(_ => [])
testDataByClass.forEach((faces, label) => {
const name = classNames[label]
console.log()
console.log('testing %s', name)
faces.forEach((face, i) => {
const prediction = recognizer.predictBest(face)
console.log('%s (%s)', prediction.className, prediction.distance)
// count number of wrong classifications
if (prediction.className !== name) {
errors[label] = errors[label] + 1
}
})
})
// print the result
const result = classNames.map((className, label) => {
const numTestFaces = testDataByClass[label].length
const numCorrect = numTestFaces - errors[label].length
const accuracy = parseInt((numCorrect / numTestFaces) * 10000) / 100
return `${className} ( ${accuracy}% ) : ${numCorrect} of ${numTestFaces} faces have been recognized correctly`
})
console.log('result:')
console.log(result)
predictBest
мы получим результат с наименьшим евклидовым расстоянием, то есть с наибольшей похожестью. Примерно так:{ className: 'sheldon', distance: 0.5 }
recognizer.predict(image)
, который для каждого класса выдаст массивы расстояний:[
{ className: 'sheldon', distance: 0.5 },
{ className: 'raj', distance: 0.8 },
{ className: 'howard', distance: 0.7 },
{ className: 'lennard', distance: 0.69 },
{ className: 'stuart', distance: 0.75 }
]
sheldon ( 90.9% ) : 10 of 11 faces have been recognized correctly
lennard ( 100% ) : 12 of 12 faces have been recognized correctly
raj ( 100% ) : 12 of 12 faces have been recognized correctly
howard ( 100% ) : 12 of 12 faces have been recognized correctly
stuart ( 100% ) : 3 of 3 faces have been recognized correctly
sheldon ( 100% ) : 16 of 16 faces have been recognized correctly
lennard ( 88.23% ) : 15 of 17 faces have been recognized correctly
raj ( 100% ) : 17 of 17 faces have been recognized correctly
howard ( 100% ) : 17 of 17 faces have been recognized correctly
stuart ( 87.5% ) : 7 of 8 faces have been recognized correctly
К сожалению, не доступен сервер mySQL