JavaCV人臉識別三部曲之二:訓練

語言: CN / TW / HK

一起養成寫作習慣!這是我參與「掘金日新計劃 · 4 月更文挑戰」的第5天,點選檢視活動詳情

歡迎訪問我的GitHub

這裡分類和彙總了欣宸的全部原創(含配套原始碼):http://github.com/zq2599/blog_demos

本篇概覽

  • 本文是《JavaCV人臉識別三部曲》的第二篇,前文《視訊中的人臉儲存為圖片》咱們藉助攝像頭為兩位群眾演員生成大量人臉照片,如下圖,群眾演員A的照片儲存在E:\temp\202112\18\001\man,B的照片儲存在E:\temp\202112\18\001\woman在這裡插入圖片描述
  • 照片準備好,並且每張照片的身份都已確定,本篇要做的就是用上述照片生成模型檔案,今後新的人臉就可以中這個模型來檢查了
  • 關於訓練,可以用下圖來表示,一共六張照片兩個類別,訓練完成後得到模型檔案faceRecognizer.xml在這裡插入圖片描述

編碼

  • 訓練的程式碼很簡單,在一個java檔案中搞定吧,simple-grab-push是整個《JavaCV的攝像頭實戰》系列一直再用的工程,現在該工程中新增檔案TrainFromDirectory.java,完整程式碼如下,有幾處要注意的地方稍後提到: ```java public class TrainFromDirectory {

    /* * 從指定目錄下 * @param dirs * @param outputPath * @throws IOException / private void train(String[] dirs, String outputPath) throws IOException { int totalImageNums = 0;

    // 統計每個路徑下的照片數,加在一起就是照片總數
    for(String dir : dirs) {
        List<String> files = getAllFilePath(dir);
        totalImageNums += files.size();
    }
    
    System.out.println("total : " + totalImageNums);
    
    // 這裡用來儲存每一張照片的序號,和照片的Mat物件
    MatVector imageIndexMatMap = new MatVector(totalImageNums);
    
    Mat lables = new Mat(totalImageNums, 1, CV_32SC1);
    
    // 這裡用來儲存每一張照片的序號,和照片的類別
    IntBuffer lablesBuf = lables.createBuffer();
    
    // 類別序號,從1開始,dirs中的每個目錄就是一個類別
    int kindIndex = 1;
    
    // 照片序號,從0開始
    int imageIndex = 0;
    
    // 每個目錄下的照片都遍歷
    for(String dir : dirs) {
        // 得到當前目錄下所有照片的絕對路徑
        List<String> files = getAllFilePath(dir);
    
        // 處理一個目錄下的每張照片,它們的序號不同,類別相同
        for(String file : files) {
            // imageIndexMatMap放的是照片的序號和Mat物件
            imageIndexMatMap.put(imageIndex, read(file));
            // bablesBuf放的是照片序號和類別
            lablesBuf.put(imageIndex, kindIndex);
            // 照片序號加一
            imageIndex++;
        }
    
        // 每當遍歷完一個目錄,才會將類別加一
        kindIndex++;
    }
    
    // 例項化人臉識別類
    FaceRecognizer faceRecognizer = FisherFaceRecognizer.create();
    // 訓練,入參就是圖片集合和分類集合
    faceRecognizer.train(imageIndexMatMap, lables);
    // 訓練完成後,模型儲存在指定位置
    faceRecognizer.save(outputPath);
    //釋放資源
    faceRecognizer.close();
    

    }

    /* * 讀取指定圖片的灰度圖,調整為指定大小 * @param path * @return / private static Mat read(String path) { Mat faceMat = opencv_imgcodecs.imread(path,IMREAD_GRAYSCALE); resize(faceMat, faceMat, new Size(Constants.RESIZE_WIDTH, Constants.RESIZE_HEIGHT)); return faceMat; }

    /* * 把指定路徑下所有檔案的絕對路徑放入list集合中返回 * @param path * @return / public static List getAllFilePath(String path) { List paths = new LinkedList<>();

    File file = new File(path);
    
    if (file.exists()) {
        // 列出該目錄下的所有檔案
        File[] files = file.listFiles();
    
        for (File f : files) {
            if (!f.isDirectory()) {
                // 把每個檔案的絕對路徑都放在list中
                paths.add(f.getAbsolutePath());
            }
        }
    }
    
    return paths;
    

    }

    public static void main(String[] args) throws IOException {

    String base = "E:\\temp\\202112\\18\\001\\";
    
    // 儲存圖片的兩個目錄
    // man目錄下儲存了群眾演員A的所有人臉照片,
    // woman目錄下儲存了群眾演員B的所有人臉照片
    String[] dirs = {base + "man", base + "woman"};
    
    // 開始訓練,並指定模型輸出位置
    new TrainFromDirectory().train(dirs, base + "faceRecognizer.xml");
    

    } } ``` - 上述程式碼有以下幾處要注意: 1. 靜態方法read用於將圖片轉為Mat 2. 靜態方法getAllFilePath可以遍歷指定目錄下的所有檔案,把它們的絕對路徑返回 3. train一共獲取了man和woman兩個目錄下的照片,man目錄下的照片的類別是1,women目錄下的照片類別是2 4. 識別類是FisherFaceRecognizer,現在的訓練和下一篇的識別都用這個類

執行

  • 執行main方法,待執行完成後,如下圖,可見目錄E:\temp\202112\18\001下已經生成模型檔案faceRecognizer.xml在這裡插入圖片描述
  • 至此,本篇任務已完成,下一篇進入終極實戰,用本篇訓練的模型識別攝像頭中的人臉,並把識別結果展示在預覽頁面上;

原始碼下載

  • 《JavaCV的攝像頭實戰》的完整原始碼可在GitHub下載到,地址和連結資訊如下表所示(http://github.com/zq2599/blog_demos):

| 名稱 | 連結 | 備註| | :-------- | :----| :----| | 專案主頁| http://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 | | git倉庫地址(https)| http://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協議 | | git倉庫地址(ssh)| [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |

  • 這個git專案中有多個資料夾,本篇的原始碼在javacv-tutorials資料夾下,如下圖紅框所示: 在這裡插入圖片描述
  • javacv-tutorials裡面有多個子工程,《JavaCV的攝像頭實戰》系列的程式碼在simple-grab-push工程下: 在這裡插入圖片描述

歡迎關注掘金:程式設計師欣宸

學習路上,你不孤單,欣宸原創一路相伴...