@ -3,6 +3,7 @@
# include "opencv2/imgproc/imgproc.hpp"
# include <iostream>
# include <iterator>
# include <stdio.h>
using namespace std ;
@ -11,36 +12,41 @@ using namespace cv;
static void help ( )
{
cout < < " \n This program demonstrates the cascade recognizer. Now you can use Haar or LBP features. \n "
" This classifier can recognize many ~rigid objects, it's most known use is for faces. \n "
" This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained. \n "
" It's most known use is for faces. \n "
" Usage: \n "
" ./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face] \n "
" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]] \n "
" [--scale=<image scale greater or equal to 1, try 1.3 for example> \n "
" [--scale=<image scale greater or equal to 1, try 1.3 for example>] \n "
" [--try-flip] \n "
" [filename|camera_index] \n \n "
" see facedetect.cmd for one call: \n "
" ./facedetect --cascade= \" ../../data/haarcascades/haarcascade_frontalface_alt.xml \" --nested-cascade= \" ../../data/haarcascades/haarcascade_eye.xml \" --scale=1.3 \n "
" Hit any key to quit. \n "
" Using OpenCV version " < < CV_VERSION < < " \n " < < endl ;
" ./facedetect --cascade= \" ../../data/haarcascades/haarcascade_frontalface_alt.xml \" --nested-cascade= \" ../../data/haarcascades/haarcascade_eye.xml \" --scale=1.3 \n \n "
" During execution: \n \t Hit any key to quit. \n "
" \t Using OpenCV version " < < CV_VERSION < < " \n " < < endl ;
}
void detectAndDraw ( Mat & img ,
CascadeClassifier & cascade , CascadeClassifier & nestedCascade ,
double scale ) ;
void detectAndDraw ( Mat & img , CascadeClassifier & cascade ,
CascadeClassifier & nestedCascade ,
double scale , bool tryflip ) ;
S tring cascadeName = " ../../data/haarcascades/haarcascade_frontalface_alt.xml " ;
S tring nestedCascadeName = " ../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml " ;
s tring cascadeName = " ../../data/haarcascades/haarcascade_frontalface_alt.xml " ;
s tring nestedCascadeName = " ../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml " ;
int main ( int argc , const char * * argv )
{
CvCapture * capture = 0 ;
Mat frame , frameCopy , image ;
const S tring scaleOpt = " --scale= " ;
const s tring scaleOpt = " --scale= " ;
size_t scaleOptLen = scaleOpt . length ( ) ;
const S tring cascadeOpt = " --cascade= " ;
const s tring cascadeOpt = " --cascade= " ;
size_t cascadeOptLen = cascadeOpt . length ( ) ;
const S tring nestedCascadeOpt = " --nested-cascade " ;
const s tring nestedCascadeOpt = " --nested-cascade " ;
size_t nestedCascadeOptLen = nestedCascadeOpt . length ( ) ;
String inputName ;
const string tryFlipOpt = " --try-flip " ;
size_t tryFlipOptLen = tryFlipOpt . length ( ) ;
string inputName ;
bool tryflip = false ;
help ( ) ;
@ -68,6 +74,11 @@ int main( int argc, const char** argv )
scale = 1 ;
cout < < " from which we read scale = " < < scale < < endl ;
}
else if ( tryFlipOpt . compare ( 0 , tryFlipOptLen , argv [ i ] , tryFlipOptLen ) = = 0 )
{
tryflip = true ;
cout < < " will try to flip image horizontally to detect assymetric objects \n " ;
}
else if ( argv [ i ] [ 0 ] = = ' - ' )
{
cerr < < " WARNING: Unknown option %s " < < argv [ i ] < < endl ;
@ -79,10 +90,7 @@ int main( int argc, const char** argv )
if ( ! cascade . load ( cascadeName ) )
{
cerr < < " ERROR: Could not load classifier cascade " < < endl ;
cerr < < " Usage: facedetect [--cascade=<cascade_path>] \n "
" [--nested-cascade[=nested_cascade_path]] \n "
" [--scale[=<image scale> \n "
" [filename|camera_index] \n " < < endl ;
help ( ) ;
return - 1 ;
}
@ -123,7 +131,7 @@ int main( int argc, const char** argv )
else
flip ( frame , frameCopy , 0 ) ;
detectAndDraw ( frameCopy , cascade , nestedCascade , scale ) ;
detectAndDraw ( frameCopy , cascade , nestedCascade , scale , tryflip ) ;
if ( waitKey ( 10 ) > = 0 )
goto _cleanup_ ;
@ -139,7 +147,7 @@ _cleanup_:
cout < < " In image read " < < endl ;
if ( ! image . empty ( ) )
{
detectAndDraw ( image , cascade , nestedCascade , scale ) ;
detectAndDraw ( image , cascade , nestedCascade , scale , tryflip ) ;
waitKey ( 0 ) ;
}
else if ( ! inputName . empty ( ) )
@ -160,7 +168,7 @@ _cleanup_:
image = imread ( buf , 1 ) ;
if ( ! image . empty ( ) )
{
detectAndDraw ( image , cascade , nestedCascade , scale ) ;
detectAndDraw ( image , cascade , nestedCascade , scale , tryflip ) ;
c = waitKey ( 0 ) ;
if ( c = = 27 | | c = = ' q ' | | c = = ' Q ' )
break ;
@ -180,13 +188,13 @@ _cleanup_:
return 0 ;
}
void detectAndDraw ( Mat & img ,
CascadeClassifier & cascade , CascadeClassifier & nestedCascade ,
double scale )
void detectAndDraw ( Mat & img , CascadeClassifier & cascade ,
CascadeClassifier & nestedCascade ,
double scale , bool tryflip )
{
int i = 0 ;
double t = 0 ;
vector < Rect > faces ;
vector < Rect > faces , faces2 ;
const static Scalar colors [ ] = { CV_RGB ( 0 , 0 , 255 ) ,
CV_RGB ( 0 , 128 , 255 ) ,
CV_RGB ( 0 , 255 , 255 ) ,
@ -209,6 +217,21 @@ void detectAndDraw( Mat& img,
| CV_HAAR_SCALE_IMAGE
,
Size ( 30 , 30 ) ) ;
if ( tryflip )
{
flip ( smallImg , smallImg , 1 ) ;
cascade . detectMultiScale ( smallImg , faces2 ,
1.1 , 2 , 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
| CV_HAAR_SCALE_IMAGE
,
Size ( 30 , 30 ) ) ;
for ( vector < Rect > : : const_iterator r = faces2 . begin ( ) ; r ! = faces2 . end ( ) ; r + + )
{
faces . push_back ( Rect ( smallImg . cols - r - > x - r - > width , r - > y , r - > width , r - > height ) ) ;
}
}
t = ( double ) cvGetTickCount ( ) - t ;
printf ( " detection time = %g ms \n " , t / ( ( double ) cvGetTickFrequency ( ) * 1000. ) ) ;
for ( vector < Rect > : : const_iterator r = faces . begin ( ) ; r ! = faces . end ( ) ; r + + , i + + )
@ -218,10 +241,19 @@ void detectAndDraw( Mat& img,
Point center ;
Scalar color = colors [ i % 8 ] ;
int radius ;
double aspect_ratio = ( double ) r - > width / r - > height ;
if ( 0.75 < aspect_ratio & & aspect_ratio < 1.3 )
{
center . x = cvRound ( ( r - > x + r - > width * 0.5 ) * scale ) ;
center . y = cvRound ( ( r - > y + r - > height * 0.5 ) * scale ) ;
radius = cvRound ( ( r - > width + r - > height ) * 0.25 * scale ) ;
circle ( img , center , radius , color , 3 , 8 , 0 ) ;
}
else
rectangle ( img , cvPoint ( cvRound ( r - > x * scale ) , cvRound ( r - > y * scale ) ) ,
cvPoint ( cvRound ( ( r - > x + r - > width - 1 ) * scale ) , cvRound ( ( r - > y + r - > height - 1 ) * scale ) ) ,
color , 3 , 8 , 0 ) ;
if ( nestedCascade . empty ( ) )
continue ;
smallImgROI = smallImg ( * r ) ;