Ask Your Question
1

CascadeClassifier wont detect image using runAt that it has already found using dectectMultiScale

asked 2013-10-17 10:51:45 -0600

_Robert gravatar image

updated 2013-10-17 15:49:41 -0600

berak gravatar image

I want to make a function that just runs the classifier once using runAt, for when you already know where the image should be. (E.g. if you have found a face but want to run several classifier over the face to decide if its happy or sad).

This was my attempt (I had to make a subclass since runAt is protected).

int RSCascadeClassifier::runOnceOnWholeImage(const cv::Mat& image,
                                             double & gypWeight)
{
    cv::Size size(image.cols, image.rows);

    // Need to set image first, see:
    // http://docs.opencv.org/modules/objdetect/doc/cascade_classification.html#featureevaluator-setimage
    bool success = featureEvaluator->setImage( image, size );

    if (!success)
    {
        CV_Assert( false );
        return 0;
    }

    // Once once over the whole image
    int result = runAt(this->featureEvaluator, cv::Point(0, 0), gypWeight);

    return result;
}

To test this out I got the result of a successful detectMultiScale, then cropped the image and sent it to my method:

faceLBPClassifier.detectMultiScale(fullImage,
                                    objects,
                                    1.1, // Scale factor
                                    2, // Min neighbours
                                    CV_HAAR_SCALE_IMAGE | 0, // Flags
                                    cv::Size( 80 , 120 ) // Min size
                                    );

if (objects.size() > 0)
{
    cv::Rect faceRect = objects[0];
    cv::Mat foundFace = fullImage(faceRect).clone();

    double weight;
    int result = faceLBPClassifier.runOnceOnWholeImage(foundFace, weight);

    NSLog(@"r:%d w:%f", result, weight);
}

The results were:

r:0 w:-2.135099
r:-2 w:-2.469498
r:0 w:-2.135099
r:-1 w:-3.106470
r:0 w:-2.135099  ...

I.e. no success (1) results.

This should always return success since the same classifier has already found the result in that the exact rectangle.

Does anyone know what I have done wrong?

edit retag flag offensive close merge delete

Comments

I have figured this out but I cant post an answer because I am a new user :(

_Robert gravatar image_Robert ( 2013-10-18 05:23:08 -0600 )edit

make it a comment (or edit the question) , and mark question as [solved] then. (we'll upvote you a bit, too, iirc all it needs is 50 points )

berak gravatar imageberak ( 2013-10-18 05:32:08 -0600 )edit

@barak - It says I have to wait 1 more day before I can answer it. It was really frustrating because it didn't tell me until I hit submit and it deleted my (quite detailed) answer. But thanks for the up vote :)

_Robert gravatar image_Robert ( 2013-10-18 13:05:15 -0600 )edit

yea, that's frustrating ;( if you didn't close any tabs, it might still be in your history

berak gravatar imageberak ( 2013-10-18 13:24:46 -0600 )edit

It worked. Got my answer in at last!

_Robert gravatar image_Robert ( 2013-10-22 15:36:25 -0600 )edit

Could you give the code of your RSCascadeClassifier class. I can't make runAt work. I derived a class from Cascade Calssifier and implemented public SetImage and RunAt. But when I try it, I get memory access violation.

maria_otago gravatar imagemaria_otago ( 2014-04-23 20:28:29 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2013-10-22 15:35:48 -0600

_Robert gravatar image

The problem was that the image provided was at a different scale to the image that was detected. A classifier has its native window size that it must detect at. This can be exposed publicly in subclass like so:

cv::Size RSCascadeClassifier::windowSize()
{
    cv::Size windowSize = data.origWinSize;

    // Note: this will not work with old format XML classifiers. 

    return windowSize;
}

Then its just a case of resizing the image to the size of this window:

cv::Rect faceRect = objects[0];
cv::Mat foundFaceImage = rotatedFullImage(faceRect).clone();

cv::Size classifierSize = _faceLBPClassifier.windowSize();

cv::Mat scaledFace;
cv::resize(foundFaceImage, scaledFace, classifierSize, 0, 0, INTER_LINEAR);

double weight;
int result = _faceLBPClassifier.runOnceOnWholeImage(scaledFace, weight);

This this fixes the issue 90% of the time, however, sometimes it still wont fully detect the image. I think this is due averaging / merging of a few overlapping rectangles.

edit flag offensive delete link more

Question Tools

Stats

Asked: 2013-10-17 10:51:45 -0600

Seen: 761 times

Last updated: Oct 22 '13