Update to 2.0.0 tree from current Fremantle build
[opencv] / samples / c / adaptiveskindetector.cpp
diff --git a/samples/c/adaptiveskindetector.cpp b/samples/c/adaptiveskindetector.cpp
new file mode 100644 (file)
index 0000000..b036c28
--- /dev/null
@@ -0,0 +1,406 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////\r
+//\r
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
+//\r
+//  By downloading, copying, installing or using the software you agree to this license.\r
+//  If you do not agree to this license, do not download, install, copy or use the software.\r
+//\r
+// Copyright (C) 2009, Farhad Dadgostar\r
+// Intel Corporation and third party copyrights are property of their respective owners.\r
+//\r
+// Redistribution and use in source and binary forms, with or without modification,\r
+// are permitted provided that the following conditions are met:\r
+//\r
+//   * Redistribution's of source code must retain the above copyright notice,\r
+//     this list of conditions and the following disclaimer.\r
+//\r
+//   * Redistribution's in binary form must reproduce the above copyright notice,\r
+//     this list of conditions and the following disclaimer in the documentation\r
+//     and/or other materials provided with the distribution.\r
+//\r
+//   * The name of Intel Corporation may not be used to endorse or promote products\r
+//     derived from this software without specific prior written permission.\r
+//\r
+// This software is provided by the copyright holders and contributors "as is" and\r
+// any express or implied warranties, including, but not limited to, the implied\r
+// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
+// In no event shall the Intel Corporation or contributors be liable for any direct,\r
+// indirect, incidental, special, exemplary, or consequential damages\r
+// (including, but not limited to, procurement of substitute goods or services;\r
+// loss of use, data, or profits; or business interruption) however caused\r
+// and on any theory of liability, whether in contract, strict liability,\r
+// or tort (including negligence or otherwise) arising in any way out of\r
+// the use of this software, even if advised of the possibility of such damage.\r
+//\r
+//M*/\r
+\r
+\r
+#include <iostream>\r
+#include <cstdio>\r
+#include <cstring>\r
+#include <ctime>\r
+#include <cvaux.h>\r
+#include <highgui.h>\r
+\r
+class ASDFrameHolder\r
+{\r
+private:\r
+       IplImage *image;\r
+       double timeStamp;\r
+\r
+public:\r
+       ASDFrameHolder();\r
+       virtual ~ASDFrameHolder();\r
+       virtual void assignFrame(IplImage *sourceImage, double frameTime);\r
+       inline IplImage *getImage();\r
+       inline double getTimeStamp();\r
+       virtual void setImage(IplImage *sourceImage);\r
+};\r
+\r
+class ASDFrameSequencer\r
+{\r
+public:\r
+       virtual ~ASDFrameSequencer();\r
+       virtual IplImage *getNextImage();\r
+       virtual void close();\r
+       virtual bool isOpen();\r
+       virtual void getFrameCaption(char *caption);\r
+};\r
+\r
+class ASDCVFrameSequencer : public ASDFrameSequencer\r
+{\r
+protected:\r
+       CvCapture *capture;\r
+\r
+public:\r
+       virtual IplImage *getNextImage();\r
+       virtual void close();\r
+       virtual bool isOpen();\r
+};\r
+\r
+class ASDFrameSequencerWebCam : public ASDCVFrameSequencer\r
+{\r
+public:\r
+       virtual bool open(int cameraIndex);\r
+};\r
+\r
+class ASDFrameSequencerVideoFile : public ASDCVFrameSequencer\r
+{\r
+public:\r
+       virtual bool open(const char *fileName);\r
+};\r
+\r
+class ASDFrameSequencerImageFile : public ASDFrameSequencer {\r
+private:\r
+       char sFileNameMask[2048];\r
+       int nCurrentIndex, nStartIndex, nEndIndex;\r
+\r
+public:\r
+       virtual void open(const char *fileNameMask, int startIndex, int endIndex);\r
+       virtual void getFrameCaption(char *caption);\r
+       virtual IplImage *getNextImage();\r
+       virtual void close();\r
+       virtual bool isOpen();\r
+};\r
+\r
+//-------------------- ASDFrameHolder -----------------------//\r
+ASDFrameHolder::ASDFrameHolder( )\r
+{\r
+       image = NULL;\r
+       timeStamp = 0;\r
+};\r
+\r
+ASDFrameHolder::~ASDFrameHolder( )\r
+{\r
+       cvReleaseImage(&image);\r
+};\r
+\r
+void ASDFrameHolder::assignFrame(IplImage *sourceImage, double frameTime)\r
+{\r
+       if (image != NULL)\r
+       {\r
+               cvReleaseImage(&image);\r
+               image = NULL;\r
+       }\r
+\r
+       image = cvCloneImage(sourceImage);\r
+       timeStamp = frameTime;\r
+};\r
+\r
+IplImage *ASDFrameHolder::getImage()\r
+{\r
+       return image;\r
+};\r
+\r
+double ASDFrameHolder::getTimeStamp()\r
+{\r
+       return timeStamp;\r
+};\r
+\r
+void ASDFrameHolder::setImage(IplImage *sourceImage)\r
+{\r
+       image = sourceImage;\r
+};\r
+\r
+\r
+//-------------------- ASDFrameSequencer -----------------------//\r
+\r
+ASDFrameSequencer::~ASDFrameSequencer()\r
+{\r
+       close();\r
+};\r
+\r
+IplImage *ASDFrameSequencer::getNextImage()\r
+{\r
+       return NULL;\r
+};\r
+\r
+void ASDFrameSequencer::close()\r
+{\r
+\r
+};\r
+\r
+bool ASDFrameSequencer::isOpen()\r
+{\r
+       return false;\r
+};\r
+\r
+void ASDFrameSequencer::getFrameCaption(char *caption) {\r
+       return;\r
+};\r
+\r
+IplImage* ASDCVFrameSequencer::getNextImage()\r
+{\r
+       IplImage *image;\r
+\r
+       image = cvQueryFrame(capture);\r
+\r
+       if (image != NULL)\r
+       {\r
+               return cvCloneImage(image);\r
+       }\r
+       else\r
+       {\r
+               return NULL;\r
+       }\r
+};\r
+\r
+void ASDCVFrameSequencer::close()\r
+{\r
+       if (capture != NULL)\r
+       {\r
+               cvReleaseCapture(&capture);\r
+       }\r
+};\r
+\r
+bool ASDCVFrameSequencer::isOpen()\r
+{\r
+       return (capture != NULL);\r
+};\r
+\r
+\r
+//-------------------- ASDFrameSequencerWebCam -----------------------//\r
+\r
+bool ASDFrameSequencerWebCam::open(int cameraIndex)\r
+{\r
+       close();\r
+\r
+       capture = cvCaptureFromCAM(cameraIndex);\r
+\r
+       if (!capture)\r
+       {\r
+               return false;\r
+       }\r
+       else\r
+       {\r
+               return true;\r
+       }\r
+};\r
+\r
+\r
+//-------------------- ASDFrameSequencerVideoFile -----------------------//\r
+\r
+bool ASDFrameSequencerVideoFile::open(const char *fileName)\r
+{\r
+       close();\r
+\r
+       capture = cvCaptureFromFile(fileName);\r
+       if (!capture)\r
+       {\r
+               return false;\r
+       }\r
+       else\r
+       {\r
+               return true;\r
+       }\r
+};\r
+\r
+\r
+//-------------------- ASDFrameSequencerImageFile -----------------------//\r
+\r
+void ASDFrameSequencerImageFile::open(const char *fileNameMask, int startIndex, int endIndex)\r
+{\r
+       nCurrentIndex = startIndex-1;\r
+       nStartIndex = startIndex;\r
+       nEndIndex = endIndex;\r
+\r
+       std::sprintf(sFileNameMask, "%s", fileNameMask);\r
+};\r
+\r
+void ASDFrameSequencerImageFile::getFrameCaption(char *caption) {\r
+       std::sprintf(caption, sFileNameMask, nCurrentIndex);\r
+};\r
+\r
+IplImage* ASDFrameSequencerImageFile::getNextImage()\r
+{\r
+       char fileName[2048];\r
+\r
+       nCurrentIndex++;\r
+\r
+       if (nCurrentIndex > nEndIndex)\r
+               return NULL;\r
+\r
+       std::sprintf(fileName, sFileNameMask, nCurrentIndex);\r
+\r
+       IplImage* img = cvLoadImage(fileName);\r
+\r
+       return img;\r
+};\r
+\r
+void ASDFrameSequencerImageFile::close()\r
+{\r
+       nCurrentIndex = nEndIndex+1;\r
+};\r
+\r
+bool ASDFrameSequencerImageFile::isOpen()\r
+{\r
+       return (nCurrentIndex <= nEndIndex);\r
+};\r
+\r
+void putTextWithShadow(IplImage *img, const char *str, CvPoint point, CvFont *font, CvScalar color = CV_RGB(255, 255, 128))\r
+{\r
+       cvPutText(img, str, cvPoint(point.x-1,point.y-1), font, CV_RGB(0, 0, 0));\r
+       cvPutText(img, str, point, font, color);\r
+};\r
+\r
+#define ASD_RGB_SET_PIXEL(pointer, r, g, b)    { (*pointer) = (unsigned char)b; (*(pointer+1)) = (unsigned char)g;     (*(pointer+2)) = (unsigned char)r; }\r
+\r
+#define ASD_RGB_GET_PIXEL(pointer, r, g, b) {b = (unsigned char)(*(pointer)); g = (unsigned char)(*(pointer+1)); r = (unsigned char)(*(pointer+2));}\r
+\r
+void displayBuffer(IplImage *rgbDestImage, IplImage *buffer, int rValue, int gValue, int bValue)\r
+{\r
+       int x, y, nWidth, nHeight;\r
+       double destX, destY, dx, dy;\r
+       uchar c;\r
+       unsigned char *pSrc;\r
+\r
+       nWidth = buffer->width;\r
+       nHeight = buffer->height;\r
+\r
+       dx = double(rgbDestImage->width)/double(nWidth);\r
+       dy = double(rgbDestImage->height)/double(nHeight);\r
+\r
+       destX = 0;\r
+       for (x = 0; x < nWidth; x++)\r
+       {\r
+               destY = 0;\r
+               for (y = 0; y < nHeight; y++)\r
+               {\r
+                       c = ((uchar*)(buffer->imageData + buffer->widthStep*y))[x];\r
+\r
+                       if (c)\r
+                       {\r
+                               pSrc = (unsigned char *)rgbDestImage->imageData + rgbDestImage->widthStep*int(destY) + (int(destX)*rgbDestImage->nChannels);\r
+                               ASD_RGB_SET_PIXEL(pSrc, rValue, gValue, bValue);\r
+                       }\r
+                       destY += dy;\r
+               }\r
+               destY = 0;\r
+               destX += dx;\r
+       }\r
+};\r
+\r
+int main(int argc, char** argv )\r
+{\r
+       IplImage *img, *filterMask = NULL;\r
+       CvAdaptiveSkinDetector filter(1, CvAdaptiveSkinDetector::MORPHING_METHOD_ERODE_DILATE);\r
+       ASDFrameSequencer *sequencer;\r
+       CvFont base_font;\r
+       char caption[2048], s[256], windowName[256];\r
+       long int clockTotal = 0, numFrames = 0;\r
+       std::clock_t clock;\r
+\r
+       if (argc < 4)\r
+       {\r
+               std::cout << "Usage: " << std::endl <<\r
+                       argv[0] << " fileMask firstFrame lastFrame" << std::endl << std::endl <<\r
+                       "Example: " << std::endl <<\r
+                       argv[0] << " C:\\VideoSequences\\sample1\\right_view\\temp_%05d.jpg  0  1000" << std::endl <<\r
+                       "       iterates through temp_00000.jpg  to  temp_01000.jpg" << std::endl << std::endl <<\r
+                       "If no parameter specified, this application will try to capture from the default Webcam." << std::endl <<\r
+                       "Please note: Background should not contain large surfaces with skin tone." <<\r
+                       std::endl;\r
+\r
+               sequencer = new ASDFrameSequencerWebCam();\r
+               (dynamic_cast<ASDFrameSequencerWebCam*>(sequencer))->open(-1);\r
+\r
+               if (! sequencer->isOpen())\r
+               {\r
+                       std::cout << std::endl << "Error: Cannot initialize the default Webcam" << std::endl << std::endl;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               sequencer = new ASDFrameSequencerImageFile();\r
+               (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
+\r
+       }\r
+       std::sprintf(windowName, "%s", "Adaptive Skin Detection Algorithm for Video Sequences");\r
+\r
+       cvNamedWindow(windowName, CV_WINDOW_AUTOSIZE);\r
+       cvInitFont( &base_font, CV_FONT_VECTOR0, 0.5, 0.5);\r
+\r
+       // Usage:\r
+       //              c:\>CvASDSample "C:\VideoSequences\sample1\right_view\temp_%05d.jpg" 0 1000\r
+\r
+       std::cout << "Press ESC to stop." << std::endl << std::endl;\r
+       while ((img = sequencer->getNextImage()) != 0)\r
+       {\r
+               numFrames++;\r
+\r
+               if (filterMask == NULL)\r
+               {\r
+                       filterMask = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_8U, 1);\r
+               }\r
+               clock = std::clock();\r
+               filter.process(img, filterMask);        // process the frame\r
+               clockTotal += (std::clock() - clock);\r
+\r
+               displayBuffer(img, filterMask, 0, 255, 0);\r
+\r
+               sequencer->getFrameCaption(caption);\r
+               std::sprintf(s, "%s - %d x %d", caption, img->width, img->height);\r
+               putTextWithShadow(img, s, cvPoint(10, img->height-35), &base_font);\r
+\r
+               std::sprintf(s, "Average processing time per frame: %5.2fms", (double(clockTotal*1000/CLOCKS_PER_SEC))/numFrames);\r
+               putTextWithShadow(img, s, cvPoint(10, img->height-15), &base_font);\r
+\r
+               cvShowImage (windowName, img);\r
+               cvReleaseImage(&img);\r
+\r
+               if (cvWaitKey(1) == 27)\r
+                       break;\r
+       }\r
+\r
+       sequencer->close();\r
+       delete sequencer;\r
+\r
+       cvReleaseImage(&filterMask);\r
+\r
+       cvDestroyWindow(windowName);\r
+\r
+       std::cout << "Finished, " << numFrames << " frames processed." << std::endl;\r
+\r
+       return 0;\r
+}\r
+\r