1. 程式人生 > 其它 >【教程】OpenCV—Node.js教程系列:Node.js+OpenCV面部臉識別

【教程】OpenCV—Node.js教程系列:Node.js+OpenCV面部臉識別

最近我將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任務。