OpenCV Java 采集人脸并训练模型,网上没有 OpenCV Java 最新训练模型的教程,经过自己看文档和一次次尝试,总结的教程。
环境
1 | OS: macOS 10.13.3 |
步骤
第一步:准备数据
下载数据库
官网教程里表示有三个数据库可以下载,我们这里用第一种
- AT&T Facedatabase(有时也称为ORL面孔数据库)包含40个不同的人,其中每个人10种不同图像。图像是在不同的时间拍摄的,改变了照明,面部表情(开放/闭眼,微笑/不微笑)和面部细节(眼镜/没有眼镜)。所有图像都是在黑暗的均匀背景下拍摄的,拍摄对象处于直立的正面位置(对某些侧面运动具有宽容度)。
下载下来我放到了桌面 /Users/limbang/Desktop/orl_faces/
该文件夹下有 s1 到 s40 每个文件夹代表一个人。
读取图片人脸收据数据,结合前面的,就可以用摄像头来创建数据
和前面一样先检测出人脸,代码重复的我就省略了,主要就是把图片缩放成和下载的数据一样1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 创建分类器
CascadeClassifier ...
省略...
// 检测人脸
face_cascade.detectMultiScale(...
int i = 0;
// 循环所有找到的人脸
for (Rect rect : faces.toArray()) {
// 将识别后的灰度图人脸,重新创建 MAT
Mat faceROI = new Mat(grayImg, rect);
if (faceROI.cols() > 100) {
// 图片缩放
Imgproc.resize(faceROI, faceROI, new Size(92, 112));
// 写出图片
Imgcodecs.imwrite("/Users/limbang/Desktop/orl_faces/s42/" + i + ".pgm", faceROI);
i++;
}
}
用上面那张图片试试
第二步:训练模型
用FaceRecognizer
的train
方法来训练模型,有三种方式LBPHFaceRecognizer
EigenFaceRecognizer
FisherFaceRecognizer
,这里我们使用 LBPH算法来训练模型。
可以看到 train(List1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
List<Mat> images = new ArrayList<>();
Mat labels = new Mat(6,1,CvType.CV_32SC1); //有多少张图片就等于多少,这里的 rows = 6
int[] labelsArray={0, 1}; //这里代表2个人
//下面是手动添加标签为0的人3张图片
images.add(Imgcodecs.imread("/Users/limbang/Desktop/orl_faces/s1/1.pgm", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE));
labels.put(0,0,labelsArray[0]);
images.add(Imgcodecs.imread("/Users/limbang/Desktop/orl_faces/s1/2.pgm", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE));
labels.put(1,0,labelsArray[0]);
images.add(Imgcodecs.imread("/Users/limbang/Desktop/orl_faces/s1/3.pgm", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE));
labels.put(2,0,labelsArray[0]);
//下面是手动添加标签为1的人3张图片
images.add(Imgcodecs.imread("/Users/limbang/Desktop/orl_faces/s2/1.pgm", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE));
labels.put(3,0,labelsArray[1]);
images.add(Imgcodecs.imread("/Users/limbang/Desktop/orl_faces/s2/2.pgm", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE));
labels.put(4,0,labelsArray[1]);
images.add(Imgcodecs.imread("/Users/limbang/Desktop/orl_faces/s2/3.pgm", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE));
labels.put(5,0,labelsArray[1]);
FaceRecognizer faceRecognizer = LBPHFaceRecognizer.create();
// 训练模型
faceRecognizer.train(images,labels);
// 存储训练的模型
faceRecognizer.write("/Users/limbang/Desktop/face.xml");
打开 XML 文件可以看到,之前是按照这个问题里面创建的模型,也和他遇到的问题一样,标签会是一个疯狂大的数值或是负数(不是预想的0和1),最后看到这篇文章里的“神经网络java+opencv2.X ” 才知道标签应该这样创建。1
2
3
4
5
6<labels type_id="opencv-matrix">
<rows>6</rows>
<cols>1</cols>
<dt>i</dt>
<data>
0 0 0 1 1 1</data></labels>
第三步:识别人脸
就是把前面的几部分代码结合,代码如下
1 | // 创建分类器 |
后记
遍历文件夹读取图片
1 | /** |