Subversion

gpucv

[/] [experimental/] [trunk/] [gpucv/] [src/] [example/] [GPUCVCamDemo/] [GpuCVCamDemo.cpp] - Rev 553 Go to most recent revision

Compare with Previous - Blame


//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();
}

Powered by WebSVN v1.61