1

I have a code that detects faces and saves multiple cropped area images of them to a file path. My code doesn't stop saving images of detected faces until I physically close the program. For every one second a face is detected on a webcam, my code saves 6 images of the face.

Is it possible to have it save just one image per face detected? For example, if there is one face, only one image, if two faces, an image of both faces are saved etc. My code is below. Can anyone help me?

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

void detectAndDisplay(Mat frame);

string face_cascade_name = "C:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml";
CascadeClassifier face_cascade;
string window_name = "Window";
int filenumber; 
string filename;


int main(void)
{
    VideoCapture capture(0);

    if (!capture.isOpened())  
        return -1;

    if (!face_cascade.load(face_cascade_name))
    {
        cout << "error" << endl;
        return (-1);
    };

    Mat frame;

    for (;;)
    {
        capture >> frame;

        if (!frame.empty())
        {
            detectAndDisplay(frame);
        }
        else
        {
            cout << "error2" << endl;
            break;
        }

        int c = waitKey(10);

        if (27 == char(c))
        {
            break;
        }
    }

    return 0;
}

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);

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

    cv::Rect roi_b;
    cv::Rect roi_c;

    size_t ic = 0; 
    int ac = 0; 

    size_t ib = 0; 
    int ab = 0; 

    for (ic = 0; ic < faces.size(); ic++) 

    {
        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; 

        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); 
        cvtColor(crop, gray, CV_BGR2GRAY); 

        filename = "C:\\Users\\Desktop\\Faces\\face";
        stringstream ssfn;
        ssfn << filename.c_str() << filenumber << ".jpg";
        filename = ssfn.str();
        cv::imwrite(filename, res); 
        filenumber++;


        Point pt1(faces[ic].x, faces[ic].y); 
        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);
    }


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

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

}
kingpin
  • 85
  • 1
  • 14
  • you should probably include that this code is taken from here http://docs.opencv.org/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html – Zach Spencer Jan 15 '15 at 21:02
  • 1
    Depending on the frame rate, and the duration for which a face appears, the code _will_ save all those images. If you want to save just one image per person, then this becomes a problem of face matching. – a-Jays Jan 16 '15 at 08:58

0 Answers0