ToB企服应用市场:ToB评测及商务社交产业平台
标题:
JavaCV人脸识别三部曲之二:训练
[打印本页]
作者:
宁睿
时间:
2023-6-29 08:06
标题:
JavaCV人脸识别三部曲之二:训练
欢迎访问我的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)git@github.com:zq2599/blog_demos.git该项目源码的仓库地址,ssh协议
这个git项目中有多个文件夹,本篇的源码在
javacv-tutorials
文件夹下,如下图红框所示:
javacv-tutorials
里面有多个子工程,《JavaCV的摄像头实战》系列的代码在
simple-grab-push
工程下:
欢迎关注博客园:程序员欣宸
学习路上,你不孤单,欣宸原创一路相伴...
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4