ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android上的人脸识别

2019-09-18 06:23:22  阅读:279  来源: 互联网

标签:face-recognition android opencv javacv


我正在尝试在Android上开发一个Face Recognition应用程序,因为我不想在项目上使用NDK(只是没有时间切换),我坚持使用Java开发整个应用程序,因此我遇到了一些问题:

>似乎Contrib模块不包含在OpenCV 2.4.2中.无论如何在项目中使用它?
>我尝试使用JavaCV来使用Contrib Module的“FaceRecognizer”类.有两个类可用,称为“FaceRecognizer”& “FaceRecognizerPtr”.有谁知道这两者之间的区别是什么?
>上面提到的类有一个叫做“Train”的方法,它在(C语言中)接收两个类型为“Mat& Integer”的矢量(模型 – >列车(图像,标签)& train(Vector< mat> theImages,Vector< ; int> theLabels).我尝试在Java中传递它们ArrayList< mat>& ArrayList< integer>和Vectors但似乎该方法显式接受了“CvArr”数据类型,我不知道如何获取…这是错误:

The method train(opencv_core.CvArr, opencv_core.CvArr) in the type
opencv_contrib.FaceRecognizer is not applicable for the arguments
(ArrayList, ArrayList)

有谁知道如何将我的ArrayList更改为CvArr?

这是我的第一篇文章,我不确定是在一个帖子还是在三个帖子中提出所有三个问题,对于给您带来的任何不便表示遗憾…如果您需要有关该项目的任何其他信息,请随时提出.

解决方法:

更新

以下文章是由Petter Christian Bjelland撰写的,所以所有的功劳都是他的.我在这里发帖,因为他的博客目前似乎处于维护模式,但我认为值得分享.

使用JavaCV进行人脸识别(自http://pcbje.com起)

我找不到任何关于如何使用OpenCV和Java进行人脸识别的教程,所以我决定在这里分享一个可行的解决方案.由于培训模型是在每次运行时构建的,因此解决方案的当前形式效率非常低,但它显示了使其工作所需的内容.

下面的类有两个参数:包含训练面的目录的路径以及要分类的图像的路径.并非所有图像都必须具有相同的尺寸,并且必须从原始图像中裁剪出面部(如果尚未进行面部检测,请查看此处).

为了简化这篇文章,该课程还要求训练图像具有文件名格式:< label> -rest_of_filename.png.例如:

1-jon_doe_1.png
1-jon_doe_2.png
2-jane_doe_1.png
2-jane_doe_2.png

… 等等.

代码:

import com.googlecode.javacv.cpp.opencv_core;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_contrib.*;
import java.io.File;
import java.io.FilenameFilter;

public class OpenCVFaceRecognizer {
  public static void main(String[] args) {
    String trainingDir = args[0];
    IplImage testImage = cvLoadImage(args[1]);

    File root = new File(trainingDir);

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

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

    MatVector images = new MatVector(imageFiles.length);

    int[] labels = new int[imageFiles.length];

    int counter = 0;
    int label;

    IplImage img;
    IplImage grayImg;

    for (File image : imageFiles) {
      // Get image and label:
      img = cvLoadImage(image.getAbsolutePath());
      label = Integer.parseInt(image.getName().split("\\-")[0]);
      // Convert image to grayscale:
      grayImg = IplImage.create(img.width(), img.height(), IPL_DEPTH_8U, 1);
      cvCvtColor(img, grayImg, CV_BGR2GRAY);
      // Append it in the image list:
      images.put(counter, grayImg);
      // And in the labels list:
      labels[counter] = label;
      // Increase counter for next image:
      counter++;
    }

    FaceRecognizer faceRecognizer = createFisherFaceRecognizer();
    // FaceRecognizer faceRecognizer = createEigenFaceRecognizer();
    // FaceRecognizer faceRecognizer = createLBPHFaceRecognizer()

    faceRecognizer.train(images, labels);

    // Load the test image:
    IplImage greyTestImage = IplImage.create(testImage.width(), testImage.height(), IPL_DEPTH_8U, 1);
    cvCvtColor(testImage, greyTestImage, CV_BGR2GRAY);

    // And get a prediction:
    int predictedLabel = faceRecognizer.predict(greyTestImage);
    System.out.println("Predicted label: " + predictedLabel);
  }
}

该类需要OpenCV Java接口.如果您正在使用Maven,则可以使用以下pom.xml检索所需的库:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.pcbje</groupId>
  <artifactId>opencvfacerecognizer</artifactId>
  <version>0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>opencvfacerecognizer</name>
  <url>http://pcbje.com</url>

  <dependencies>
    <dependency>
      <groupId>com.googlecode.javacv</groupId>
      <artifactId>javacv</artifactId>
      <version>0.3</version>
    </dependency>

    <!-- For Linux x64 environments -->
    <dependency>
      <groupId>com.googlecode.javacv</groupId>
      <artifactId>javacv</artifactId>
      <classifier>linux-x86_64</classifier>
      <version>0.3</version>
    </dependency>    

    <!-- For OSX environments -->
    <dependency>
      <groupId>com.googlecode.javacv</groupId>
      <artifactId>javacv</artifactId>
      <classifier>macosx-x86_64</classifier>
      <version>0.3</version>
    </dependency>
  </dependencies>

  <repositories>
    <repository>
      <id>javacv</id>
      <name>JavaCV</name>
      <url>http://maven2.javacv.googlecode.com/git/</url>
    </repository>
  </repositories>
</project>

原帖

引自我在http://answers.opencv.org/question/865/the-contrib-module-problem的回复.

在没有使用过javacv的情况下,让我们看看我们可以通过查看接口获得多远!该项目位于googlecode上,可以轻松浏览代码:http://code.google.com/p/javacv.

首先看看如何包装cv :: FaceRecognizer(opencv_contrib.java, line 845 at time of writing this):

@Namespace("cv") public static class FaceRecognizer extends Algorithm {
    static { Loader.load(); }
    public FaceRecognizer() { }
    public FaceRecognizer(Pointer p) { super(p); }

    public /*abstract*/ native void train(@ByRef MatVector src, @Adapter("ArrayAdapter") CvArr labels);
    public /*abstract*/ native int predict(@Adapter("ArrayAdapter") CvArr src);
    public /*abstract*/ native void predict(@Adapter("ArrayAdapter") CvArr src, @ByRef int[] label, @ByRef double[] dist);
    public native void save(String filename);
    public native void load(String filename);
    public native void save(@Adapter("FileStorageAdapter") CvFileStorage fs);
    public native void load(@Adapter("FileStorageAdapter") CvFileStorage fs);
}

啊哈,所以你需要为图像传递MatVector!您可以在CvArr(一行或一列)中传递标签. MatVector在opencv_core, line 4629 (at time of writing this)中定义,它看起来像这样:

public static class MatVector extends Pointer {
    static { load(); }
    public MatVector()       { allocate();  }
    public MatVector(long n) { allocate(n); }
    public MatVector(Pointer p) { super(p); }
    private native void allocate();
    private native void allocate(@Cast("size_t") long n);

    public native long size();
    public native void resize(@Cast("size_t") long n);

    @Index @ValueGetter public native @Adapter("MatAdapter") CvMat getCvMat(@Cast("size_t") long i);
    @Index @ValueGetter public native @Adapter("MatAdapter") CvMatND getCvMatND(@Cast("size_t") long i);
    @Index @ValueGetter public native @Adapter("MatAdapter") IplImage getIplImage(@Cast("size_t") long i);
    @Index @ValueSetter public native MatVector put(@Cast("size_t") long i, @Adapter("MatAdapter") CvArr value);
}

再看看代码,我想它可以像这样使用:

int numberOfImages = 10;
// Allocate some memory:
MatVector images = new MatVector(numberOfImages);
// Then fill the MatVector, you probably want to do something useful instead:
for(int idx = 0; idx < numberOfImages; idx++){
   // Load an image:
   CvArr image = cvLoadImage("/path/to/your/image");
   // And put it into the MatVector:
   images.put(idx, image);
}

您可能想要自己编写一个方法来执行从Java ArrayList到MatVector的转换(如果javacv中还没有这样的函数).

现在回答你的第二个问题. FaceRecognizer等同于cv :: FaceRecognizer.本机OpenCV C类返回一个cv :: Ptr< cv :: FaceRecognizer&gt ;,这是一个指向cv :: FaceRecognizer的(智能)指针.这也必须包装好.看到这里的模式? FaceRecognizerPtr的界面现在看起来像这样:

@Name("cv::Ptr<cv::FaceRecognizer>")
public static class FaceRecognizerPtr extends Pointer {
    static { load(); }
    public FaceRecognizerPtr()       { allocate();  }
    public FaceRecognizerPtr(Pointer p) { super(p); }
    private native void allocate();

    public native FaceRecognizer get();
    public native FaceRecognizerPtr put(FaceRecognizer value);
}

因此,您可以从此类获取FaceRecognizer或将FaceRecognizer放入其中.您应该只关注get(),因为指针由创建具体FaceRecognizer算法的方法填充:

@Namespace("cv") public static native @ByVal FaceRecognizerPtr createEigenFaceRecognizer(int num_components/*=0*/, double threshold/*=DBL_MAX*/);
@Namespace("cv") public static native @ByVal FaceRecognizerPtr createFisherFaceRecognizer(int num_components/*=0*/, double threshold/*=DBL_MAX*/);
@Namespace("cv") public static native @ByVal FaceRecognizerPtr createLBPHFaceRecognizer(int radius/*=1*/,
        int neighbors/*=8*/, int grid_x/*=8*/, int grid_y/*=8*/, double threshold/*=DBL_MAX*/);

所以,一旦你有FaceRecognizerPtr,你可以做以下事情:

// Holds your training data and labels:
MatVector images;
CvArr labels;
// Do something with the images and labels... Probably fill them?
// ...
// Then get a Pointer to a FaceRecognizer (FaceRecognizerPtr).
// Java doesn't have default parameters, so you have to add some yourself,
// if you pass 0 as num_components to the EigenFaceRecognizer, the number of
// components is determined by the data, for the threshold use the maximum possible
// value if you don't want one. I don't know the constant in Java:
FaceRecognizerPtr model = createEigenFaceRecognizer(0, 10000);
// Then train it. See how I call get(), to get the FaceRecognizer inside the FaceRecognizerPtr:
model.get().train(images, labels);

这会让你学会一个特征脸模型.就是这样!

标签:face-recognition,android,opencv,javacv
来源: https://codeday.me/bug/20190918/1810726.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有