1
#include "opencv2/objdetect.hpp"
2
#include "opencv2/highgui.hpp"
3
#include "opencv2/imgproc.hpp"
4
#include "opencv2/core/ocl.hpp"
12
cout << "\nThis program demonstrates the cascade recognizer. Now you can use Haar or LBP features.\n"
13
"This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n"
14
"It's most known use is for faces.\n"
16
"./ufacedetect [--cascade=<cascade_path> this is the primary trained classifier such as frontal face]\n"
17
" [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n"
18
" [--scale=<image scale greater or equal to 1, try 1.3 for example>]\n"
20
" [filename|camera_index]\n\n"
21
"see facedetect.cmd for one call:\n"
22
"./ufacedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n"
23
"During execution:\n\tHit any key to quit.\n"
24
"\tUsing OpenCV version " << CV_VERSION << "\n" << endl;
27
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
28
CascadeClassifier& nestedCascade,
29
double scale, bool tryflip );
31
string cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
32
string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
34
int main( int argc, const char** argv )
43
CascadeClassifier cascade, nestedCascade;
46
cv::CommandLineParser parser(argc, argv,
47
"{cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}"
48
"{nested-cascade|../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml|}"
49
"{help h ||}{scale|1|}{try-flip||}{@filename||}"
51
if (parser.has("help"))
56
cascadeName = parser.get<string>("cascade");
57
nestedCascadeName = parser.get<string>("nested-cascade");
58
scale = parser.get<double>("scale");
59
tryflip = parser.has("try-flip");
60
inputName = parser.get<string>("@filename");
68
if ( !nestedCascade.load( nestedCascadeName ) )
69
cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
70
if( !cascade.load( cascadeName ) )
72
cerr << "ERROR: Could not load classifier cascade" << endl;
77
cout << "old cascade: " << (cascade.isOldFormatCascade() ? "TRUE" : "FALSE") << endl;
79
if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) )
81
int c = inputName.empty() ? 0 : inputName[0] - '0';
83
cout << "Capture from camera #" << c << " didn't work" << endl;
87
if( inputName.empty() )
88
inputName = "../data/lena.jpg";
89
image = imread( inputName, 1 ).getUMat(ACCESS_READ);
92
if(!capture.open( inputName ))
93
cout << "Could not read " << inputName << endl;
97
if( capture.isOpened() )
99
cout << "Video capturing has been started ..." << endl;
106
detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip );
109
if( c == 27 || c == 'q' || c == 'Q' )
115
cout << "Detecting face(s) in " << inputName << endl;
118
detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
121
else if( !inputName.empty() )
123
/* assume it is a text file containing the
124
list of the image filenames to be processed - one per line */
125
FILE* f = fopen( inputName.c_str(), "rt" );
129
while( fgets( buf, 1000, f ) )
131
int len = (int)strlen(buf), c;
132
while( len > 0 && isspace(buf[len-1]) )
135
cout << "file " << buf << endl;
136
image = imread( buf, 1 ).getUMat(ACCESS_READ);
139
detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
141
if( c == 27 || c == 'q' || c == 'Q' )
146
cerr << "Aw snap, couldn't read image " << buf << endl;
157
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
158
CascadeClassifier& nestedCascade,
159
double scale, bool tryflip )
162
vector<Rect> faces, faces2;
163
const static Scalar colors[] =
174
static UMat gray, smallImg;
176
t = (double)getTickCount();
178
cvtColor( img, gray, COLOR_BGR2GRAY );
179
double fx = 1 / scale;
180
resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );
181
equalizeHist( smallImg, smallImg );
183
cascade.detectMultiScale( smallImg, faces,
185
//|CASCADE_FIND_BIGGEST_OBJECT
186
//|CASCADE_DO_ROUGH_SEARCH
187
|CASCADE_SCALE_IMAGE,
191
flip(smallImg, smallImg, 1);
192
cascade.detectMultiScale( smallImg, faces2,
194
//|CASCADE_FIND_BIGGEST_OBJECT
195
//|CASCADE_DO_ROUGH_SEARCH
196
|CASCADE_SCALE_IMAGE,
198
for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); r++ )
200
faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
203
t = (double)getTickCount() - t;
206
double fps = getTickFrequency()/t;
207
static double avgfps = 0;
208
static int nframes = 0;
210
double alpha = nframes > 50 ? 0.01 : 1./nframes;
211
avgfps = avgfps*(1-alpha) + fps*alpha;
213
putText(canvas, format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", avgfps), Point(50, 30),
214
FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 2);
216
for ( size_t i = 0; i < faces.size(); i++ )
219
vector<Rect> nestedObjects;
221
Scalar color = colors[i%8];
224
double aspect_ratio = (double)r.width/r.height;
225
if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
227
center.x = cvRound((r.x + r.width*0.5)*scale);
228
center.y = cvRound((r.y + r.height*0.5)*scale);
229
radius = cvRound((r.width + r.height)*0.25*scale);
230
circle( canvas, center, radius, color, 3, 8, 0 );
233
rectangle( canvas, Point(cvRound(r.x*scale), cvRound(r.y*scale)),
234
Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
236
if( nestedCascade.empty() )
238
UMat smallImgROI = smallImg(r);
239
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
241
//|CASCADE_FIND_BIGGEST_OBJECT
242
//|CASCADE_DO_ROUGH_SEARCH
243
//|CASCADE_DO_CANNY_PRUNING
244
|CASCADE_SCALE_IMAGE,
247
for ( size_t j = 0; j < nestedObjects.size(); j++ )
249
Rect nr = nestedObjects[j];
250
center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
251
center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
252
radius = cvRound((nr.width + nr.height)*0.25*scale);
253
circle( canvas, center, radius, color, 3, 8, 0 );
256
imshow( "result", canvas );