//CVG_LicenseBegin==============================================================
//
// Copyright@ Institut TELECOM 2005
// http://www.institut-telecom.fr/en_accueil.html
//
// This software is a GPU accelerated library for computer-vision. It
// supports an OPENCV-like extensible interface for easily porting OPENCV
// applications.
//
// Contacts :
// patrick.horain@it-sudparis.eu
// gpucv-developers@picoforge.int-evry.fr
//
// Project's Home Page :
// https://picoforge.int-evry.fr/cgi-bin/twiki/view/Gpucv/Web/WebHome
//
// This software is governed by the CeCILL-B license under French law and
// abiding by the rules of distribution of free software. You can use,
// modify and/ or redistribute the software under the terms of the CeCILL-B
// license as circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html".
//
//================================================================CVG_LicenseEnd
#include "StdAfx.h"
//see the following string 'help' for keyboard details...
#include "GpuCVCamDemo.h"
using namespace GCV;
#define _CAMDEBUG 1
//All images
//================================================================================
IplImage* imageCam = NULL; //!< Image from the video input.
IplImage* imageSrc = NULL; //!< Image resized and used as source image for morphology.
IplImage* imageDst = NULL; //!< Destination image for morphology.
IplImage* imageTemp = NULL; //!< Temp image for morphology.
int iterac = 1; //!< Iteration number for morphology.
GpuCVProcessing CamDemoFilters[]={
{MorphoInit,MorphoProcess,MorphoClean, MorphoSwitch}
,{DericheInit,DericheProcess,DericheClean, DericheSwitch}
,{LutInit,LutProcess,LutClean, LutSwitch}
// ,{BackGroundInit,BackGroundProcess,BackGroundClean}
};
int FilterNbr = sizeof(CamDemoFilters)/sizeof(GpuCVProcessing);
int FilterID = 0;
//State variables =================================
bool VideoFinished = false; //!< Flag used to know when the video is finished.
bool PerformProcessing = true;
enum GpuCVSettings::Implementation CVG_STATUS = GpuCVSettings::GPUCV_IMPL_OPENCV;//!< Flag to know if we start with OpenCV/GpuCV GLSL / GpuCV CUDA implementations.
//=================================================
/** Help text shown in the console when starting the application.
*/
string help ="\n\nCamDemo grab images from the first webcam found, proccess several open/close filter and show the result image."\
"\n\nKeys used:"\
"\n\t- 'q', 'Q', and Escape to exit."\
"\n\t- space bar to switch between OpenCV and GpuCV."\
"\n\t- 'c', 'C' to enable profiling output in the console(may reduce performance."\
"\n\t- characters from '1' to '9' can be used to select a different filter."\
"\n\t- '-', '+' to decrease/increase number iterations of morphology operators.";
//================================================================================
//Application main variables
CvCapture* VideoCapture = NULL; //!< Main capture input source.
bool UseWebCam = false; //!< Flag to know which source we are using
std::string AppPath=""; //!< Path of the executable file.
std::string VideoSeqFile = ""; //!< Filepath of the video to load.
char iCameraID = -1;
std::string LabelOpenCVFile = "../../data/pictures/processed_by_opencv.bmp";//!< Image file use to show that we are using OpenCV.
std::string LabelGpuCVFile = "../../data/pictures/processed_by_gpucv.bmp";//!< Image file use to show that we are using GpuCV.
std::string LabelGCUDAFile = "../../data/pictures/processed_by_gpucv_cuda.bmp";//!< Image file use to show that we are using GpuCV.
IplImage *MSG_CV = NULL; //!< OpenCV label image.
IplImage *MSG_CVG = NULL; //!< GpuCV-Glsl label image.
IplImage *MSG_CVGCU = NULL; //!< GpuCV-Cuda label image.
IplImage* CurrentImplLabel = NULL;
#if _CAMDEBUG
CvSize ImageSize = {256,256}; //!< Image size requested for processing. We will resize input image if smaller.
#else
CvSize ImageSize = {1080,760}; //!< Image size requested for processing. We will resize input image if smaller.
#endif
CvSize ImageSize_Next = {ImageSize.width,ImageSize.height}; //!< Store the image size defined by the window size. Changing the window size will also change default image resolution.
bool printError(const char* _errorMsg)
{
std::cout << _errorMsg << std::endl;
return false;
}
//parse command line options...
/**
Command line options:
<table>
<tr>
<td>Option</td>
<td>Values</td>
<td>Description</td>
</tr>
<tr>
<td>-f videofilname</td>
<td>videofilname: Path to a video file</td>
<td>Open the given video file as input stream</td>
</tr>
<tr>
<td>-c cameraid</td>
<td>cameraid: id of the camera(from 0 to x)</td>
<td>Open the given video camera as input stream</td>
</tr>
<td>-w width - height</td>
<td>width & height: size of the video input</td>
<td>Try to open the video input using the given size, otherwise resize input to fit the given size</td>
</tr>
</table>
*/
bool parseCommandLine(int argc, char * argv[])
{
std::string strCurrentCmd;
for(int i = 1; i< argc; i++)
{
strCurrentCmd= argv[i];
if(strCurrentCmd=="-q")//quit application, used to see if it compiles and run. Further tests must be done
{
//printError("Exiting application");
exit(0);
}
if(strCurrentCmd=="-w")//input width
{
if(i+1<argc)
{
ImageSize.width = atoi(argv[++i]);
ImageSize_Next.width = ImageSize.width;
continue;
}
else
return printError("Error while parsing arguments: missing width value");
}
if(strCurrentCmd=="-h")//input height
{
if(i+1<argc)
{
ImageSize.height = atoi(argv[++i]);
ImageSize_Next.height = ImageSize.height;
continue;
}
else
return printError("Error while parsing arguments: missing height value");
}
if(strCurrentCmd=="-c")//camera id
{
if(i+1<argc)
{
iCameraID = atoi(argv[++i]);
continue;
}
else
return printError("Error while parsing arguments: missing camera id value");
}
if(strCurrentCmd=="-f")//video file
{
if(i+1<argc)
{
VideoSeqFile = argv[++i];
continue;
}
else
return printError("Error while parsing arguments: missing video filename");
}
}
return true;
}
//================================================================================
int main(int argc, char **argv)
{
GPUCV_FUNCNAME("GpuCVCamDemo");
DEBUG_FCT("");
//parse command line options...
if(parseCommandLine(argc,argv)==false)
{
GPUCV_ERROR("Exiting application...");
exit(-1);
}
try
{
InitGlut(argc, argv); //Init OpenGL and GLUT
#if !_DEMO_FORCE_NATIVE_OPENCV
cvgInit(false, false); //Init GPUCV
cvgswInit(false, false);
SET_GPUCV_OPTION(GpuCVSettings::GPUCV_SETTINGS_GL_ERROR_RISE_EXCEPTION, true);
SET_GPUCV_OPTION(GpuCVSettings::GPUCV_SETTINGS_GL_ERROR_CHECK, true);
//Select processing mode CV/CVG, default is auto.
//cvgswSetGlobalImplementation(CVG_STATUS);
#endif
SET_GPUCV_OPTION(GpuCVSettings::GPUCV_SETTINGS_GLOBAL_DEBUG, true);
cvUseOptimized(false);
//get application path
//get application path
std::string AppName= argv[0];
std::string AppPath;
GPUCV_DEBUG("argv[0]: " << AppName);
SGE::ReformatFilePath(AppName);
SGE::ParseFilePath(AppName, &AppPath);
GPUCV_NOTICE("Current application path: " << AppPath);
#ifdef _LINUX
if(AppPath=="./")
{
AppPath="../../bin";
GPUCV_NOTICE("Changing to: " << AppPath);
}
else if(AppPath.find("lib/gnu/"))
{
AppPath = AppPath.substr(0, AppPath.find("lib/gnu")-1);
AppPath += "/bin";
GPUCV_NOTICE("Changing to: " << AppPath);
}
#else
if(AppPath.find("vs200"))
{
GPUCV_NOTICE("Visual studio path found:" << AppPath);
AppPath = AppPath.substr(0, AppPath.find("vs200")-1);//remove vs6/vs2003/vs2005
if(AppPath=="")
AppPath="../";
}
#endif
GetGpuCVSettings()->SetShaderPath(AppPath);//define shader files path.
GPUCV_DEBUG("AppPath 1 "<< AppPath);
AppPath = GetGpuCVSettings()->GetShaderPath();
GPUCV_DEBUG("AppPath 1b "<< AppPath);
//=============================================
OpenVideoInput(VideoSeqFile, iCameraID);//open video input from file or webcam
InitProcessing();//init OpenCV objects
//grab first frame
imageCam = GrabInputFrame();
//initialize window size
CBChangeSize(imageCam->width, imageCam->height);
//init first filter:
CamDemoFilters[FilterID].ProcessInit();
CamDemoFilters[FilterID].Process();
GPUCV_NOTICE(help);//show starting message
glutMainLoop();//start main GLUT loop
#if CAM_DEMO_PROFILE
AppliTracer()->GenerateTextFile("Bench_DemoCam_CVG.txt");
#endif
}
catch(SGE::CAssertException &e)
{//catch any exceptions and log message
GPUCV_NOTICE("=================== Exception catched Start =================");
GPUCV_NOTICE(e.what());
GPUCV_NOTICE("=================== Exception catched End =================");
GPUCV_NOTICE("Press a key to continue...");
// SGE::Sleep(5000);
getchar();
#if !_DEMO_FORCE_NATIVE_OPENCV
cvgTerminate();
}
cvgTerminate();
#else
}
cvReleaseCapture(&VideoCapture);
cvDestroyWindow("MainWindow");
#endif
}
//================================================================================
void InitGlut(int argc, char **argv)
{
GPUCV_FUNCNAME("InitGlut");
DEBUG_FCT("");
//Init GLUT and OpenGL
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA| GLUT_ALPHA);
glutInitWindowPosition(100,100);
glutInitWindowSize(ImageSize.width, ImageSize.height);
glutCreateWindow("Morphology on CPU vs GPU");
//callback settings
glutDisplayFunc(CBDisplay);
glutIdleFunc(CBIdle);
glutReshapeFunc(CBChangeSize);
glutKeyboardFunc(CBkeys);
//==========================
#if _DEMO_FORCE_NATIVE_OPENCV
//using only opencv, we create a window to see the result image
cvNamedWindow("MainWindow", 1);
#endif
}
//================================================================================
//open video input...[WEBCAM|VIDEO_FILE]
//if video file is specified, load it
//else check if a webcam is available, if not load default video sequence.
void OpenVideoInput(const std::string _videoFile, char _cCameraID/*=-1*/)
{
GPUCV_FUNCNAME("OpenVideoInput");
GPUCV_NOTICE("Opening video input...");
#if 1 //old
//look for webcam first
if(_cCameraID>-1)//cvcamGetCamerasCount()!=0)
{//open Webcam
GPUCV_DEBUG("Trying camera..."<< _cCameraID);
VideoCapture = cvCaptureFromCAM(_cCameraID);//take first webcam.
if(!VideoCapture)
{
GPUCV_WARNING("Could not open Webcam " << _cCameraID);
}
else
{
UseWebCam =true;
return;
}
}
else
{
GPUCV_NOTICE("No camera found.");
}
if((_videoFile!="") && VideoCapture==NULL)
{//no webcam, open file
GPUCV_NOTICE("Trying video file:"<< _videoFile);
VideoSeqFile = _videoFile;
#ifdef _LINUX
VideoSeqFile = GetGpuCVSettings()->GetShaderPath() + "/" + VideoSeqFile;
#else
if(VideoSeqFile.find(":")== std::string::npos)
{//using realative path name
VideoSeqFile = GetGpuCVSettings()->GetShaderPath() + "/" + VideoSeqFile;
SGE::ReformatFilePath(VideoSeqFile);
}
#endif
VideoCapture = cvCaptureFromAVI(VideoSeqFile.data());
SG_AssertFile(VideoCapture, VideoSeqFile,"Could not open file.");
return;
}
else
{
GPUCV_NOTICE("Empty video file...");
}
#else//new
CvCapture* capture = 0;
if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
VideoCapture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
else if( argc == 2 )
VideoCapture = cvCaptureFromAVI( argv[1] );
if( !VideoCapture )
{
fprintf(stderr,"Could not initialize capturing...\n");
return -1;
}
#endif
}
//================================================================================
//grab video frame from current capture input source
IplImage * GrabInputFrame()
{
static int frameId = 0;
GPUCV_FUNCNAME("GrabInputFrame");
DEBUG_FCT("");
imageCam = cvQueryFrame(VideoCapture);
if(!imageCam)
{
GPUCV_ERROR("Could not open input frame");
if(!UseWebCam)
{//reopen video file
cvReleaseCapture(&VideoCapture);
VideoCapture = cvCaptureFromAVI(VideoSeqFile.data());
GPUCV_ERROR("Trying to re-openfile");
SG_AssertFile(VideoCapture, VideoSeqFile,"Could not open file.");
//imageCam = cvRetrieveFrame(VideoCapture);
}
else
SG_Assert(0, "Error while grabing new frame from Webcam/File!");
}
// imageCam = cvRetrieveFrame(VideoCapture);
if(!imageCam)
{//reopen video file
GPUCV_ERROR("Could not open input frame");
cvReleaseCapture(&VideoCapture);
VideoCapture = cvCaptureFromAVI(VideoSeqFile.data());
SG_AssertFile(VideoCapture, VideoSeqFile,"Could not open file.");
imageCam = cvRetrieveFrame(VideoCapture);
}
if(!imageCam)
{
VideoFinished = true;
GPUCV_NOTICE("Video file finished");
}
else
{//resize to required one
#if _CAMDEBUG
cvNamedWindow("Cam Image",1);
cvShowImage("Cam Image",imageCam);
cvWaitKey(0);
#endif
//check if resize size has changed:
bool ImageResize=false;
if(ImageSize.width!=ImageSize_Next.width || ImageSize.height!=ImageSize_Next.height)
{
ImageSize.width=ImageSize_Next.width;
ImageSize.height=ImageSize_Next.height;
if(imageSrc)
cvReleaseImage(&imageSrc);
//if(CamDemoFilters[FilterID]!=NULL)
ImageResize=true;
}
if(!imageSrc)
imageSrc = cvCreateImage(ImageSize, imageCam->depth, imageCam->nChannels);
GPUCV_DEBUG("====>>>frame ID:" <<frameId);
frameId++;
#if !_DEMO_FORCE_NATIVE_OPENCV
cvgSetLabel(imageCam, "ImageCam");
cvgSetLabel(imageSrc, "ImageSrc");
cvgSetDataFlag<DataDsc_IplImage>(imageSrc, true, true);
// cvgSetOptions(imageCam, DataContainer::UBIQUITY, true);
// cvgSetOptions(imageSrc, DataContainer::UBIQUITY, true);
#endif
//resize image to fit defined camera size
GPUCV_DEBUG("resize image to fit defined camera size");
cvResize(imageCam, imageSrc);//, CV_INTER_CUBIC);//CV_INTER_CUBIC is done on CPU...
if(ImageResize)
{
CamDemoFilters[FilterID].ProcessClean();
CamDemoFilters[FilterID].ProcessInit();
}
#if _CAMDEBUG
cvNamedWindow("Input Image",1);
cvShowImage("Input Image",imageSrc);
cvNamedWindow("Cam Image",1);
cvShowImage("Cam Image",imageCam);
#endif
}
return imageCam;
}
//================================================================================
/**
Init OpenCV structures and element for morphology processing.
*/
void InitProcessing()
{
GPUCV_FUNCNAME("InitProcessing");
DEBUG_FCT("");
static bool InitDone = false;
if (!InitDone)
{
#if 1
//loading GPUCV/OPENCV label (text)images files
//reformat file pathdft
LabelOpenCVFile = GetGpuCVSettings()->GetShaderPath()+"/"+LabelOpenCVFile;
SGE::ReformatFilePath(LabelOpenCVFile);
LabelGpuCVFile = GetGpuCVSettings()->GetShaderPath()+"/"+LabelGpuCVFile;
SGE::ReformatFilePath(LabelGpuCVFile);
LabelGCUDAFile = GetGpuCVSettings()->GetShaderPath()+"/"+LabelGCUDAFile;
SGE::ReformatFilePath(LabelGCUDAFile);
GPUCV_DEBUG("AppPath 2 "<< GetGpuCVSettings()->GetShaderPath());
GPUCV_DEBUG("Open Image "<< LabelOpenCVFile);
//open files
MSG_CV = cvLoadImage(LabelOpenCVFile.data(),1);
SG_AssertFile(MSG_CV, LabelOpenCVFile, "Could not open");
GPUCV_DEBUG("Open Image "<< LabelGpuCVFile);
MSG_CVG = cvLoadImage(LabelGpuCVFile.data(),1);
SG_AssertFile(MSG_CVG, LabelGpuCVFile, "Could not open");
GPUCV_DEBUG("Open Image "<< LabelGCUDAFile);
MSG_CVGCU = cvLoadImage(LabelGCUDAFile.data(),1);
SG_AssertFile(MSG_CVGCU, LabelGCUDAFile, "Could not open");
//load to GPU
#if !_DEMO_FORCE_NATIVE_OPENCV
cvgSetLocation<DataDsc_GLTex>(MSG_CV, true);
cvgSetLocation<DataDsc_GLTex>(MSG_CVG, true);
cvgSetLocation<DataDsc_GLTex>(MSG_CVGCU, true);
#endif
MSG_CV->origin = 1;
MSG_CVG->origin = 1;
MSG_CVGCU->origin = 1;
#endif
InitDone=true;
//=======================================
}
}
//================================================================================
void CBDisplay()
{
GPUCV_FUNCNAME("CBDisplay");
DEBUG_FCT("");
if (VideoFinished)
{
glutSwapBuffers();
return;
}
#if _DEBUG
cvNamedWindow("Output Image",1);
cvShowImage("Output Image",imageDst);
#endif
#if _DEMO_FORCE_NATIVE_OPENCV
//we don't use opengl to show the results...no need
//we use classic OpenCV window
cvShowImage("MainWindow", imageDst);
InitGLView(0,imageDst->width, 0, imageDst->height);
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
glutSwapBuffers();
#else
//beginning of drawing
cvgInitGLView(imageDst);
glClear(GL_COLOR_BUFFER_BIT);
//draw img Dst
cvgDrawGLQuad(imageDst);
//=================
//Draw labels : "Processed with OpenCV/GpuCV/CUDA"
glPushMatrix();
glRotatef(180, 1.,0.,0.);
glTranslatef(0,0.92,0);
glScalef(1,(float)38/480,1);
if(CurrentImplLabel)
cvgDrawGLQuad(CurrentImplLabel);
glPopMatrix();
glFlush();
glutSwapBuffers();
#endif
}
//
//================================================================================
void CBChangeSize(int w, int h) {
GPUCV_FUNCNAME("CBChangeSize");
DEBUG_FCT("");
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
float ratio = 1.0* w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);
ImageSize_Next.width=w;
ImageSize_Next.height=h;
}
//================================================================================
/**
Manage input keyboard events
*/
void CBkeys(unsigned char key, int x, int y)
{
GPUCV_FUNCNAME("CBkeys");
DEBUG_FCT("");
if(key<='9' && key >='0')
{
int NewFilterID = key-'0'-1;
if(NewFilterID >=0 && NewFilterID < FilterNbr)
{
CamDemoFilters[FilterID].ProcessClean();
FilterID = NewFilterID;
CamDemoFilters[FilterID].ProcessInit();
CamDemoFilters[FilterID].ProcessSwitch(CVG_STATUS);
}
}
switch (key)
{
case 27 ://escape Key
case 'Q' :
case 'q' :
#if !_DEMO_FORCE_NATIVE_OPENCV
cvgswPrintAllFctStats();
#endif
CamDemoFilters[FilterID].ProcessClean();
getchar();
exit(0);
break;
case 'C' :
case 'c' :
#if CAM_DEMO_PROFILE
if(AppliTracer()->GetConsoleStatus())
AppliTracer()->DisableConsole();
else
AppliTracer()->EnableConsole();
break;
#endif
case 's' :
//start Background substract
PerformProcessing = !PerformProcessing;
break;
case ' ' :
//re-initialize background
/* if(BackGrnd_Img)
{
cvReleaseImage(&BackGrnd_Img);
}
*/
#if 1
if (CVG_STATUS==GpuCVSettings::GPUCV_IMPL_GLSL)
{
CVG_STATUS=GpuCVSettings::GPUCV_IMPL_CUDA;
std::cout << std::endl << "Using GpuCV-CUDA" << std::endl;
CurrentImplLabel = MSG_CVGCU;
}
else if(CVG_STATUS==GpuCVSettings::GPUCV_IMPL_CUDA)
{
CVG_STATUS=GpuCVSettings::GPUCV_IMPL_OPENCV;
std::cout << std::endl << "Using OpenCV" << std::endl;
CurrentImplLabel = MSG_CV;
}
else if(CVG_STATUS==GpuCVSettings::GPUCV_IMPL_OPENCV)
{
CVG_STATUS=GpuCVSettings::GPUCV_IMPL_GLSL;
std::cout << std::endl << "Using GpuCV-GLSL" << std::endl;
CurrentImplLabel = MSG_CVG;
}
#if !_DEMO_FORCE_NATIVE_OPENCV
CamDemoFilters[FilterID].ProcessSwitch(CVG_STATUS);
cvgswSetGlobalImplementation(CVG_STATUS);
#endif
break;
case '+' :
if(++iterac > 10) iterac = 10;
GPUCV_NOTICE("Nbr of iterations:" << iterac);
break;
case '-' :
if(--iterac < 1) iterac = 1;
GPUCV_NOTICE("Nbr of iterations:" << iterac);
break;
#endif
}
}
//================================================================================
//================================================================================
void CBIdle()
{
GPUCV_FUNCNAME("CBIdle");
DEBUG_FCT("");
if (VideoFinished)
return;
//grabbing next frame
if(GrabInputFrame()==NULL)
{
return;
}
//beginning of image processing
if(PerformProcessing)
{
GPUCV_DEBUG("Call process");
CamDemoFilters[FilterID].Process();
}
//show results
glutPostRedisplay();
}
|