欢迎访问我的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");
}
}
  • 上述代码有以下几处要注意:
  1. 静态方法read用于将图片转为Mat
  2. 静态方法getAllFilePath可以遍历指定目录下的所有文件,把它们的绝对路径返回
  3. train一共获取了man和woman两个目录下的照片,man目录下的照片的类别是1,women目录下的照片类别是2
  4. 识别类是FisherFaceRecognizer,现在的训练和下一篇的识别都用这个类

执行

  • 运行main方法,待执行完成后,如下图,可见目录E:\temp\202112\18\001下已经生成模型文件faceRecognizer.xml:

  • 至此,本篇任务已完成,下一篇进入终极实战,用本篇训练的模型识别摄像头中的人脸,并把识别结果展示在预览页面上;

源码下载

名称 链接 备注
项目主页 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工程下:

欢迎关注博客园:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

JavaCV人脸识别三部曲之二:训练的更多相关文章

  1. 人脸识别经典算法二:LBP方法

    与第一篇博文特征脸方法不同,LBP(Local Binary Patterns,局部二值模式)是提取局部特征作为判别依据的.LBP方法显著的优点是对光照不敏感,但是依然没有解决姿态和表情的问题.不过相 ...

  2. opencv实现人脸识别(三) 训练图片模块

    现在我们已经拍好了需要训练的图片,接下来就是进行训练 流程图: 我们在这里用到了numpy库,NumPy是一个功能强大的Python库,主要用于对多维数组执行计算. 使用numpy的目的是减少pyth ...

  3. [DeeplearningAI笔记]卷积神经网络4.1-4.5 人脸识别/one-shot learning/Siamase网络/Triplet损失/将面部识别转化为二分类问题

    4.4特殊应用:人脸识别和神经网络风格转换 觉得有用的话,欢迎一起讨论相互学习~Follow Me 4.1什么是人脸识别 Face verification人脸验证 VS face recogniti ...

  4. atitit.人脸识别的应用场景and使用最佳实践 java .net php

    atitit.人脸识别的应用场景and使用最佳实践 java .net php 1. 人脸识别的应用场景 1 2. 框架选型 JNI2OpenCV.dll and JavaCV 1 3. Url ap ...

  5. Yale数据库上的人脸识别

    一.问题分析 1. 问题描述 在Yale数据集上完成以下工作:在给定的人脸库中,通过算法完成人脸识别,算法需要做到能判断出测试的人脸是否属于给定的数据集.如果属于,需要判断出测试的人脸属于数据集中的哪 ...

  6. atitit.人脸识别的应用场景and使用最佳实践 java .net php

    atitit.人脸识别的应用场景and使用最佳实践 java .net php 1. 人脸识别的应用场景1 2. 标准化的api1 3. 框架选型 JNI2OpenCV.dll and JavaCV ...

  7. face_recognition开源人脸识别库:离线识别率高达99.38%

    基于Python的开源人脸识别库:离线识别率高达99.38%——新开源的用了一下感受一下 原创 2017年07月28日 21:25:28 标签: 人脸识别 / 人脸自动定位 / 人脸识别开源库 / f ...

  8. OpenCV 和 Dlib 人脸识别基础

    00 环境配置 Anaconda 安装 1 下载 https://repo.anaconda.com/archive/ 考虑到兼容性问题,推荐下载Anaconda3-5.2.0版本. 2 安装 3 测 ...

  9. OpenCV人脸识别的原理 .

    OpenCV人脸识别的原理 . 在之前讲到的人脸测试后,提取出人脸来,并且保存下来,以供训练或识别是用,提取人脸的代码如下: void GetImageRect(IplImage* orgImage, ...

  10. C# 人脸识别库 0.2

    ViewFaceCore 0.2 超简单的 C# 人脸识别库 前言: 首先谢谢大家对这个库的关注,前一篇博文得到了大家的 支持 和 Star,十分开心.本想尽快实现大家的期待的活体检测功能,但是前段时 ...

随机推荐

  1. 机器学习(六):回归分析——鸢尾花多变量回归、逻辑回归三分类只用numpy,sigmoid、实现RANSAC 线性拟合

    [实验1 回归分析] 一. 预备知识 使用梯度下降法求解多变量回归问题 数据集 Iris 鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作示例.数据集内包含 3 类共 150 条记录 ...

  2. 迁移学习(COAL)《Generalized Domain Adaptation with Covariate and Label Shift CO-ALignment》

    论文信息 论文标题:Generalized Domain Adaptation with Covariate and Label Shift CO-ALignment论文作者:Shuhan Tan, ...

  3. LDAP数据过滤问题

    集成ldap同步用户遇到的问题: 首先说明同步需求: 业务需要只同步 objectClass 类型为user的用户 连接ldap查询用户的时候 过滤器只加了 .where("objectCl ...

  4. 新员工入职,前端基础环境变量的配置!node、nvm、vue-cli的安装和下载

    1.安装nvm及配置 首先下载nvm不要下载node,如果电脑已经有node的话需要卸载node,并使用命令提示符来查看node的位置(where node)手动删除 nvm下载链接:https:// ...

  5. python 高级函数补充

    补充几个高级函数 zip 把两个可迭代内容生成一个可迭代的tuple元素类型组成的内容 # zip 案例 l1 = [ 1,2,3,4,5] l2 = [11,22,33,44,55] z = zip ...

  6. #PowerBi 1分钟学会,以“万”为单位显示数据

    PowerBi是一款强大的数据分析和可视化工具,它可以帮助我们快速地制作出各种图表和报表,展示数据的价值和洞察. 但是,有时候我们的数据量太大,导致图表上的数字难以阅读和比较.例如,如果我们想要查看某 ...

  7. #Python 缺失值的检测与处理,处理部分

  8. python列表函数的基本使用

    一.列表简介 序列是Python最常见的操作,是最经常使用的一种数据操作.列表是当前序列中使用最多的. 序列中的每一个值对应的位置,称之为索引.通常情景下,第一个索引是位置为0,第二个索引位置为1.. ...

  9. 2023-03-13:给定一个整数数组 A,坡是元组 (i, j),其中 i < j 且 A[i] <= A[j], 这样的坡的宽度为 j - i。 找出 A 中的坡的最大宽度,如果不存在,返回 0

    2023-03-13:给定一个整数数组 A,坡是元组 (i, j),其中 i < j 且 A[i] <= A[j], 这样的坡的宽度为 j - i. 找出 A 中的坡的最大宽度,如果不存在 ...

  10. 2023-03-11:给定一个N*M的二维矩阵,只由字符‘O‘、‘X‘、‘S‘、‘E‘组成, ‘O‘表示这个地方是可通行的平地, ‘X‘表示这个地方是不可通行的障碍, ‘S‘表示这个地方有一个士兵,全

    2023-03-11:给定一个N*M的二维矩阵,只由字符'O'.'X'.'S'.'E'组成, 'O'表示这个地方是可通行的平地, 'X'表示这个地方是不可通行的障碍, 'S'表示这个地方有一个士兵,全 ...