JavaCV人臉識別三部曲之二:訓練
一起養成寫作習慣!這是我參與「掘金日新計劃 · 4 月更文挑戰」的第5天,點選檢視活動詳情。
歡迎訪問我的GitHub
這裡分類和彙總了欣宸的全部原創(含配套原始碼):https://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下載到,地址和連結資訊如下表所示(https://github.com/zq2599/blog_demos):
| 名稱 | 連結 | 備註| | :-------- | :----| :----| | 專案主頁| https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 | | git倉庫地址(https)| https://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工程下:
歡迎關注掘金:程式設計師欣宸
- 瀏覽器上寫程式碼,4核8G微軟伺服器免費用,Codespaces真香
- Java擴充套件Nginx之三:基礎配置項
- Java擴充套件Nginx之一:你好,nginx-clojure
- JavaCV的攝像頭實戰之十四:口罩檢測
- JavaCV人臉識別三部曲之二:訓練
- JavaCV人臉識別三部曲之一:視訊中的人臉儲存為圖片
- JavaCV的攝像頭實戰之八:人臉檢測
- 超詳細的編碼實戰,讓你的springboot應用識別圖片中的行人、汽車、狗子、喵星人(JavaCV YOLO4)
- Java應用日誌如何與Jaeger的trace關聯
- Spring Cloud Gateway實戰之五:內建filter
- Spring Cloud Gateway的斷路器(CircuitBreaker)功能
- Java版流媒體編解碼和影象處理(JavaCPP FFmpeg)
- DL4J實戰之六:圖形化展示訓練過程
- 純淨Ubuntu16安裝CUDA(9.1)和cuDNN
- disruptor筆記之六:常見場景
- Spring Cloud Gateway過濾器精確控制異常返回(分析篇)
- disruptor筆記之四:事件消費知識點小結
- disruptor筆記之二:Disruptor類分析
- disruptor筆記之一:快速入門
- Spring Native實戰(暢快體驗79毫秒啟動springboot應用)