JavaCV人脸识别三部曲之二:训练

这篇具有很好参考价值的文章主要介绍了JavaCV人脸识别三部曲之二:训练。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《JavaCV人脸识别三部曲》的第二篇,前文《视频中的人脸保存为图片》咱们借助摄像头为两位群众演员生成大量人脸照片,如下图,群众演员A的照片保存在E:\temp\202112\18\001\man,B的照片保存在E:\temp\202112\18\001\woman
    JavaCV人脸识别三部曲之二:训练
  • 照片准备好,并且每张照片的身份都已确定,本篇要做的就是用上述照片生成模型文件,今后新的人脸就可以中这个模型来检查了
  • 关于训练,可以用下图来表示,一共六张照片两个类别,训练完成后得到模型文件faceRecognizer.xml
    JavaCV人脸识别三部曲之二:训练

编码

  • 训练的代码很简单,在一个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
    JavaCV人脸识别三部曲之二:训练
  • 至此,本篇任务已完成,下一篇进入终极实战,用本篇训练的模型识别摄像头中的人脸,并把识别结果展示在预览页面上;

源码下载

  • 《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人脸识别三部曲之二:训练
  • javacv-tutorials里面有多个子工程,《JavaCV的摄像头实战》系列的代码在simple-grab-push工程下:
    JavaCV人脸识别三部曲之二:训练

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

学习路上,你不孤单,欣宸原创一路相伴...文章来源地址https://www.toymoban.com/news/detail-507312.html

到了这里,关于JavaCV人脸识别三部曲之二:训练的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java版人脸跟踪三部曲之三:编码实战

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 作为《Java版人脸跟踪三部曲》系列的终篇,本文会与大家一起写出完整的人脸跟踪应用代码 前文《开发设计》中,已经对人脸跟踪的核心技术、应用主流程、异常处理等方方面面做了详细设计,建

    2024年02月12日
    浏览(36)
  • LeetCode952三部曲之二:小幅度优化(137ms -> 122ms,超39% -> 超51%)

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本文是《LeetCode952三部曲》系列之二,在前文中,咱们详细分析了解题思路,然后按照思路写出了代码,在LeetCode提交成功,成绩如下图所示,137ms,超过39% 不得不说这个成绩很不理想,于是今天咱们

    2024年02月10日
    浏览(39)
  • 【Docker学习三部曲】—— 入门篇

    1️⃣ 什么是 docker ? Docker 是 一种运行应用程序的平台,它可以使应用程序在容器中不受环境差异的影响进行部署和运行 。Docker 的流行度越来越高,是因为它可以帮助在不同的开发者和开发团队之间实现代码的共享和协同开发,并且大大 简化了应用程序的部署,提高了可移

    2023年04月20日
    浏览(48)
  • 【Docker学习三部曲】——进阶篇

    1️⃣ 什么是 Docker-Compose ? Docker Compose 是 Docker 官方提供的 一个用于定义和运行多个容器的工具 ,它采用了声明式的语法定义单个应用程序的多个容器以及它们之间的相互关系和依赖关系。 使用 Docker Compose ,您可以通过一个配置文件来管理多个 Docker 容器,从而更轻松地部署

    2023年04月25日
    浏览(40)
  • vscode上的git三部曲+git pull操作

    git三部曲:git add .、git commit -m \\\'\\\'、git push,命令在连接远程仓库的本地仓库路径下的终端执行。 vscode上的可视化操作如下:  1、对仓库里的文件做更改,让仓库操作的地方有变化。 2、 点击+号,让文件进入缓存,此步骤相当于终端执行命令git add .  3、在这里输入信息并点击

    2024年02月11日
    浏览(39)
  • Go语言基准测试(benchmark)三部曲之一:基础篇

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos Go的标准库内置的testing框架提供了基准测试(benchmark)功能,可以用来验证本地方法在串行或者并行执行时的基准表现,帮助开发者了解代码的真实性能情况,例如一个方法执行一次的平均耗时,还能

    2024年02月06日
    浏览(48)
  • 大模型 Dalle2 学习三部曲(二)clip学习

    clip论文比较长48页,但是clip模型本身又比较简单,效果又奇好,正所谓大道至简,我们来学习一下clip论文中的一些技巧,可以让我们快速加深对clip模型的理解,以及大模型对推荐带来革命性的变化。 首选我们来看看clip的结构,如图clip结构比较直观,训练的时候把文本描述

    2024年02月09日
    浏览(38)
  • 【C++系列P4】‘类与对象‘-三部曲——[类](2/3)

     前言 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎! 【 \\\'类与对象\\\'-三部曲】的大纲主要内容如下 : 如标题所示,本章是【 \\\'类与对象\\\'-三部曲】三章中的第二章节—— 类章节 ,主要内容如下: 目录 一.类 1.类的组成与计算类的大小(含结构体内存对齐规则) 二. 空类的大小

    2024年02月08日
    浏览(40)
  • 数据结构:堆的三部曲(二)top K问题

    top k问题解决的是获取前几个最值的问题。 我们知道 堆的功能主要是选数,选出最大值或者最小值 。那么我们每次获取堆顶元素后,再将剩余元素调整成堆,就可以选出次大的数,如果我们只想要前k个最大值或者最小值,就只需要获取堆顶元素k次,调整k次。比如王者荣耀

    2024年02月02日
    浏览(40)
  • Go语言基准测试(benchmark)三部曲之三:提高篇

    这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos -《Go语言基准测试(benchmark)三部曲》已近尾声,经历了《基础篇》和《内存篇》的实战演练,相信您已熟练掌握了基准测试的常规操作以及各种参数的用法,现在可以学习一些进阶版的技能了,在面

    2024年02月06日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包