首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【教程】OpenCV—Node.js教程系列:Node.js+OpenCV面部脸识别

【教程】OpenCV—Node.js教程系列:Node.js+OpenCV面部脸识别

作者头像
AiTechYun
发布2018-03-06 10:39:46
4.1K0
发布2018-03-06 10:39:46
举报
文章被收录于专栏:ATYUN订阅号ATYUN订阅号

最近我将OpenCV普通发布版本设计的面部识别算法添加到了opencv4nodejs,它是一个npm包,允许你在Node.js应用程序中使用OpenCV。今天,我们将看一下在OpenCVs的面部模块中实现的Fisher -、Eigen -和LBPH facerecognizer,并构建一个简单的Node.js面部识别的例子。在我的github repo上可以找到示例的源代码。我们不要再浪费时间了,开始吧!

  • OpenCV普通发布版本地址:https://docs.opencv.org/3.1.0/d3/d81/tutorial_contrib_root.html
  • opencv4nodejs地址:https://github.com/justadudewhohacks/opencv4nodejs
  • OpenCVs面部模块中的实现地址:https://docs.opencv.org/2.4/modules/contrib/doc/facerec/facerec_tutorial.html
  • github repo地址:https://github.com/justadudewhohacks/opencv4nodejs/tree/master/examples

1 .工作准备图像数据

在我们对识别器进行训练之前,必须收集一些面部图像数据。如果你像我一样对行尸走肉(美国电视剧)感到兴奋,那么你很可能对我们的测试对象很熟悉。我收集了Daryl,Rick和邪恶少年Negan的图像,每人4张,总共12张。

简单地从网络中选取一些图像,我们必须提取以每个图像中显示的字符为中心的子图像。因此,我们将使用OpenCV的CascadeClassifier类来检测人物的面部:

const classifier = new cv.CascadeClassifier(cv.HAAR_FRONTALFACE_ALT2);
const getFaceImage = (grayImg) => {
  const faceRects = classifier.detectMultiScale(grayImg).objects;
  if (!faceRects.length) {
    throw new Error('failed to detect faces');
  }
  return grayImg.getRegion(faceRects[0]);
};

CascadeClassifier可以用于目标检测,它是从一个包含训练模型表示的xml文件中创建的。OpenCV为不同的使用案例提供了一些预先训练的模型,如面部检测、人眼检测、全身检测等。为了检测到面部,我们将使用HAAR_FRONTALFACE_ALT2模型。给定一个灰度图像,detectMultiScale将返回图像中潜在面部的边界矩形。我们可以简单地获取第一个最佳检测结果,并返回矩形覆盖的子图像。

图像上标上daryl <n >,rick <n >,negan <n >,n从1 – 4。我们将阅读这些图片并将它们分成一组训练和测试样本如下:

const basePath = '../data/face-recognition';
const imgsPath = path.resolve(basePath, 'imgs');
const nameMappings = ['daryl', 'rick', 'negan'];

const imgFiles = fs.readdirSync(imgsPath);

const images = imgFiles
  // get absolute file path
  .map(file => path.resolve(imgsPath, file))
  // read image
  .map(filePath => cv.imread(filePath))
  // face recognizer works with gray scale images
  .map(img => img.bgrToGray())
  // detect and extract face
  .map(getFaceImage)
  // face images must be equally sized
  .map(faceImg => faceImg.resize(80, 80));

const isImageFour = (_, i) => imgFiles[i].includes('4');
const isNotImageFour = (_, i) => !isImageFour(_, i);
// use images 1 - 3 for training
const trainImages = images.filter(isNotImageFour);
// use images 4 for testing
const testImages = images.filter(isImageFour);
// make labels
const labels = imgFiles
  .filter(isNotImageFour)
  .map(file => nameMappings.findIndex(name => file.includes(name)));

将给出以下图像:

调整图像的大小是必要的,因为识别器希望图像的大小相等。我们将使用每个角色的前3张图像进行训练,第4张用来测试识别器(第19 – 24行)。最后,我们必须标记数据(第26 – 28行)。为了训练识别器,我们需要给它提供一个图像数组(训练图像)和一个将相应标签保存为数字(标签)的数组。数据应该是这样的:

训练图像:

[Rick1, Rick2, Rick3, Daryl1, Daryl2, Daryl3, Negan1, Negan2, Negan3]

标签:

[0, 0, 0, 1, 1, 1, 2, 2, 2]

2.训练识别器

现在我们已经准备好了数据,我们将初始化识别器并对它们进行训练:

const eigen = new cv.EigenFaceRecognizer();
const fisher = new cv.FisherFaceRecognizer();
const lbph = new cv.LBPHFaceRecognizer();
eigen.train(trainImages, labels);
fisher.train(trainImages, labels);
lbph.train(trainImages, labels);

还可以将一些参数传递给识别器的构造函数来对它们进行微调,但为了简单起见,我们将使用默认设置。从逻辑上讲,训练方法期望训练图像标签数组的长度相同,标签数组必须包含至少2个不同的标签。

3.识别面部

就是这样!我们现在可以运行我们测试图像的预测:

const runPrediction = (recognizer) => {
  testImages.forEach((img) => {
    const result = recognizer.predict(img);
    console.log('predicted: %s, confidence: %s', nameMappings[result.label], result.confidence);
    cv.imshowWait('face', img);
    cv.destroyAllWindows();
  });
};

console.log('eigen:');
runPrediction(eigen);

console.log('fisher:');
runPrediction(fisher);

console.log('lbph:');
runPrediction(lbph);

运行这个示例应该给出如下输出:

eigen:
predicted daryl to be: daryl, confidence: 1245.68
predicted negan to be: negan, confidence: 2247.25
predicted rick to be: negan, confidence: 2502.47
fisher:
predicted daryl to be: daryl, confidence: 452.15
predicted negan to be: negan, confidence: 464.76
predicted rick to be: rick, confidence: 831.38
lbph:
predicted daryl to be: daryl, confidence: 108.37
predicted negan to be: negan, confidence: 119.33
predicted rick to be: rick, confidence: 105.65

每个类(角色)仅使用3个图像,我们就可以得到很好的结果。Opencv4nodejs是一个npm包,将 Node.js绑定到OpenCV,并且OpenCV普通发布版通过异步API设计。该包将本机OpenCV库的所有性能优势都带到 Node.js应用程序,允许通过Promise轻松实现多线程的CV任务。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ATYUN订阅号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 .工作准备图像数据
  • 2.训练识别器
  • 3.识别面部
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档