JavaCV Face Recognition Trilogy Part 2: Training

Get into the habit of writing together! This is the 5th day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

Welcome to my GitHub

All original works of Xinchen (including supporting source code) are classified and summarized here: github.com/zq2599/blog…

Overview of this article

  • This article is the second of the "JavaCV Face Recognition Trilogy". In the previous article "Save the Face in the Video as a Picture", we use the camera to generate a large number of face photos for the two extras, as shown below, the photo of extra actor A is saved In E:\temp\202112\18\001\ man , B's photo is saved in E:\temp\202112\18\001\ woman :

insert image description here

  • The photos are ready, and the identity of each photo has been determined. What we need to do in this article is to use the above photos to generate model files. In the future, new faces can be checked in this model.
  • Regarding training, it can be represented by the following figure. There are six photos in two categories. After the training is completed, the model file faceRecognizer.xml is obtained:

insert image description here

coding

  • The training code is very simple. Let’s do it in a java file. Simple-grab-push is a project that has been reused in the entire "JavaCV Camera Actual Combat" series. Now the new file TrainFromDirectory.java is added to this project. The complete code is as follows, there are A few points to note are mentioned later:
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");
    }
}
复制代码
  • The above code has the following points to note:
  1. The static method read is used to convert the image to Mat
  2. The static method getAllFilePath can traverse all files in the specified directory and return their absolute paths
  3. The train obtained a total of photos in the man and woman categories. The photo category in the man category is 1, and the photo category in the women category is 2.
  4. The recognition class is FisherFaceRecognizer, which is used for the current training and the recognition of the next article

implement

  • Run the main method. After the execution is completed, as shown in the figure below, it can be seen that the model file faceRecognizer.xml has been generated in the directory E:\temp\202112\18\001:

insert image description here

  • So far, this task has been completed, and the next one will enter the ultimate actual combat, use the model trained in this article to recognize the face in the camera, and display the recognition result on the preview page;

Source code download

  • The complete source code of "Camera Combat of JavaCV" can be downloaded from GitHub. The address and link information are shown in the following table ( github.com/zq2599/blog…
name Link Remark
Project homepage github.com/zq2599/blog… The project's homepage on GitHub
git repository address (https) github.com/zq2599/blog… The warehouse address of the source code of the project, https protocol
git repository address (ssh) [email protected]:zq2599/blog_demos.git The warehouse address of the project source code, ssh protocol
  • There are multiple folders in this git project. The source code of this article is in the javacv-tutorials folder, as shown in the red box below:

insert image description here

  • There are multiple sub-projects in javacv-tutorials. The code of the "JavaCV Camera Actual" series is under the simple-grab-push project:

insert image description here

Welcome to the Nuggets: Programmer Xin Chen

On the road of learning, you are not alone, Xinchen Original will accompany you all the way...

Guess you like

Origin juejin.im/post/7083053535419432968