/***************************************************************************** * Face Recognition using Eigenfaces or Fisherfaces ****************************************************************************** * by Shervin Emami, 5th Dec 2012 * http://www.shervinemami.info/openCV.html ****************************************************************************** * Ch8 of the book "Mastering OpenCV with Practical Computer Vision Projects" * Copyright Packt Publishing 2012. * http://www.packtpub.com/cool-projects-with-opencv/book *****************************************************************************/ ////////////////////////////////////////////////////////////////////////////////////// // detectObject.cpp, by Shervin Emami (www.shervinemami.info) on 30th May 2012. // Easily detect objects such as faces or eyes (using LBP or Haar Cascades). ////////////////////////////////////////////////////////////////////////////////////// #include "detectObject.h" // Easily detect faces or eyes (using LBP or Haar Cascades). // Search for objects such as faces in the image using the given parameters, storing the multiple cv::Rects into 'objects'. // Can use Haar cascades or LBP cascades for Face Detection, or even eye, mouth, or car detection. // Input is temporarily shrunk to 'scaledWidth' for much faster detection, since 200 is enough to find faces. void detectObjectsCustom(const Mat &img, CascadeClassifier &cascade, vector &objects, int scaledWidth, int flags, Size minFeatureSize, float searchScaleFactor, int minNeighbors) { // If the input image is not grayscale, then convert the BGR or BGRA color image to grayscale. Mat gray; if (img.channels() == 3) { cvtColor(img, gray, CV_BGR2GRAY); } else if (img.channels() == 4) { cvtColor(img, gray, CV_BGRA2GRAY); } else { // Access the input image directly, since it is already grayscale. gray = img; } // Possibly shrink the image, to run much faster. Mat inputImg; float scale = img.cols / (float)scaledWidth; if (img.cols > scaledWidth) { // Shrink the image while keeping the same aspect ratio. int scaledHeight = cvRound(img.rows / scale); resize(gray, inputImg, Size(scaledWidth, scaledHeight)); } else { // Access the input image directly, since it is already small. inputImg = gray; } // Standardize the brightness and contrast to improve dark images. Mat equalizedImg; equalizeHist(inputImg, equalizedImg); // Detect objects in the small grayscale image. cascade.detectMultiScale(equalizedImg, objects, searchScaleFactor, minNeighbors, flags, minFeatureSize); // Enlarge the results if the image was temporarily shrunk before detection. if (img.cols > scaledWidth) { for (int i = 0; i < (int)objects.size(); i++ ) { objects[i].x = cvRound(objects[i].x * scale); objects[i].y = cvRound(objects[i].y * scale); objects[i].width = cvRound(objects[i].width * scale); objects[i].height = cvRound(objects[i].height * scale); } } // Make sure the object is completely within the image, in case it was on a border. for (int i = 0; i < (int)objects.size(); i++ ) { if (objects[i].x < 0) objects[i].x = 0; if (objects[i].y < 0) objects[i].y = 0; if (objects[i].x + objects[i].width > img.cols) objects[i].x = img.cols - objects[i].width; if (objects[i].y + objects[i].height > img.rows) objects[i].y = img.rows - objects[i].height; } // Return with the detected face rectangles stored in "objects". } // Search for just a single object in the image, such as the largest face, storing the result into 'largestObject'. // Can use Haar cascades or LBP cascades for Face Detection, or even eye, mouth, or car detection. // Input is temporarily shrunk to 'scaledWidth' for much faster detection, since 200 is enough to find faces. // Note: detectLargestObject() should be faster than detectManyObjects(). void detectLargestObject(const Mat &img, CascadeClassifier &cascade, Rect &largestObject, int scaledWidth) { // Only search for just 1 object (the biggest in the image). int flags = CASCADE_FIND_BIGGEST_OBJECT;// | CASCADE_DO_ROUGH_SEARCH; // Smallest object size. Size minFeatureSize = Size(20, 20); // How detailed should the search be. Must be larger than 1.0. float searchScaleFactor = 1.1f; // How much the detections should be filtered out. This should depend on how bad false detections are to your system. // minNeighbors=2 means lots of good+bad detections, and minNeighbors=6 means only good detections are given but some are missed. int minNeighbors = 4; // Perform Object or Face Detection, looking for just 1 object (the biggest in the image). vector objects; detectObjectsCustom(img, cascade, objects, scaledWidth, flags, minFeatureSize, searchScaleFactor, minNeighbors); if (objects.size() > 0) { // Return the only detected object. largestObject = (Rect)objects.at(0); } else { // Return an invalid rect. largestObject = Rect(-1,-1,-1,-1); } } // Search for many objects in the image, such as all the faces, storing the results into 'objects'. // Can use Haar cascades or LBP cascades for Face Detection, or even eye, mouth, or car detection. // Input is temporarily shrunk to 'scaledWidth' for much faster detection, since 200 is enough to find faces. // Note: detectLargestObject() should be faster than detectManyObjects(). void detectManyObjects(const Mat &img, CascadeClassifier &cascade, vector &objects, int scaledWidth) { // Search for many objects in the one image. int flags = CASCADE_SCALE_IMAGE; // Smallest object size. Size minFeatureSize = Size(20, 20); // How detailed should the search be. Must be larger than 1.0. float searchScaleFactor = 1.1f; // How much the detections should be filtered out. This should depend on how bad false detections are to your system. // minNeighbors=2 means lots of good+bad detections, and minNeighbors=6 means only good detections are given but some are missed. int minNeighbors = 4; // Perform Object or Face Detection, looking for many objects in the one image. detectObjectsCustom(img, cascade, objects, scaledWidth, flags, minFeatureSize, searchScaleFactor, minNeighbors); }