lot's of changes; nonfree & photo modules added; SIFT & SURF -> nonfree module; Inpai...
[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 <iostream>\r
39 #include <cstdio>\r
40 #include <cstring>\r
41 #include <ctime>\r
42 #include "opencv2/contrib/contrib.hpp"\r
43 #include "opencv2/highgui/highgui.hpp"\r
44 \r
45 void help(char **argv)\r
46 {\r
47         std::cout << "\nThis program demonstrates the contributed flesh detector CvAdaptiveSkinDetector which can be found in contrib.cpp\n"\r
48                         << "Usage: " << std::endl <<\r
49                 argv[0] << " fileMask firstFrame lastFrame" << std::endl << std::endl <<\r
50                 "Example: " << std::endl <<\r
51                 argv[0] << " C:\\VideoSequences\\sample1\\right_view\\temp_%05d.jpg  0  1000" << std::endl <<\r
52                 "       iterates through temp_00000.jpg  to  temp_01000.jpg" << std::endl << std::endl <<\r
53                 "If no parameter specified, this application will try to capture from the default Webcam." << std::endl <<\r
54                 "Please note: Background should not contain large surfaces with skin tone." <<\r
55                 "\n\n ESC will stop\n"\r
56                 "Using OpenCV version %s\n" << CV_VERSION << "\n"\r
57                 << std::endl;\r
58 }\r
59 \r
60 class ASDFrameHolder\r
61 {\r
62 private:\r
63         IplImage *image;\r
64         double timeStamp;\r
65 \r
66 public:\r
67         ASDFrameHolder();\r
68         virtual ~ASDFrameHolder();\r
69         virtual void assignFrame(IplImage *sourceImage, double frameTime);\r
70         inline IplImage *getImage();\r
71         inline double getTimeStamp();\r
72         virtual void setImage(IplImage *sourceImage);\r
73 };\r
74 \r
75 class ASDFrameSequencer\r
76 {\r
77 public:\r
78         virtual ~ASDFrameSequencer();\r
79         virtual IplImage *getNextImage();\r
80         virtual void close();\r
81         virtual bool isOpen();\r
82         virtual void getFrameCaption(char *caption);\r
83 };\r
84 \r
85 class ASDCVFrameSequencer : public ASDFrameSequencer\r
86 {\r
87 protected:\r
88         CvCapture *capture;\r
89 \r
90 public:\r
91         virtual IplImage *getNextImage();\r
92         virtual void close();\r
93         virtual bool isOpen();\r
94 };\r
95 \r
96 class ASDFrameSequencerWebCam : public ASDCVFrameSequencer\r
97 {\r
98 public:\r
99         virtual bool open(int cameraIndex);\r
100 };\r
101 \r
102 class ASDFrameSequencerVideoFile : public ASDCVFrameSequencer\r
103 {\r
104 public:\r
105         virtual bool open(const char *fileName);\r
106 };\r
107 \r
108 class ASDFrameSequencerImageFile : public ASDFrameSequencer {\r
109 private:\r
110         char sFileNameMask[2048];\r
111         int nCurrentIndex, nStartIndex, nEndIndex;\r
112 \r
113 public:\r
114         virtual void open(const char *fileNameMask, int startIndex, int endIndex);\r
115         virtual void getFrameCaption(char *caption);\r
116         virtual IplImage *getNextImage();\r
117         virtual void close();\r
118         virtual bool isOpen();\r
119 };\r
120 \r
121 //-------------------- ASDFrameHolder -----------------------//\r
122 ASDFrameHolder::ASDFrameHolder( )\r
123 {\r
124         image = NULL;\r
125         timeStamp = 0;\r
126 };\r
127 \r
128 ASDFrameHolder::~ASDFrameHolder( )\r
129 {\r
130         cvReleaseImage(&image);\r
131 };\r
132 \r
133 void ASDFrameHolder::assignFrame(IplImage *sourceImage, double frameTime)\r
134 {\r
135         if (image != NULL)\r
136         {\r
137                 cvReleaseImage(&image);\r
138                 image = NULL;\r
139         }\r
140 \r
141         image = cvCloneImage(sourceImage);\r
142         timeStamp = frameTime;\r
143 };\r
144 \r
145 IplImage *ASDFrameHolder::getImage()\r
146 {\r
147         return image;\r
148 };\r
149 \r
150 double ASDFrameHolder::getTimeStamp()\r
151 {\r
152         return timeStamp;\r
153 };\r
154 \r
155 void ASDFrameHolder::setImage(IplImage *sourceImage)\r
156 {\r
157         image = sourceImage;\r
158 };\r
159 \r
160 \r
161 //-------------------- ASDFrameSequencer -----------------------//\r
162 \r
163 ASDFrameSequencer::~ASDFrameSequencer()\r
164 {\r
165         close();\r
166 };\r
167 \r
168 IplImage *ASDFrameSequencer::getNextImage()\r
169 {\r
170         return NULL;\r
171 };\r
172 \r
173 void ASDFrameSequencer::close()\r
174 {\r
175 \r
176 };\r
177 \r
178 bool ASDFrameSequencer::isOpen()\r
179 {\r
180         return false;\r
181 };\r
182 \r
183 void ASDFrameSequencer::getFrameCaption(char* /*caption*/) {\r
184         return;\r
185 };\r
186 \r
187 IplImage* ASDCVFrameSequencer::getNextImage()\r
188 {\r
189         IplImage *image;\r
190 \r
191         image = cvQueryFrame(capture);\r
192 \r
193         if (image != NULL)\r
194         {\r
195                 return cvCloneImage(image);\r
196         }\r
197         else\r
198         {\r
199                 return NULL;\r
200         }\r
201 };\r
202 \r
203 void ASDCVFrameSequencer::close()\r
204 {\r
205         if (capture != NULL)\r
206         {\r
207                 cvReleaseCapture(&capture);\r
208         }\r
209 };\r
210 \r
211 bool ASDCVFrameSequencer::isOpen()\r
212 {\r
213         return (capture != NULL);\r
214 };\r
215 \r
216 \r
217 //-------------------- ASDFrameSequencerWebCam -----------------------//\r
218 \r
219 bool ASDFrameSequencerWebCam::open(int cameraIndex)\r
220 {\r
221         close();\r
222 \r
223         capture = cvCaptureFromCAM(cameraIndex);\r
224 \r
225         if (!capture)\r
226         {\r
227                 return false;\r
228         }\r
229         else\r
230         {\r
231                 return true;\r
232         }\r
233 };\r
234 \r
235 \r
236 //-------------------- ASDFrameSequencerVideoFile -----------------------//\r
237 \r
238 bool ASDFrameSequencerVideoFile::open(const char *fileName)\r
239 {\r
240         close();\r
241 \r
242         capture = cvCaptureFromFile(fileName);\r
243         if (!capture)\r
244         {\r
245                 return false;\r
246         }\r
247         else\r
248         {\r
249                 return true;\r
250         }\r
251 };\r
252 \r
253 \r
254 //-------------------- ASDFrameSequencerImageFile -----------------------//\r
255 \r
256 void ASDFrameSequencerImageFile::open(const char *fileNameMask, int startIndex, int endIndex)\r
257 {\r
258         nCurrentIndex = startIndex-1;\r
259         nStartIndex = startIndex;\r
260         nEndIndex = endIndex;\r
261 \r
262         std::sprintf(sFileNameMask, "%s", fileNameMask);\r
263 };\r
264 \r
265 void ASDFrameSequencerImageFile::getFrameCaption(char *caption) {\r
266         std::sprintf(caption, sFileNameMask, nCurrentIndex);\r
267 };\r
268 \r
269 IplImage* ASDFrameSequencerImageFile::getNextImage()\r
270 {\r
271         char fileName[2048];\r
272 \r
273         nCurrentIndex++;\r
274 \r
275         if (nCurrentIndex > nEndIndex)\r
276                 return NULL;\r
277 \r
278         std::sprintf(fileName, sFileNameMask, nCurrentIndex);\r
279 \r
280         IplImage* img = cvLoadImage(fileName);\r
281 \r
282         return img;\r
283 };\r
284 \r
285 void ASDFrameSequencerImageFile::close()\r
286 {\r
287         nCurrentIndex = nEndIndex+1;\r
288 };\r
289 \r
290 bool ASDFrameSequencerImageFile::isOpen()\r
291 {\r
292         return (nCurrentIndex <= nEndIndex);\r
293 };\r
294 \r
295 void putTextWithShadow(IplImage *img, const char *str, CvPoint point, CvFont *font, CvScalar color = CV_RGB(255, 255, 128))\r
296 {\r
297         cvPutText(img, str, cvPoint(point.x-1,point.y-1), font, CV_RGB(0, 0, 0));\r
298         cvPutText(img, str, point, font, color);\r
299 };\r
300 \r
301 #define ASD_RGB_SET_PIXEL(pointer, r, g, b)     { (*pointer) = (unsigned char)b; (*(pointer+1)) = (unsigned char)g;     (*(pointer+2)) = (unsigned char)r; }\r
302 \r
303 #define ASD_RGB_GET_PIXEL(pointer, r, g, b) {b = (unsigned char)(*(pointer)); g = (unsigned char)(*(pointer+1)); r = (unsigned char)(*(pointer+2));}\r
304 \r
305 void displayBuffer(IplImage *rgbDestImage, IplImage *buffer, int rValue, int gValue, int bValue)\r
306 {\r
307         int x, y, nWidth, nHeight;\r
308         double destX, destY, dx, dy;\r
309         uchar c;\r
310         unsigned char *pSrc;\r
311 \r
312         nWidth = buffer->width;\r
313         nHeight = buffer->height;\r
314 \r
315         dx = double(rgbDestImage->width)/double(nWidth);\r
316         dy = double(rgbDestImage->height)/double(nHeight);\r
317 \r
318         destX = 0;\r
319         for (x = 0; x < nWidth; x++)\r
320         {\r
321                 destY = 0;\r
322                 for (y = 0; y < nHeight; y++)\r
323                 {\r
324                         c = ((uchar*)(buffer->imageData + buffer->widthStep*y))[x];\r
325 \r
326                         if (c)\r
327                         {\r
328                                 pSrc = (unsigned char *)rgbDestImage->imageData + rgbDestImage->widthStep*int(destY) + (int(destX)*rgbDestImage->nChannels);\r
329                                 ASD_RGB_SET_PIXEL(pSrc, rValue, gValue, bValue);\r
330                         }\r
331                         destY += dy;\r
332                 }\r
333                 destY = 0;\r
334                 destX += dx;\r
335         }\r
336 };\r
337 \r
338 int main(int argc, char** argv )\r
339 {\r
340         IplImage *img, *filterMask = NULL;\r
341         CvAdaptiveSkinDetector filter(1, CvAdaptiveSkinDetector::MORPHING_METHOD_ERODE_DILATE);\r
342         ASDFrameSequencer *sequencer;\r
343         CvFont base_font;\r
344         char caption[2048], s[256], windowName[256];\r
345         long int clockTotal = 0, numFrames = 0;\r
346         std::clock_t clock;\r
347 \r
348         if (argc < 4)\r
349         {\r
350                 help(argv);\r
351                 sequencer = new ASDFrameSequencerWebCam();\r
352                 (dynamic_cast<ASDFrameSequencerWebCam*>(sequencer))->open(-1);\r
353 \r
354                 if (! sequencer->isOpen())\r
355                 {\r
356                         std::cout << std::endl << "Error: Cannot initialize the default Webcam" << std::endl << std::endl;\r
357                 }\r
358         }\r
359         else\r
360         {\r
361                 sequencer = new ASDFrameSequencerImageFile();\r
362                 (dynamic_cast<ASDFrameSequencerImageFile*>(sequencer))->open(argv[1], std::atoi(argv[2]), std::atoi(argv[3]) ); // A sequence of images captured from video source, is stored here\r
363 \r
364         }\r
365         std::sprintf(windowName, "%s", "Adaptive Skin Detection Algorithm for Video Sequences");\r
366 \r
367         cvNamedWindow(windowName, CV_WINDOW_AUTOSIZE);\r
368         cvInitFont( &base_font, CV_FONT_VECTOR0, 0.5, 0.5);\r
369 \r
370         // Usage:\r
371         //              c:\>CvASDSample "C:\VideoSequences\sample1\right_view\temp_%05d.jpg" 0 1000\r
372 \r
373         std::cout << "Press ESC to stop." << std::endl << std::endl;\r
374         while ((img = sequencer->getNextImage()) != 0)\r
375         {\r
376                 numFrames++;\r
377 \r
378                 if (filterMask == NULL)\r
379                 {\r
380                         filterMask = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_8U, 1);\r
381                 }\r
382                 clock = std::clock();\r
383                 filter.process(img, filterMask);        // DETECT SKIN\r
384                 clockTotal += (std::clock() - clock);\r
385 \r
386                 displayBuffer(img, filterMask, 0, 255, 0);\r
387 \r
388                 sequencer->getFrameCaption(caption);\r
389                 std::sprintf(s, "%s - %d x %d", caption, img->width, img->height);\r
390                 putTextWithShadow(img, s, cvPoint(10, img->height-35), &base_font);\r
391 \r
392                 std::sprintf(s, "Average processing time per frame: %5.2fms", (double(clockTotal*1000/CLOCKS_PER_SEC))/numFrames);\r
393                 putTextWithShadow(img, s, cvPoint(10, img->height-15), &base_font);\r
394 \r
395                 cvShowImage (windowName, img);\r
396                 cvReleaseImage(&img);\r
397 \r
398                 if (cvWaitKey(1) == 27)\r
399                         break;\r
400         }\r
401 \r
402         sequencer->close();\r
403         delete sequencer;\r
404 \r
405         cvReleaseImage(&filterMask);\r
406 \r
407         cvDestroyWindow(windowName);\r
408 \r
409         std::cout << "Finished, " << numFrames << " frames processed." << std::endl;\r
410 \r
411         return 0;\r
412 }\r
413 \r