歡迎訪問我的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,完整代碼如下,有幾處要注意的地方稍后提到:
package com.bolingcavalry.grabpush.extend;
import com.bolingcavalry.grabpush.Constants;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.MatVector;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_face.FaceRecognizer;
import org.bytedeco.opencv.opencv_face.FisherFaceRecognizer;
import java.io.File;
import java.io.IOException;
import java.nio.IntBuffer;
import java.util.LinkedList;
import java.util.List;
import static org.bytedeco.opencv.global.opencv_core.CV_32SC1;
import static org.bytedeco.opencv.global.opencv_imgcodecs.IMREAD_GRAYSCALE;
import static org.bytedeco.opencv.global.opencv_imgproc.resize;
/**
* @author willzhao
* @version 1.0
* @description 訓練
* @date 2021/12/12 18:26
*/
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<String> getAllFilePath(String path) {
List<String> 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");
}
}
- 上述代碼有以下幾處要注意:
- 靜態方法read用于將圖片轉為Mat
- 靜態方法getAllFilePath可以遍歷指定目錄下的所有檔案,把它們的絕對路徑回傳
- train一共獲取了man和woman兩個目錄下的照片,man目錄下的照片的類別是1,women目錄下的照片類別是2
- 識別類是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工程下:
歡迎關注博客園:程式員欣宸
學習路上,你不孤單,欣宸原創一路相伴...
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556280.html
標籤:其他
上一篇:【后端面經-Java】AQS詳解
下一篇:返回列表