Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/samples/tapi/ufacedetect.cpp
16337 views
1
#include "opencv2/objdetect.hpp"
2
#include "opencv2/highgui.hpp"
3
#include "opencv2/imgproc.hpp"
4
#include "opencv2/core/ocl.hpp"
5
#include <iostream>
6
7
using namespace std;
8
using namespace cv;
9
10
static void help()
11
{
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"
15
"Usage:\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"
19
" [--try-flip]\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;
25
}
26
27
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
28
CascadeClassifier& nestedCascade,
29
double scale, bool tryflip );
30
31
string cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
32
string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
33
34
int main( int argc, const char** argv )
35
{
36
VideoCapture capture;
37
UMat frame, image;
38
Mat canvas;
39
40
string inputName;
41
bool tryflip;
42
43
CascadeClassifier cascade, nestedCascade;
44
double scale;
45
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||}"
50
);
51
if (parser.has("help"))
52
{
53
help();
54
return 0;
55
}
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");
61
if ( !parser.check())
62
{
63
parser.printErrors();
64
help();
65
return -1;
66
}
67
68
if ( !nestedCascade.load( nestedCascadeName ) )
69
cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
70
if( !cascade.load( cascadeName ) )
71
{
72
cerr << "ERROR: Could not load classifier cascade" << endl;
73
help();
74
return -1;
75
}
76
77
cout << "old cascade: " << (cascade.isOldFormatCascade() ? "TRUE" : "FALSE") << endl;
78
79
if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) )
80
{
81
int camera = inputName.empty() ? 0 : inputName[0] - '0';
82
if(!capture.open(camera))
83
cout << "Capture from camera #" << camera << " didn't work" << endl;
84
}
85
else
86
{
87
if( inputName.empty() )
88
inputName = "../data/lena.jpg";
89
image = imread( inputName, 1 ).getUMat(ACCESS_READ);
90
if( image.empty() )
91
{
92
if(!capture.open( inputName ))
93
cout << "Could not read " << inputName << endl;
94
}
95
}
96
97
if( capture.isOpened() )
98
{
99
cout << "Video capturing has been started ..." << endl;
100
for(;;)
101
{
102
capture >> frame;
103
if( frame.empty() )
104
break;
105
106
detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip );
107
108
char c = (char)waitKey(10);
109
if( c == 27 || c == 'q' || c == 'Q' )
110
break;
111
}
112
}
113
else
114
{
115
cout << "Detecting face(s) in " << inputName << endl;
116
if( !image.empty() )
117
{
118
detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
119
waitKey(0);
120
}
121
else if( !inputName.empty() )
122
{
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" );
126
if( f )
127
{
128
char buf[1000+1];
129
while( fgets( buf, 1000, f ) )
130
{
131
int len = (int)strlen(buf);
132
while( len > 0 && isspace(buf[len-1]) )
133
len--;
134
buf[len] = '\0';
135
cout << "file " << buf << endl;
136
image = imread( buf, 1 ).getUMat(ACCESS_READ);
137
if( !image.empty() )
138
{
139
detectAndDraw( image, canvas, cascade, nestedCascade, scale, tryflip );
140
char c = (char)waitKey(0);
141
if( c == 27 || c == 'q' || c == 'Q' )
142
break;
143
}
144
else
145
{
146
cerr << "Aw snap, couldn't read image " << buf << endl;
147
}
148
}
149
fclose(f);
150
}
151
}
152
}
153
154
return 0;
155
}
156
157
void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade,
158
CascadeClassifier& nestedCascade,
159
double scale, bool tryflip )
160
{
161
double t = 0;
162
vector<Rect> faces, faces2;
163
const static Scalar colors[] =
164
{
165
Scalar(255,0,0),
166
Scalar(255,128,0),
167
Scalar(255,255,0),
168
Scalar(0,255,0),
169
Scalar(0,128,255),
170
Scalar(0,255,255),
171
Scalar(0,0,255),
172
Scalar(255,0,255)
173
};
174
static UMat gray, smallImg;
175
176
t = (double)getTickCount();
177
178
cvtColor( img, gray, COLOR_BGR2GRAY );
179
double fx = 1 / scale;
180
resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR_EXACT );
181
equalizeHist( smallImg, smallImg );
182
183
cascade.detectMultiScale( smallImg, faces,
184
1.1, 3, 0
185
//|CASCADE_FIND_BIGGEST_OBJECT
186
//|CASCADE_DO_ROUGH_SEARCH
187
|CASCADE_SCALE_IMAGE,
188
Size(30, 30) );
189
if( tryflip )
190
{
191
flip(smallImg, smallImg, 1);
192
cascade.detectMultiScale( smallImg, faces2,
193
1.1, 2, 0
194
//|CASCADE_FIND_BIGGEST_OBJECT
195
//|CASCADE_DO_ROUGH_SEARCH
196
|CASCADE_SCALE_IMAGE,
197
Size(30, 30) );
198
for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r )
199
{
200
faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
201
}
202
}
203
t = (double)getTickCount() - t;
204
img.copyTo(canvas);
205
206
double fps = getTickFrequency()/t;
207
static double avgfps = 0;
208
static int nframes = 0;
209
nframes++;
210
double alpha = nframes > 50 ? 0.01 : 1./nframes;
211
avgfps = avgfps*(1-alpha) + fps*alpha;
212
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);
215
216
for ( size_t i = 0; i < faces.size(); i++ )
217
{
218
Rect r = faces[i];
219
vector<Rect> nestedObjects;
220
Point center;
221
Scalar color = colors[i%8];
222
int radius;
223
224
double aspect_ratio = (double)r.width/r.height;
225
if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
226
{
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 );
231
}
232
else
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)),
235
color, 3, 8, 0);
236
if( nestedCascade.empty() )
237
continue;
238
UMat smallImgROI = smallImg(r);
239
nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
240
1.1, 2, 0
241
//|CASCADE_FIND_BIGGEST_OBJECT
242
//|CASCADE_DO_ROUGH_SEARCH
243
//|CASCADE_DO_CANNY_PRUNING
244
|CASCADE_SCALE_IMAGE,
245
Size(30, 30) );
246
247
for ( size_t j = 0; j < nestedObjects.size(); j++ )
248
{
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 );
254
}
255
}
256
imshow( "result", canvas );
257
}
258
259