天天热头条丨JavaCV人脸识别三部曲之二:训练
2023-06-29 08:27:28
|
来源:博客园
【资料图】
欢迎访问我的GitHub本篇概览本文是《JavaCV人脸识别三部曲》的第二篇,前文《视频中的人脸保存为图片》咱们借助摄像头为两位群众演员生成大量人脸照片,如下图,群众演员A的照片保存在E:\temp\202112\18\001\man,B的照片保存在E:\temp\202112\18\001\woman:照片准备好,并且每张照片的身份都已确定,本篇要做的就是用上述照片生成模型文件,今后新的人脸就可以中这个模型来检查了关于训练,可以用下图来表示,一共六张照片两个类别,训练完成后得到模型文件faceRecognizer.xml:编码训练的代码很简单,在一个java文件中搞定吧,simple-grab-push是整个《JavaCV的摄像头实战》系列一直再用的工程,现在该工程中新增文件TrainFromDirectory.java,完整代码如下,有几处要注意的地方稍后提到:这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
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 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 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"); }}
上述代码有以下几处要注意:静态方法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协议 |
学习路上,你不孤单,欣宸原创一路相伴...