Merge pull request #1263 from abidrahmank:pyCLAHE_24
[profile/ivi/opencv.git] / samples / ocl / facedetect.cpp
1 #include "opencv2/objdetect/objdetect.hpp"
2 #include "opencv2/highgui/highgui.hpp"
3 #include "opencv2/imgproc/imgproc.hpp"
4 #include "opencv2/ocl/ocl.hpp"
5 #include <iostream>
6 #include <stdio.h>
7
8 using namespace std;
9 using namespace cv;
10 #define LOOP_NUM 10
11
12 const static Scalar colors[] =  { CV_RGB(0,0,255),
13                                   CV_RGB(0,128,255),
14                                   CV_RGB(0,255,255),
15                                   CV_RGB(0,255,0),
16                                   CV_RGB(255,128,0),
17                                   CV_RGB(255,255,0),
18                                   CV_RGB(255,0,0),
19                                   CV_RGB(255,0,255)
20                                 } ;
21
22
23 int64 work_begin = 0;
24 int64 work_end = 0;
25 string outputName;
26
27 static void workBegin()
28 {
29     work_begin = getTickCount();
30 }
31 static void workEnd()
32 {
33     work_end += (getTickCount() - work_begin);
34 }
35 static double getTime()
36 {
37     return work_end /((double)cvGetTickFrequency() * 1000.);
38 }
39
40
41 void detect( Mat& img, vector<Rect>& faces,
42              ocl::OclCascadeClassifierBuf& cascade,
43              double scale, bool calTime);
44
45
46 void detectCPU( Mat& img, vector<Rect>& faces,
47                 CascadeClassifier& cascade,
48                 double scale, bool calTime);
49
50
51 void Draw(Mat& img, vector<Rect>& faces, double scale);
52
53
54 // This function test if gpu_rst matches cpu_rst.
55 // If the two vectors are not equal, it will return the difference in vector size
56 // Else if will return (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels)
57 double checkRectSimilarity(Size sz, vector<Rect>& cpu_rst, vector<Rect>& gpu_rst);
58
59
60 int main( int argc, const char** argv )
61 {
62     const char* keys =
63         "{ h | help       | false       | print help message }"
64         "{ i | input      |             | specify input image }"
65         "{ t | template   | haarcascade_frontalface_alt.xml |"
66         " specify template file path }"
67         "{ c | scale      |   1.0       | scale image }"
68         "{ s | use_cpu    | false       | use cpu or gpu to process the image }"
69         "{ o | output     | facedetect_output.jpg  |"
70         " specify output image save path(only works when input is images) }";
71
72     CommandLineParser cmd(argc, argv, keys);
73     if (cmd.get<bool>("help"))
74     {
75         cout << "Avaible options:" << endl;
76         cmd.printParams();
77         return 0;
78     }
79     CvCapture* capture = 0;
80     Mat frame, frameCopy, image;
81
82     bool useCPU = cmd.get<bool>("s");
83     string inputName = cmd.get<string>("i");
84     outputName = cmd.get<string>("o");
85     string cascadeName = cmd.get<string>("t");
86     double scale = cmd.get<double>("c");
87     ocl::OclCascadeClassifierBuf cascade;
88     CascadeClassifier  cpu_cascade;
89
90     if( !cascade.load( cascadeName ) || !cpu_cascade.load(cascadeName) )
91     {
92         cerr << "ERROR: Could not load classifier cascade" << endl;
93         return -1;
94     }
95
96     if( inputName.empty() )
97     {
98         capture = cvCaptureFromCAM(0);
99         if(!capture)
100             cout << "Capture from CAM 0 didn't work" << endl;
101     }
102     else if( inputName.size() )
103     {
104         image = imread( inputName, 1 );
105         if( image.empty() )
106         {
107             capture = cvCaptureFromAVI( inputName.c_str() );
108             if(!capture)
109                 cout << "Capture from AVI didn't work" << endl;
110             return -1;
111         }
112     }
113     else
114     {
115         image = imread( "lena.jpg", 1 );
116         if(image.empty())
117             cout << "Couldn't read lena.jpg" << endl;
118         return -1;
119     }
120
121
122     cvNamedWindow( "result", 1 );
123     vector<ocl::Info> oclinfo;
124     int devnums = ocl::getDevice(oclinfo);
125     if( devnums < 1 )
126     {
127         std::cout << "no device found\n";
128         return -1;
129     }
130     //if you want to use undefault device, set it here
131     //setDevice(oclinfo[0]);
132     ocl::setBinpath("./");
133     if( capture )
134     {
135         cout << "In capture ..." << endl;
136         for(;;)
137         {
138             IplImage* iplImg = cvQueryFrame( capture );
139             frame = iplImg;
140             vector<Rect> faces;
141             if( frame.empty() )
142                 break;
143             if( iplImg->origin == IPL_ORIGIN_TL )
144                 frame.copyTo( frameCopy );
145             else
146                 flip( frame, frameCopy, 0 );
147             if(useCPU)
148             {
149                 detectCPU(frameCopy, faces, cpu_cascade, scale, false);
150             }
151             else
152             {
153                 detect(frameCopy, faces, cascade, scale, false);
154             }
155             Draw(frameCopy, faces, scale);
156             if( waitKey( 10 ) >= 0 )
157                 goto _cleanup_;
158         }
159
160
161         waitKey(0);
162
163
164 _cleanup_:
165         cvReleaseCapture( &capture );
166     }
167     else
168     {
169         cout << "In image read" << endl;
170         vector<Rect> faces;
171         vector<Rect> ref_rst;
172         double accuracy = 0.;
173         for(int i = 0; i <= LOOP_NUM; i ++)
174         {
175             cout << "loop" << i << endl;
176             if(useCPU)
177             {
178                 detectCPU(image, faces, cpu_cascade, scale, i==0?false:true);
179             }
180             else
181             {
182                 detect(image, faces, cascade, scale, i==0?false:true);
183                 if(i == 0)
184                 {
185                     detectCPU(image, ref_rst, cpu_cascade, scale, false);
186                     accuracy = checkRectSimilarity(image.size(), ref_rst, faces);
187                 }
188             }
189             if (i == LOOP_NUM)
190             {
191                 if (useCPU)
192                     cout << "average CPU time (noCamera) : ";
193                 else
194                     cout << "average GPU time (noCamera) : ";
195                 cout << getTime() / LOOP_NUM << " ms" << endl;
196                 cout << "accuracy value: " << accuracy <<endl;
197             }
198         }
199         Draw(image, faces, scale);
200         waitKey(0);
201     }
202
203     cvDestroyWindow("result");
204     return 0;
205 }
206
207 void detect( Mat& img, vector<Rect>& faces,
208              ocl::OclCascadeClassifierBuf& cascade,
209              double scale, bool calTime)
210 {
211     ocl::oclMat image(img);
212     ocl::oclMat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
213     if(calTime) workBegin();
214     ocl::cvtColor( image, gray, CV_BGR2GRAY );
215     ocl::resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
216     ocl::equalizeHist( smallImg, smallImg );
217
218     cascade.detectMultiScale( smallImg, faces, 1.1,
219                               3, 0
220                               |CV_HAAR_SCALE_IMAGE
221                               , Size(30,30), Size(0, 0) );
222     if(calTime) workEnd();
223 }
224
225
226 void detectCPU( Mat& img, vector<Rect>& faces,
227                 CascadeClassifier& cascade,
228                 double scale, bool calTime)
229 {
230     if(calTime) workBegin();
231     Mat cpu_gray, cpu_smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
232     cvtColor(img, cpu_gray, CV_BGR2GRAY);
233     resize(cpu_gray, cpu_smallImg, cpu_smallImg.size(), 0, 0, INTER_LINEAR);
234     equalizeHist(cpu_smallImg, cpu_smallImg);
235     cascade.detectMultiScale(cpu_smallImg, faces, 1.1,
236                              3, 0 | CV_HAAR_SCALE_IMAGE,
237                              Size(30, 30), Size(0, 0));
238     if(calTime) workEnd();
239 }
240
241
242 void Draw(Mat& img, vector<Rect>& faces, double scale)
243 {
244     int i = 0;
245     for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
246     {
247         Point center;
248         Scalar color = colors[i%8];
249         int radius;
250         center.x = cvRound((r->x + r->width*0.5)*scale);
251         center.y = cvRound((r->y + r->height*0.5)*scale);
252         radius = cvRound((r->width + r->height)*0.25*scale);
253         circle( img, center, radius, color, 3, 8, 0 );
254     }
255     imwrite( outputName, img );
256     if(abs(scale-1.0)>.001)
257     {
258         resize(img, img, Size((int)(img.cols/scale), (int)(img.rows/scale)));
259     }
260     imshow( "result", img );
261     
262 }
263
264
265 double checkRectSimilarity(Size sz, vector<Rect>& ob1, vector<Rect>& ob2)
266 {
267     double final_test_result = 0.0;
268     size_t sz1 = ob1.size();
269     size_t sz2 = ob2.size();
270
271     if(sz1 != sz2)
272     {
273         return sz1 > sz2 ? (double)(sz1 - sz2) : (double)(sz2 - sz1);
274     }
275     else
276     {
277         if(sz1==0 && sz2==0)
278             return 0;
279         Mat cpu_result(sz, CV_8UC1);
280         cpu_result.setTo(0);
281
282         for(vector<Rect>::const_iterator r = ob1.begin(); r != ob1.end(); r++)
283         {
284             Mat cpu_result_roi(cpu_result, *r);
285             cpu_result_roi.setTo(1);
286             cpu_result.copyTo(cpu_result);
287         }
288         int cpu_area = countNonZero(cpu_result > 0);
289
290
291         Mat gpu_result(sz, CV_8UC1);
292         gpu_result.setTo(0);
293         for(vector<Rect>::const_iterator r2 = ob2.begin(); r2 != ob2.end(); r2++)
294         {
295             cv::Mat gpu_result_roi(gpu_result, *r2);
296             gpu_result_roi.setTo(1);
297             gpu_result.copyTo(gpu_result);
298         }
299
300         Mat result_;
301         multiply(cpu_result, gpu_result, result_);
302         int result = countNonZero(result_ > 0);
303         if(cpu_area!=0 && result!=0)
304             final_test_result = 1.0 - (double)result/(double)cpu_area;
305         else if(cpu_area==0 && result!=0)
306             final_test_result = -1;
307     }
308     return final_test_result;
309 }