fdb7f178eeba6c07fc309084975bbf6ee5b3766e
[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()\r
327 {\r
328      printf("\nThis program demonstrates the contributed flesh detector CvAdaptiveSkinDetector \n"\r
329             "which can be found in contrib.cpp \n"\r
330             "Usage: \n"\r
331             "./adaptiveskindetector [--fileMask]=<path to file, which are used in mask \n"\r
332             "           [--firstFrame]=<first frame number \n"\r
333             "           [--lastFrame]=<last frame number> \n"\r
334             "if at least one parameter doesn't specified, it will try to use default webcam \n"\r
335             "Expample: \n"\r
336             "         --fileMask = /home/user_home_directory/work/opencv/samples/c/temp_%%05d.jpg --firstFrame=0  --lastFrame=1000 \n");\r
337 }\r
338 \r
339 int main(int argc, const char** argv )\r
340 {\r
341     help();\r
342 \r
343     CommandLineParser parser(argc, argv);\r
344 \r
345     string fileMask = parser.get<string>("fileMask");\r
346     int firstFrame = parser.get<int>("firstFrame", 0);\r
347     int lastFrame = parser.get<int>("lastFrame", 0);\r
348 \r
349         IplImage *img, *filterMask = NULL;\r
350         CvAdaptiveSkinDetector filter(1, CvAdaptiveSkinDetector::MORPHING_METHOD_ERODE_DILATE);\r
351         ASDFrameSequencer *sequencer;\r
352         CvFont base_font;\r
353         char caption[2048], s[256], windowName[256];\r
354         long int clockTotal = 0, numFrames = 0;\r
355     std::clock_t clock;\r
356 \r
357         if (argc < 4)\r
358         {\r
359                 sequencer = new ASDFrameSequencerWebCam();\r
360                 (dynamic_cast<ASDFrameSequencerWebCam*>(sequencer))->open(-1);\r
361 \r
362                 if (! sequencer->isOpen())\r
363                 {\r
364                         std::cout << std::endl << "Error: Cannot initialize the default Webcam" << std::endl << std::endl;\r
365                 }\r
366         }\r
367         else\r
368         {\r
369         // A sequence of images captured from video source, is stored here\r
370                 sequencer = new ASDFrameSequencerImageFile();\r
371                 (dynamic_cast<ASDFrameSequencerImageFile*>(sequencer))->open(fileMask.c_str(), firstFrame, lastFrame );\r
372 \r
373         }\r
374         std::sprintf(windowName, "%s", "Adaptive Skin Detection Algorithm for Video Sequences");\r
375 \r
376         cvNamedWindow(windowName, CV_WINDOW_AUTOSIZE);\r
377         cvInitFont( &base_font, CV_FONT_VECTOR0, 0.5, 0.5);\r
378 \r
379         while ((img = sequencer->getNextImage()) != 0)\r
380         {\r
381                 numFrames++;\r
382 \r
383                 if (filterMask == NULL)\r
384                 {\r
385                         filterMask = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_8U, 1);\r
386                 }\r
387                 clock = std::clock();\r
388                 filter.process(img, filterMask);        // DETECT SKIN\r
389                 clockTotal += (std::clock() - clock);\r
390 \r
391                 displayBuffer(img, filterMask, 0, 255, 0);\r
392 \r
393                 sequencer->getFrameCaption(caption);\r
394                 std::sprintf(s, "%s - %d x %d", caption, img->width, img->height);\r
395                 putTextWithShadow(img, s, cvPoint(10, img->height-35), &base_font);\r
396 \r
397                 std::sprintf(s, "Average processing time per frame: %5.2fms", (double(clockTotal*1000/CLOCKS_PER_SEC))/numFrames);\r
398                 putTextWithShadow(img, s, cvPoint(10, img->height-15), &base_font);\r
399 \r
400                 cvShowImage (windowName, img);\r
401                 cvReleaseImage(&img);\r
402 \r
403                 if (cvWaitKey(1) == 27)\r
404                         break;\r
405         }\r
406 \r
407         sequencer->close();\r
408         delete sequencer;\r
409 \r
410         cvReleaseImage(&filterMask);\r
411 \r
412         cvDestroyWindow(windowName);\r
413 \r
414         std::cout << "Finished, " << numFrames << " frames processed." << std::endl;\r
415 \r
416         return 0;\r
417 }\r
418 \r