some samples updated according to new CommandLineParser class
[profile/ivi/opencv.git] / samples / c / adaptiveskindetector.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
4 //\r
5 //  By downloading, copying, installing or using the software you agree to this license.\r
6 //  If you do not agree to this license, do not download, install, copy or use the software.\r
7 //\r
8 // Copyright (C) 2009, Farhad Dadgostar\r
9 // Intel Corporation and third party copyrights are property of their respective owners.\r
10 //\r
11 // Redistribution and use in source and binary forms, with or without modification,\r
12 // are permitted provided that the following conditions are met:\r
13 //\r
14 //   * Redistribution's of source code must retain the above copyright notice,\r
15 //     this list of conditions and the following disclaimer.\r
16 //\r
17 //   * Redistribution's in binary form must reproduce the above copyright notice,\r
18 //     this list of conditions and the following disclaimer in the documentation\r
19 //     and/or other materials provided with the distribution.\r
20 //\r
21 //   * The name of Intel Corporation may not be used to endorse or promote products\r
22 //     derived from this software without specific prior written permission.\r
23 //\r
24 // This software is provided by the copyright holders and contributors "as is" and\r
25 // any express or implied warranties, including, but not limited to, the implied\r
26 // warranties of merchantability and fitness for a particular purpose are disclaimed.\r
27 // In no event shall the Intel Corporation or contributors be liable for any direct,\r
28 // indirect, incidental, special, exemplary, or consequential damages\r
29 // (including, but not limited to, procurement of substitute goods or services;\r
30 // loss of use, data, or profits; or business interruption) however caused\r
31 // and on any theory of liability, whether in contract, strict liability,\r
32 // or tort (including negligence or otherwise) arising in any way out of\r
33 // the use of this software, even if advised of the possibility of such damage.\r
34 //\r
35 //M*/\r
36 \r
37 \r
38 #include <opencv2/core/core.hpp>\r
39 #include <opencv2/contrib/contrib.hpp>\r
40 #include <opencv2/highgui/highgui.hpp>\r
41 \r
42 #include <iostream>\r
43 #include <cstdio>\r
44 #include <cstring>\r
45 #include <ctime>\r
46 \r
47 using namespace std;\r
48 using namespace cv;\r
49 \r
50 class ASDFrameHolder\r
51 {\r
52 private:\r
53         IplImage *image;\r
54         double timeStamp;\r
55 \r
56 public:\r
57         ASDFrameHolder();\r
58         virtual ~ASDFrameHolder();\r
59         virtual void assignFrame(IplImage *sourceImage, double frameTime);\r
60         inline IplImage *getImage();\r
61         inline double getTimeStamp();\r
62         virtual void setImage(IplImage *sourceImage);\r
63 };\r
64 \r
65 class ASDFrameSequencer\r
66 {\r
67 public:\r
68         virtual ~ASDFrameSequencer();\r
69         virtual IplImage *getNextImage();\r
70         virtual void close();\r
71         virtual bool isOpen();\r
72         virtual void getFrameCaption(char *caption);\r
73 };\r
74 \r
75 class ASDCVFrameSequencer : public ASDFrameSequencer\r
76 {\r
77 protected:\r
78         CvCapture *capture;\r
79 \r
80 public:\r
81         virtual IplImage *getNextImage();\r
82         virtual void close();\r
83         virtual bool isOpen();\r
84 };\r
85 \r
86 class ASDFrameSequencerWebCam : public ASDCVFrameSequencer\r
87 {\r
88 public:\r
89         virtual bool open(int cameraIndex);\r
90 };\r
91 \r
92 class ASDFrameSequencerVideoFile : public ASDCVFrameSequencer\r
93 {\r
94 public:\r
95         virtual bool open(const char *fileName);\r
96 };\r
97 \r
98 class ASDFrameSequencerImageFile : public ASDFrameSequencer {\r
99 private:\r
100         char sFileNameMask[2048];\r
101         int nCurrentIndex, nStartIndex, nEndIndex;\r
102 \r
103 public:\r
104         virtual void open(const char *fileNameMask, int startIndex, int endIndex);\r
105         virtual void getFrameCaption(char *caption);\r
106         virtual IplImage *getNextImage();\r
107         virtual void close();\r
108         virtual bool isOpen();\r
109 };\r
110 \r
111 //-------------------- ASDFrameHolder -----------------------//\r
112 ASDFrameHolder::ASDFrameHolder( )\r
113 {\r
114         image = NULL;\r
115         timeStamp = 0;\r
116 };\r
117 \r
118 ASDFrameHolder::~ASDFrameHolder( )\r
119 {\r
120         cvReleaseImage(&image);\r
121 };\r
122 \r
123 void ASDFrameHolder::assignFrame(IplImage *sourceImage, double frameTime)\r
124 {\r
125         if (image != NULL)\r
126         {\r
127                 cvReleaseImage(&image);\r
128                 image = NULL;\r
129         }\r
130 \r
131         image = cvCloneImage(sourceImage);\r
132         timeStamp = frameTime;\r
133 };\r
134 \r
135 IplImage *ASDFrameHolder::getImage()\r
136 {\r
137         return image;\r
138 };\r
139 \r
140 double ASDFrameHolder::getTimeStamp()\r
141 {\r
142         return timeStamp;\r
143 };\r
144 \r
145 void ASDFrameHolder::setImage(IplImage *sourceImage)\r
146 {\r
147         image = sourceImage;\r
148 };\r
149 \r
150 \r
151 //-------------------- ASDFrameSequencer -----------------------//\r
152 ASDFrameSequencer::~ASDFrameSequencer()\r
153 {\r
154         close();\r
155 };\r
156 \r
157 IplImage *ASDFrameSequencer::getNextImage()\r
158 {\r
159         return NULL;\r
160 };\r
161 \r
162 void ASDFrameSequencer::close()\r
163 {\r
164 \r
165 };\r
166 \r
167 bool ASDFrameSequencer::isOpen()\r
168 {\r
169         return false;\r
170 };\r
171 \r
172 void ASDFrameSequencer::getFrameCaption(char* /*caption*/) {\r
173         return;\r
174 };\r
175 \r
176 IplImage* ASDCVFrameSequencer::getNextImage()\r
177 {\r
178         IplImage *image;\r
179 \r
180         image = cvQueryFrame(capture);\r
181 \r
182         if (image != NULL)\r
183         {\r
184                 return cvCloneImage(image);\r
185         }\r
186         else\r
187         {\r
188                 return NULL;\r
189         }\r
190 };\r
191 \r
192 void ASDCVFrameSequencer::close()\r
193 {\r
194         if (capture != NULL)\r
195         {\r
196                 cvReleaseCapture(&capture);\r
197         }\r
198 };\r
199 \r
200 bool ASDCVFrameSequencer::isOpen()\r
201 {\r
202         return (capture != NULL);\r
203 };\r
204 \r
205 \r
206 //-------------------- ASDFrameSequencerWebCam -----------------------//\r
207 bool ASDFrameSequencerWebCam::open(int cameraIndex)\r
208 {\r
209         close();\r
210 \r
211         capture = cvCaptureFromCAM(cameraIndex);\r
212 \r
213         if (!capture)\r
214         {\r
215                 return false;\r
216         }\r
217         else\r
218         {\r
219                 return true;\r
220         }\r
221 };\r
222 \r
223 \r
224 //-------------------- ASDFrameSequencerVideoFile -----------------------//\r
225 \r
226 bool ASDFrameSequencerVideoFile::open(const char *fileName)\r
227 {\r
228         close();\r
229 \r
230         capture = cvCaptureFromFile(fileName);\r
231         if (!capture)\r
232         {\r
233                 return false;\r
234         }\r
235         else\r
236         {\r
237                 return true;\r
238         }\r
239 };\r
240 \r
241 \r
242 //-------------------- ASDFrameSequencerImageFile -----------------------//\r
243 \r
244 void ASDFrameSequencerImageFile::open(const char *fileNameMask, int startIndex, int endIndex)\r
245 {\r
246         nCurrentIndex = startIndex-1;\r
247         nStartIndex = startIndex;\r
248         nEndIndex = endIndex;\r
249 \r
250         std::sprintf(sFileNameMask, "%s", fileNameMask);\r
251 };\r
252 \r
253 void ASDFrameSequencerImageFile::getFrameCaption(char *caption) {\r
254         std::sprintf(caption, sFileNameMask, nCurrentIndex);\r
255 };\r
256 \r
257 IplImage* ASDFrameSequencerImageFile::getNextImage()\r
258 {\r
259         char fileName[2048];\r
260 \r
261         nCurrentIndex++;\r
262 \r
263         if (nCurrentIndex > nEndIndex)\r
264                 return NULL;\r
265 \r
266         std::sprintf(fileName, sFileNameMask, nCurrentIndex);\r
267 \r
268         IplImage* img = cvLoadImage(fileName);\r
269 \r
270         return img;\r
271 };\r
272 \r
273 void ASDFrameSequencerImageFile::close()\r
274 {\r
275         nCurrentIndex = nEndIndex+1;\r
276 };\r
277 \r
278 bool ASDFrameSequencerImageFile::isOpen()\r
279 {\r
280         return (nCurrentIndex <= nEndIndex);\r
281 };\r
282 \r
283 void putTextWithShadow(IplImage *img, const char *str, CvPoint point, CvFont *font, CvScalar color = CV_RGB(255, 255, 128))\r
284 {\r
285         cvPutText(img, str, cvPoint(point.x-1,point.y-1), font, CV_RGB(0, 0, 0));\r
286         cvPutText(img, str, point, font, color);\r
287 };\r
288 \r
289 #define ASD_RGB_SET_PIXEL(pointer, r, g, b)     { (*pointer) = (unsigned char)b; (*(pointer+1)) = (unsigned char)g;     (*(pointer+2)) = (unsigned char)r; }\r
290 \r
291 #define ASD_RGB_GET_PIXEL(pointer, r, g, b) {b = (unsigned char)(*(pointer)); g = (unsigned char)(*(pointer+1)); r = (unsigned char)(*(pointer+2));}\r
292 \r
293 void displayBuffer(IplImage *rgbDestImage, IplImage *buffer, int rValue, int gValue, int bValue)\r
294 {\r
295         int x, y, nWidth, nHeight;\r
296         double destX, destY, dx, dy;\r
297         uchar c;\r
298         unsigned char *pSrc;\r
299 \r
300         nWidth = buffer->width;\r
301         nHeight = buffer->height;\r
302 \r
303         dx = double(rgbDestImage->width)/double(nWidth);\r
304         dy = double(rgbDestImage->height)/double(nHeight);\r
305 \r
306         destX = 0;\r
307         for (x = 0; x < nWidth; x++)\r
308         {\r
309                 destY = 0;\r
310                 for (y = 0; y < nHeight; y++)\r
311                 {\r
312                         c = ((uchar*)(buffer->imageData + buffer->widthStep*y))[x];\r
313 \r
314                         if (c)\r
315                         {\r
316                                 pSrc = (unsigned char *)rgbDestImage->imageData + rgbDestImage->widthStep*int(destY) + (int(destX)*rgbDestImage->nChannels);\r
317                                 ASD_RGB_SET_PIXEL(pSrc, rValue, gValue, bValue);\r
318                         }\r
319                         destY += dy;\r
320                 }\r
321                 destY = 0;\r
322                 destX += dx;\r
323         }\r
324 };\r
325 \r
326 void help(const char *exe_name)\r
327 {\r
328     std::cout << "\nThis program demonstrates the contributed flesh detector CvAdaptiveSkinDetector which can be found in contrib.cpp\n"\r
329             << "Usage: " << std::endl <<\r
330                 exe_name << " --fileMask --firstFrame --lastFrame" << std::endl << std::endl <<\r
331         "Example: " << std::endl <<\r
332                 exe_name << " --fileMask=C:\\VideoSequences\\sample1\\right_view\\temp_%05d.jpg  --firstFrame=0  --lastFrame=1000" << std::endl <<\r
333         "       iterates through temp_00000.jpg  to  temp_01000.jpg" << std::endl << std::endl <<\r
334         "If no parameter specified, this application will try to capture from the default Webcam." << std::endl <<\r
335         "Please note: Background should not contain large surfaces with skin tone." <<\r
336         "\n\n ESC will stop\n"\r
337         "Using OpenCV version %s\n" << CV_VERSION << "\n"\r
338         << std::endl;\r
339 }\r
340 \r
341 int main(int argc, const char** argv )\r
342 {\r
343     help(argv[0]);\r
344 \r
345     CommandLineParser parser(argc, argv);\r
346 \r
347     string fileMask = parser.get<string>("fileMask");\r
348     int firstFrame = parser.get<int>("firstFrame", 0);\r
349     int lastFrame = parser.get<int>("lastFrame", 0);\r
350 \r
351         IplImage *img, *filterMask = NULL;\r
352         CvAdaptiveSkinDetector filter(1, CvAdaptiveSkinDetector::MORPHING_METHOD_ERODE_DILATE);\r
353         ASDFrameSequencer *sequencer;\r
354         CvFont base_font;\r
355         char caption[2048], s[256], windowName[256];\r
356         long int clockTotal = 0, numFrames = 0;\r
357     std::clock_t clock;\r
358 \r
359         if (argc < 4)\r
360         {\r
361                 sequencer = new ASDFrameSequencerWebCam();\r
362                 (dynamic_cast<ASDFrameSequencerWebCam*>(sequencer))->open(-1);\r
363 \r
364                 if (! sequencer->isOpen())\r
365                 {\r
366                         std::cout << std::endl << "Error: Cannot initialize the default Webcam" << std::endl << std::endl;\r
367                 }\r
368         }\r
369         else\r
370         {\r
371         // A sequence of images captured from video source, is stored here\r
372                 sequencer = new ASDFrameSequencerImageFile();\r
373                 (dynamic_cast<ASDFrameSequencerImageFile*>(sequencer))->open(fileMask.c_str(), firstFrame, lastFrame );\r
374 \r
375         }\r
376         std::sprintf(windowName, "%s", "Adaptive Skin Detection Algorithm for Video Sequences");\r
377 \r
378         cvNamedWindow(windowName, CV_WINDOW_AUTOSIZE);\r
379         cvInitFont( &base_font, CV_FONT_VECTOR0, 0.5, 0.5);\r
380 \r
381         while ((img = sequencer->getNextImage()) != 0)\r
382         {\r
383                 numFrames++;\r
384 \r
385                 if (filterMask == NULL)\r
386                 {\r
387                         filterMask = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_8U, 1);\r
388                 }\r
389                 clock = std::clock();\r
390                 filter.process(img, filterMask);        // DETECT SKIN\r
391                 clockTotal += (std::clock() - clock);\r
392 \r
393                 displayBuffer(img, filterMask, 0, 255, 0);\r
394 \r
395                 sequencer->getFrameCaption(caption);\r
396                 std::sprintf(s, "%s - %d x %d", caption, img->width, img->height);\r
397                 putTextWithShadow(img, s, cvPoint(10, img->height-35), &base_font);\r
398 \r
399                 std::sprintf(s, "Average processing time per frame: %5.2fms", (double(clockTotal*1000/CLOCKS_PER_SEC))/numFrames);\r
400                 putTextWithShadow(img, s, cvPoint(10, img->height-15), &base_font);\r
401 \r
402                 cvShowImage (windowName, img);\r
403                 cvReleaseImage(&img);\r
404 \r
405                 if (cvWaitKey(1) == 27)\r
406                         break;\r
407         }\r
408 \r
409         sequencer->close();\r
410         delete sequencer;\r
411 \r
412         cvReleaseImage(&filterMask);\r
413 \r
414         cvDestroyWindow(windowName);\r
415 \r
416         std::cout << "Finished, " << numFrames << " frames processed." << std::endl;\r
417 \r
418         return 0;\r
419 }\r
420 \r