0

I am using opencv and C++ although i'm beginner. I am trying to detect and count faces from a set of image using Haarcascade . I only want to get the number of faces on each image . how can i edit this code to get the number of faces on image????

// Function detectAndDisplay
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
Mat crop;
Mat res;
Mat gray;
string text;
stringstream sstm;

cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);

// Detect faces
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 |     CASCADE_SCALE_IMAGE, Size(30, 30));

// Set Region of Interest
cv::Rect roi_b;
cv::Rect roi_c;

size_t ic = 0; // ic is index of current element
int ac = 0; // ac is area of current element

size_t ib = 0; // ib is index of biggest element
int ab = 0; // ab is area of biggest element

for (ic = 0; ic < faces.size(); ic++) // Iterate through all current  elements (detected faces)

{
    roi_c.x = faces[ic].x;
    roi_c.y = faces[ic].y;
    roi_c.width = (faces[ic].width);
    roi_c.height = (faces[ic].height);

    ac = roi_c.width * roi_c.height; // Get the area of current element (detected face)

    roi_b.x = faces[ib].x;
    roi_b.y = faces[ib].y;
    roi_b.width = (faces[ib].width);
    roi_b.height = (faces[ib].height);

    ab = roi_b.width * roi_b.height; // Get the area of biggest element, at beginning it is same as "current" element

    if (ac > ab)
    {
        ib = ic;
        roi_b.x = faces[ib].x;
        roi_b.y = faces[ib].y;
        roi_b.width = (faces[ib].width);
        roi_b.height = (faces[ib].height);
    }

    crop = frame(roi_b);
    resize(crop, res, Size(128, 128), 0, 0, INTER_LINEAR); // This will be needed later while saving images
    cvtColor(crop, gray, CV_BGR2GRAY); // Convert cropped image to Grayscale

    // Form a filename
    filename = "";
    stringstream ssfn;
    ssfn << filenumber << ".png";
    filename = ssfn.str();
    filenumber++;

    imwrite(filename, gray);
    printf("filename");
    Point pt1(faces[ic].x, faces[ic].y); // Display detected faces on main window - live stream from camera
    Point pt2((faces[ic].x + faces[ic].height), (faces[ic].y + faces[ic].width));
    rectangle(frame, pt1, pt2, Scalar(0, 255, 0), 2, 8, 0);
}

// Show image
/*sstm << "Crop area size: " << roi_b.width << "x" << roi_b.height << " Filename: " << filename;
text = sstm.str();

putText(frame, text, cvPoint(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 0.8, cvScalar(0, 0, 255), 1, CV_AA);
imshow("original", frame);

if (!crop.empty())
{
    imshow("detected", crop);
}
else
    destroyWindow("detected");*/

}

laeemra
  • 1
  • 4

2 Answers2

1

modified your posted code sample to just return the number of detected faces in the image...

// Function to count the detected faces in your image
void countFacesInImage(Mat frame)
{
    std::vector<Rect> faces;
    Mat frame_gray;

    cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
    equalizeHist(frame_gray, frame_gray);

    // Detect faces
    face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 |     CASCADE_SCALE_IMAGE, Size(30, 30));

    return faces.size();
}

if you want to get an impression of which faces were detected and which weren't you can add this code before the return:

cv::Mat tmpImage = frame.clone();
for(unsigned int i=0; i<faces.size(); ++i)
{
    cv::rectangle(tmpImage, faces[i], cv::Scalar(0,255,0), 2);
}
cv::imshow("faces", tmpImage);
cv::waitKey(0);

after each image you have to press a key with active window "faces". You can change to cv::waitKey(n) to wait n milliseconds instead of the need to press a key.

Micka
  • 19,585
  • 4
  • 56
  • 74
  • thank you ...it really helps, but do i have to Set Region of Interest?? because i got some wrong number for my images – laeemra May 05 '15 at 13:17
  • if you want to detect faces in he whole image you dont have to use any ROI (if you need a ROI you should pass only the cropped ROI image to the function). But haar cascade face detection isnt THAT accurate, so you probably get wrong values because of detector accuracy. I've heard that the face detector of `dlib` library is more accurate, but didn't test it yet. http://dlib.net/ – Micka May 05 '15 at 13:29
  • if you want to get an impression of which faces were detected and which werent, you can try to add the new code snippet. – Micka May 05 '15 at 13:34
0

I had to do something similar and used the example of a CascadeClassifier on the OpenCV website.

The rough steps to follow are:

  1. Load all images you want to process.
  2. For each image, apply the CascadeClassifier as in the example, you will need to pass a std::vector<cv::Rect> as parameter. After detection, this vector will contain the location of all detected objects (in your case, faces).
  3. For each image, return the size of the vector to know the number of faces that were detected.

To be honest, the example I linked is something you could have found on your own without much effort.

Maarten Bamelis
  • 2,243
  • 19
  • 32
  • thank you , but the problem am a beginner although this example as like all the example i already found are using video streaming. – laeemra May 05 '15 at 12:29
  • To load an image from a file, check out [this link](http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html). You have to use the `cv::imread()` function. It will return a `cv::Mat` object that represents the image and can be used in the example I mentioned in the answer. – Maarten Bamelis May 05 '15 at 12:36