1 #include "opencv2/objdetect.hpp"
2 #include "opencv2/highgui.hpp"
3 #include "opencv2/imgproc.hpp"
4 #include "opencv2/core/utility.hpp"
5 #include "opencv2/core/ocl.hpp"
17 cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
18 "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n"
19 "It's most known use is for faces.\n"
21 "./facedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
22 " [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
23 " [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"
25 " [filename|camera_index]\n\n"
26 "see facedetect.cmd for one call:\n"
27 "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3\n\n"
28 "During execution:\n\tHit any key to quit.\n"
29 "\tUsing OpenCV version " << CV_VERSION << "\n" << endl;
32 void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
33 CascadeClassifier& nestedCascade,
34 double scale, bool tryflip );
36 string cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
37 string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
39 int main( int argc, const char** argv )
44 const string scaleOpt = "--scale=";
45 size_t scaleOptLen = scaleOpt.length();
46 const string cascadeOpt = "--cascade=";
47 size_t cascadeOptLen = cascadeOpt.length();
48 const string nestedCascadeOpt = "--nested-cascade";
49 size_t nestedCascadeOptLen = nestedCascadeOpt.length();
50 const string tryFlipOpt = "--try-flip";
51 size_t tryFlipOptLen = tryFlipOpt.length();
57 CascadeClassifier cascade, nestedCascade;
60 for( int i = 1; i < argc; i++ )
62 cout << "Processing " << i << " " << argv[i] << endl;
63 if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 )
65 cascadeName.assign( argv[i] + cascadeOptLen );
66 cout << " from which we have cascadeName= " << cascadeName << endl;
68 else if( nestedCascadeOpt.compare( 0, nestedCascadeOptLen, argv[i], nestedCascadeOptLen ) == 0 )
70 if( argv[i][nestedCascadeOpt.length()] == '=' )
71 nestedCascadeName.assign( argv[i] + nestedCascadeOpt.length() + 1 );
72 if( !nestedCascade.load( nestedCascadeName ) )
73 cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
75 else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 )
77 if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale > 1 )
79 cout << " from which we read scale = " << scale << endl;
81 else if( tryFlipOpt.compare( 0, tryFlipOptLen, argv[i], tryFlipOptLen ) == 0 )
84 cout << " will try to flip image horizontally to detect assymetric objects\n";
86 else if( argv[i][0] == '-' )
88 cerr << "WARNING: Unknown option %s" << argv[i] << endl;
94 if( !cascade.load( cascadeName ) )
96 cerr << "ERROR: Could not load classifier cascade" << endl;
101 if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
103 int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0';
105 cout << "Capture from camera #" << c << " didn't work" << endl;
109 if( inputName.empty() )
110 inputName = "lena.jpg";
111 image = imread( inputName, 1 ).getUMat(ACCESS_READ);
114 if(!capture.open( inputName ))
115 cout << "Could not read " << inputName << endl;
119 namedWindow( "result", 1 );
121 if( capture.isOpened() )
123 cout << "Video capturing has been started ..." << endl;
130 detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip );
132 if( waitKey( 10 ) >= 0 )
138 cout << "Detecting face(s) in " << inputName << endl;
141 detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
144 else if( !inputName.empty() )
146 /* assume it is a text file containing the
147 list of the image filenames to be processed - one per line */
148 FILE* f = fopen( inputName.c_str(), "rt" );
152 while( fgets( buf, 1000, f ) )
154 int len = (int)strlen(buf), c;
155 while( len > 0 && isspace(buf[len-1]) )
158 cout << "file " << buf << endl;
159 image = imread( buf, 1 ).getUMat(ACCESS_READ);
162 detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
164 if( c == 27 || c == 'q' || c == 'Q' )
169 cerr << "Aw snap, couldn't read image " << buf << endl;
180 void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
181 CascadeClassifier& nestedCascade,
182 double scale0, bool tryflip )
185 double t = 0, scale=1;
186 vector<Rect> faces, faces2;
187 const static Scalar colors[] =
198 static UMat gray, smallImg;
200 t = (double)getTickCount();
202 cvtColor( img, gray, COLOR_BGR2GRAY );
203 resize( gray, smallImg, Size(), scale0, scale0, INTER_LINEAR );
204 cvtColor(smallImg, canvas, COLOR_GRAY2BGR);
205 equalizeHist( smallImg, smallImg );
207 cascade.detectMultiScale( smallImg, faces,
209 //|CASCADE_FIND_BIGGEST_OBJECT
210 //|CASCADE_DO_ROUGH_SEARCH
216 flip(smallImg, smallImg, 1);
217 cascade.detectMultiScale( smallImg, faces2,
219 //|CASCADE_FIND_BIGGEST_OBJECT
220 //|CASCADE_DO_ROUGH_SEARCH
224 for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++ )
226 faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
229 t = (double)getTickCount() - t;
230 cvtColor(smallImg, canvas, COLOR_GRAY2BGR);
232 double fps = getTickFrequency()/t;
234 putText(canvas, format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", fps), Point(250, 50),
235 FONT_HERSHEY_SIMPLEX, 1, Scalar(0,255,0), 3);
237 for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
239 vector<Rect> nestedObjects;
241 Scalar color = colors[i%8];
244 double aspect_ratio = (double)r->width/r->height;
245 if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
247 center.x = cvRound((r->x + r->width*0.5)*scale);
248 center.y = cvRound((r->y + r->height*0.5)*scale);
249 radius = cvRound((r->width + r->height)*0.25*scale);
250 circle( canvas, center, radius, color, 3, 8, 0 );
253 rectangle( canvas, Point(cvRound(r->x*scale), cvRound(r->y*scale)),
254 Point(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),
256 if( nestedCascade.empty() )
258 UMat smallImgROI = smallImg(*r);
259 nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
261 //|CASCADE_FIND_BIGGEST_OBJECT
262 //|CASCADE_DO_ROUGH_SEARCH
263 //|CASCADE_DO_CANNY_PRUNING
267 for( vector<Rect>::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ )
269 center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
270 center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
271 radius = cvRound((nr->width + nr->height)*0.25*scale);
272 circle( canvas, center, radius, color, 3, 8, 0 );
275 imshow( "result", canvas );