Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use FaceDetector.Face for face recognition on Android

This is my first post here so I am sorry if my question is not clear or there is not enough information provided.

I am currently working on an Android application that could recognize faces from pictures.

My first approach was to use JavaCV and everything works fine, except the fact that face detection takes too much of time to finish!

After that, I tried to detect faces by using FaceDetector.Face. Then I used the detected faces for training my face recognizer model. There was no error found so far.

My problem is that my model could not recognize any detected face given by FaceDetector.Face. I always get -1 from the predict function. Could anybody tell what might be wrong? Thank you in advance!

This is how I crop faces after detection:

    for(int count=0;count<NUMBER_OF_FACE_DETECTED;count++)
    {
        Face face=detectedFaces[count];
        PointF midPoint=new PointF();
        face.getMidPoint(midPoint);         
        eyeDistance=face.eyesDistance();

        left = midPoint.x - (float)(1.4 * eyeDistance);
        top = midPoint.y - (float)(1.8 * eyeDistance);

        bmFace = Bitmap.createBitmap(origiImage, (int) left, (int) top, (int) (2.8 * eyeDistance), (int) (3.6 * eyeDistance));          
        bmFaces.add(bmFace);
    }

Here is a main part of training the model.

    MatVector images = new MatVector(imageFiles.length);            
    int[] labels = new int[imageFiles.length];

    IplImage img;
    IplImage grayImage;
    FaceRecognizer faceRecognizer = createLBPHFaceRecognizer(1, 8, 8, 8, binaryTreshold);
    try
    {          
        FileInputStream fstream = new FileInputStream(working_Dir.getAbsolutePath()+"/csv.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
        String imgInfo;

        for (int i = 0; (imgInfo = br.readLine()) != null; i++)  
        {
            String info[] = imgInfo.split(";");

            String imagePath = info[0];             
            img = cvLoadImage(imagePath);
            grayImage = IplImage.create(img.width(),img.height(), IPL_DEPTH_8U, 1);
            cvCvtColor(img, grayImage, CV_BGR2GRAY);
            images.put(i, grayImage);
            labels[i] = Integer.parseInt(info[1]);;
        }
        in.close();

        //train the FaceRecognizer model         
        faceRecognizer.train(images, labels);
    }catch (Exception e)
    {
        System.err.println("Error: " + e.getMessage());
    }

Finally I recognize face with the following code:

    public static String identifyFace(IplImage grayImg)
{
    String predictedName = "";

    //identify face from the image
    int predictedLabel = faceRecognizer.predict(grayImg);

    if(predictedLabel != -1 )
    {
        predictedName = new String(idToName.get(predictedLabel));
    }
    return predictedName;
}
like image 812
user1956743 Avatar asked Jan 08 '13 02:01

user1956743


People also ask

How do you use face recognition on Android?

From Settings, tap Biometrics and security, and then tap Face recognition. Tap Continue. If you don't already have a secure screen lock, you will need to set one up. Hold the phone 8-20 inches away and position your face inside the circle.

Can Samsung face recognition with mask?

However, Android also has a version of facial recognition that can unlock your phone without entering a passcode or pattern — and may work if you're wearing a mask. To enable it, you have to set up an alternate appearance similar to the steps for the iPhone noted above.


2 Answers

This can only happen if you don't set the threshold appropriately, see the documentation:

  • http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_api.html#createlbphfacerecognizer

The method to create a LBPHFaceRecognizer is:

Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius=1, int neighbors=8, int grid_x=8, int grid_y=8, double threshold=DBL_MAX)

, where:

  • threshold – The threshold applied in the prediction. If the distance to the nearest neighbor is larger than the threshold, this method returns -1.

So in the above method signature you see, that the threshold is set to DBL_MAX by default. So if you simply leave the threshold out, then it'll never yield -1. On the other hand, if you set the threshold too low, the FaceRecognizer is always going to yield -1. That said, check what you have set binaryTreshold in your code to. Finding the appropriate decision threshold for your data is a classic optimization problem, where you have to optimize for the best threshold by a given criteria (for example based on False Acceptance Rate/False Rejection Rate).

like image 120
bytefish Avatar answered Sep 20 '22 15:09

bytefish


I know this is really late, but try using Haar cascade classifier from JavaCV instead of facedetector from Android itself

like image 34
Joshua H Avatar answered Sep 21 '22 15:09

Joshua H