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