mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
415 lines
11 KiB
415 lines
11 KiB
/*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/compat.hpp" |
|
#include "opencv2/highgui/highgui_c.h" |
|
|
|
#ifndef _CRT_SECURE_NO_WARNINGS |
|
# define _CRT_SECURE_NO_WARNINGS |
|
#endif |
|
|
|
static void help(char **argv) |
|
{ |
|
std::cout << "\nThis 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; |
|
}
|
|
|