带有 FaceRecognizer 的 OpenCV 示例。 Mat.createBuffer() 不存在。为什么所有图像都必须具有相同的大小并被裁剪掉?

问题描述 投票:0回答:0

我正在尝试编写一个简单的软件,给定一组图像,识别我正在寻找的人是否在该组图像中。 通过查看 openCV 文档,我遇到了这个类

FaceRecognizer
。我试图寻找例子,而这个是我唯一能找到的例子: https://github.com/bytedeco/javacv/blob/master/samples/OpenCVFaceRecognizer.java

我做了一些替换,因为有些类在 Java 中不可用,因为我没有使用

org.bytedeco
。这是更新后的代码:

/**
 * I couldn't find any tutorial on how to perform face recognition using OpenCV and Java,
 * so I decided to share a viable solution here. The solution is very inefficient in its
 * current form as the training model is built at each run, however it shows what's needed
 * to make it work.
 *
 * The class below takes two arguments: The path to the directory containing the training
 * faces and the path to the image you want to classify. Not that all images has to be of
 * the same size and that the faces already has to be cropped out of their original images
 * (Take a look here http://fivedots.coe.psu.ac.th/~ad/jg/nui07/index.html if you haven't
 * done the face detection yet).
 *
 * For the simplicity of this post, the class also requires that the training images have
 * filename format: <label>-rest_of_filename.png. For example:
 *
 * 1-jon_doe_1.png
 * 1-jon_doe_2.png
 * 2-jane_doe_1.png
 * 2-jane_doe_2.png
 * ...and so on.
 *
 * Source: http://pcbje.com/2012/12/doing-face-recognition-with-javacv/
 *
 * @author Petter Christian Bjelland
 */
public class OpenCVFaceRecognizer {
    public static void main(String[] args) {
        String trainingDir = args[0];
        Mat testImage = Imgcodecs.imread(args[1], Imgcodecs.IMREAD_GRAYSCALE);

        File root = new File(trainingDir);

        FilenameFilter imgFilter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                name = name.toLowerCase();
                return name.endsWith(".jpg") || name.endsWith(".pgm") || name.endsWith(".png");
            }
        };

        File[] imageFiles = root.listFiles(imgFilter);

        List<Mat> images = new ArrayList<>(imageFiles.length);

        Mat labels = new Mat(imageFiles.length, 1, CvType.CV_32SC1);
        IntBuffer labelsBuf = labels.createBuffer();

        int counter = 0;

        for (File image : imageFiles) {
            Mat img = Imgcodecs.imread(image.getAbsolutePath(), Imgcodecs.IMREAD_GRAYSCALE);

            int label = Integer.parseInt(image.getName().split("\\-")[0]);

            images.add(counter, img);

            labelsBuf.put(counter, label);

            counter++;
        }

        FaceRecognizer faceRecognizer = FisherFaceRecognizer.create();
        // FaceRecognizer faceRecognizer = EigenFaceRecognizer.create();
        // FaceRecognizer faceRecognizer = LBPHFaceRecognizer.create();

        faceRecognizer.train(images, labels);

        //IntPointer label = new IntPointer(1);
        int[] label = new int [1];
        //DoublePointer confidence = new DoublePointer(1);
        double[] confidence = new double [1];
        faceRecognizer.predict(testImage, label, confidence);
        int predictedLabel = label[0];

        System.out.println("Predicted label: " + predictedLabel);
    }
}

我的问题是:

  1. .createBuffer()
    对于Java中的
    Mat
    类不存在。那么,我该如何更换呢?
  2. 为什么所有图像都必须具有相同的大小?因为训练目录当然有不同大小的图像。
  3. 为什么脸必须已经被裁掉了?我能够通过绘制一个矩形成功检测到人脸(如果你愿意,我也可以在这里分享代码)。所以,我应该将检测到的人脸保存到文件中,或者我可以简单地用检测到的人脸区域创建一个新的 BufferedImages 实例?
  4. 什么是标签,它们有什么用?仅仅为了确定那些照片代表的是同一个人? 例如: 1-jon_at_the_sea.png 1-jon_at_the_beach.png

谢谢。

java opencv face-recognition
© www.soinside.com 2019 - 2024. All rights reserved.