libface Status

When I started working on libface, the face detection was not really good – we used one Haar cascade, and tuning certain parameters caused the detection to either ignore lots of genuine faces or gave tons of false positives.

Therefore, the main focus of my work till now was to get detection to work better. So I made a class Haarcascades, which is essentially a “set” of cascades, to which you can add a cascade, remove one, set a cascade’s weight, and so on.

This tremendously simplifies things when you want to perform the actual detection with multiple cascades.

Now, since I use multiple cascades for detection, most of the genuine faces are detected more than once. And since I’ve allowed detection to be very permissive ( tuning some parameters ), I actually INVITE false detections to occur, but also allow multiple detections of true faces. Thus, what I get is this :

An example of using multiple cascades

See? It sucks. Big time. When you want to pass all these detections to a program/library that will actually USE these detections, it will mean passing some faces over and over again, and also passing that random square near the bottom.

So what I tried was a simple clustering algorithm to reduce a cluster of many squares whose center points are very close ( distance lesser than a tunable threshold ) to one square. The number of squares that were “duplicates” of the reduced square per face is then called the “genuineness” of that face. Because, if there were a lot of duplicate detections for a face, then there’s a high chance that it is genuine. This fact is evident from the above picture. Note that the unwanted square near the bottom has no duplicate near it. Therefore, in the final detection output, I do not allow faces with less than 2 duplicates, and the result is awesome:

The detection results after using the clustering algorithm

This is the code for the clustering:

// Returns a vector of the final, true faces, with no duplicates
vector<Face> FaceDetect::finalFaces(vector< vector<Face> > combo, int maxdist, int mindups)
{
    vector<Face> finalResult;
    vector<int> genuineness;
    
    // Make one long vector of all faces
    unsigned int i, j;
    for (i = 0; i < combo.size(); ++i)
    {
        for (j = 0; j < combo[i].size(); ++j)
            finalResult.push_back(combo[i].at(j));
    }

    /* Now, starting from the left, take a face and compare with rest. If distance is less than a threshold, consider them to
       be "overlapping" face frames and delete the "duplicate" from the vector.
       Remember that only faces to the RIGHT of the reference face will be deleted.
    */

    int ctr = 0;
    for (i = 0; i < finalResult.size(); ++i)
    {
        int duplicates = 0;
        for (j = i + 1; j < finalResult.size(); ++j)	// Compare with the faces to the right
        {
            ctr++;
            if (distance(finalResult[i], finalResult[j]) < maxdist)
            {
                finalResult.erase(finalResult.begin() + j);
                duplicates++;
                j--;

            }
        }
        genuineness.push_back(duplicates);
        if (duplicates < mindups)	// Less duplicates, probably not genuine, kick it out
        {
            genuineness.erase(genuineness.begin() + i);
            finalResult.erase(finalResult.begin() + i);
            i--;
        }
        /* Note that the index of the reference element will be the same as the index of it's number of duplicates
           in the genuineness vector, so win-win!.
        */
    }
    printf("Faces parsed : %d, number of final faces : %d\n", ctr, (int)genuineness.size());
    return finalResult;
}

Now, there is a single detection instance per image. Now, I guess, apart from possible future optimizations, the face detection problem is solved. Now I’ll have to concentrate on polishing libface’s Eigenfaces implementation for better and faster facial recognition. I’m also working on a Qt widget to that can be used to “tag” ( you know, draw squares ) regions in images. So if you know Qt and can help me with this, you’re welcome to help!

Thanks to my roommate Parth for his photos, which I use for testing libface.

After finishing the Eigenfaces polishing, I intend to get familiar with the digiKam codebase and plugins so that my GSoC work can be made easier. That is, IF I get selected in GSoC 2010!

One thought on “libface Status

  1. Pingback: Tweets that mention libface Status « Aditya Bhatt's Blog -- Topsy.com

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 46 other followers

%d bloggers like this: