laeemra
laeemra

Reputation: 1

detect and count face on image using open cv and c++

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");*/

}

Upvotes: 0

Views: 1958

Answers (2)

Micka
Micka

Reputation: 20130

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.

Upvotes: 1

Maarten Bamelis
Maarten Bamelis

Reputation: 2423

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.

Upvotes: 0

Related Questions