I'm trying to develop a Face Recognition app on Android and since I don't want to use NDK on the project (simply don't have the time to switch), I'm sticking to develop the whole app with Java and therefor I'm having some problems :
-
It seems the Contrib Module isn't included in OpenCV 2.4.2 . is there anyway to use it in the project ?
-
I tried using JavaCV to use the Contrib Module's "FaceRecognizer" class. there are two classes available called "FaceRecognizer" & "FaceRecognizerPtr". does anybody know what the difference between these two is ?
-
The classes mentioned above have a method called "Train" which (In C++) receives two Vectors of types "Mat & Integer" (
model->train(images,labels) & train(Vector<mat> theImages, Vector<int> theLabels
) . I tried passing themArrayList<mat> & ArrayList<integer>
and Vectors in Java but it seems that the method explicitly accepts the "CvArr" Data type which I'm not sure how to acquire… Here is the error :
The method train(opencv_core.CvArr, opencv_core.CvArr) in the type
opencv_contrib.FaceRecognizer is not applicable for the arguments
(ArrayList, ArrayList)
Does anyone know how to change my ArrayList to CvArr ?!
This is my first post and I wasn't sure whether to ask all three questions in one post or in three posts so sorry for any inconveniences… If you need any other Information about the project, feel free to ask.
Best Answer
Update
The following article was written by Petter Christian Bjelland, so all credit is his. I am posting it here, because his blog seems to be in Maintenance mode at the moment, but I think it is worth sharing.
Doing face recognition with JavaCV (from http://pcbje.com)
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 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:... and so on.
The code:
The class requires the OpenCV Java interface. If you’re using Maven, you can retrieve the required libraries with the following pom.xml:
Original Post
Quoting from my reply on http://answers.opencv.org/question/865/the-contrib-module-problem.
Without ever having used javacv, let's see how far we can get by just looking at the interfaces! The project is on googlecode, which makes it easy to browse the code: http://code.google.com/p/javacv.
First have a look at how
cv::FaceRecognizer
has been wrapped (opencv_contrib.java, line 845 at time of writing this):Aha, so you need to pass a
MatVector
for the images! You can pass the labels in aCvArr
(one row or one column). TheMatVector
is defined in opencv_core, line 4629 (at time of writing this) and it looks like this:Again just by looking at the code, I guess it can be used like this:
You probably want to write yourself a method that does the conversion from a Java
ArrayList
to aMatVector
(if such a function does not exist in javacv yet).Now to your second question.
FaceRecognizer
is the equivalent tocv::FaceRecognizer
. The native OpenCV C++ classes return acv::Ptr<cv::FaceRecognizer>
, which is a (Smart) Pointer to acv::FaceRecognizer
. This has to be wrapped as well. See a pattern here?The interface of
FaceRecognizerPtr
now looks like this:So you can either get a
FaceRecognizer
from this class or put aFaceRecognizer
into. You should only be concerned about theget()
, as the Pointer is filled by the method creating the concreteFaceRecognizer
algorithm:So once you have got the FaceRecognizerPtr, you can do things like:
This learns you an Eigenfaces model. And that's it!