CodeVis.com SourceForge.net Logo

Example.cpp

Go to the documentation of this file.
00001 // Example.cpp
00002 // Test and sample program for CodeVis VidCapture
00003 // Written by Michael Ellison
00004 //-------------------------------------------------------------------------
00005 //                      CodeVis's Free License
00006 //                         www.codevis.com
00007 //
00008 // Copyright (c) 2003 by Michael Ellison (mike@codevis.com)
00009 // All rights reserved.
00010 //
00011 // You may use this software in source and/or binary form, with or without
00012 // modification, for commercial or non-commercial purposes, provided that 
00013 // you comply with the following conditions:
00014 //
00015 // * Redistributions of source code must retain the above copyright notice,
00016 //   this list of conditions and the following disclaimer. 
00017 //
00018 // * Redistributions of modified source must be clearly marked as modified,
00019 //   and due notice must be placed in the modified source indicating the
00020 //   type of modification(s) and the name(s) of the person(s) performing
00021 //   said modification(s).
00022 //
00023 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00024 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00025 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00026 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00027 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00028 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
00029 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
00030 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
00031 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00032 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
00033 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 //
00035 //---------------------------------------------------------------------------
00036 // Modifications:
00037 //
00038 //---------------------------------------------------------------------------
00056 
00057 // if STOP_BEFORE_EXIT is defined,
00058 // we'll wait for a key hit before exiting.
00059 // #define STOP_BEFORE_EXIT
00060 
00061 // if LOOP_TEST is defined, we'll loop until a key is hit
00062 // #define LOOP_TEST
00063 
00064 
00065 #if (defined(STOP_BEFORE_EXIT) || defined(LOOP_TEST))
00066    #include <conio.h>
00067 #endif
00068 
00069 #ifdef STOP_BEFORE_EXIT
00070    // Clear any existing keystrokes, then wait for a final one on exit.
00071    #define EXIT_MACRO printf("Press any key to exit...\n"); \
00072                       while (kbhit()) {getch();} \
00073                       getch();
00074 #else
00075    #define EXIT_MACRO
00076 #endif
00077 
00078 
00079 
00080 
00081 #include <stdio.h>
00082  #include "VidCapture.h"
00083 
00084 // You only need to include this if you plan on using CodeVis utility
00085 // or tracing functions
00086 #include "CVUtil.h"
00087 
00092 bool TestIt();
00093 
00100 bool enumCallback(   const char*             devname, 
00101                      void*                   userParam);
00102 
00110 bool capCallback (   CVRES                   status,
00111                      CVImage*                image,
00112                      void*                   userParam);
00113 
00120 void SlowNegateImage(CVImage* image);
00121 
00122 // Global test device name
00123 char gDeviceName[256];
00124 
00125 // Global frame count
00126 int gFrameNum = 0;   // Offset
00127 
00128 // Global device number
00129 int gDevNum = 0; 
00130 
00131 //--------------------------------------------------------------------
00137 void main()
00138 {
00139    printf("-------------------------------------------------------\n");
00140    printf("CodeVis VidCapture Test Program                        \n");
00141    printf("%s",kVIDCAPTURE_STRING);
00142    printf("-------------------------------------------------------\n");
00143 
00144 #ifdef LOOP_TEST
00145    printf("Looping until you press a key.\n");
00146    // Loop until key hit
00147    while (!kbhit())
00148    {
00149       // reset globals for another pass...
00150       memset(gDeviceName,0,sizeof(gDeviceName));
00151       gFrameNum = 0;
00152       gDevNum = 0;
00153 #endif // LOOP_TEST
00154       
00155       static int testRunNumber = 1;
00156 
00157       if (false == TestIt())
00158       {
00159          printf("************* Test run %d failed!\n", testRunNumber);
00160          EXIT_MACRO
00161          return;
00162       }
00163       else
00164       {
00165          printf("Test run %d succeeded.\n", testRunNumber++);
00166       }
00167 
00168 #ifdef LOOP_TEST
00169    } // end while (!kbhit)
00170 #endif
00171 
00172    EXIT_MACRO
00173 }
00174 
00175 
00176 
00177 bool TestIt()
00178 {
00179    // Acquire a video capture object from CVPlatform.
00180    // You can also just instantiate a CVVidCaptureDSWin32 object
00181    // directly, but this way the code is platform-neutral.
00182    CVVidCapture* vidCap = CVPlatform::GetPlatform()->AcquireVideoCapture();
00183 
00184    // First initialize the video capture interface
00185    // by calling Init().
00186    if (CVSUCCESS(vidCap->Init()))
00187    {
00188       printf("Initialized video capture object.\n");
00189    }
00190    else
00191    {
00192       printf("Error initializing video capture object.\n");
00193       
00194       // Release the video capture object.
00195       // You could also just delete it right now, but using this
00196       // method allows us to switch to a singleton if we need
00197       // for subclasses of CVVidCapture, lets us reference count
00198       // if desired, etc.
00199       CVPlatform::GetPlatform()->Release(vidCap);                  
00200       return false;
00201    }
00202 
00203    // Enumerate devices.
00204    // The enumCallback is called for each available
00205    // video capture device.  Our current enumeration
00206    // callback just saves the first one. In practice,
00207    // you'd usually want to add these to a list and
00208    // let the user select one if the last selected
00209    // one was not available.
00210    //
00211    // Note that the video capture interface must
00212    // first be initialized before enumerating devices.
00213    memset(gDeviceName,0,256);
00214    
00215    int numDevices = 0;
00216    if (CVFAILED(vidCap->GetNumDevices(numDevices)))
00217    {
00218       printf("Failed enumerating devices.\n");
00219       vidCap->Uninit();
00220       CVPlatform::GetPlatform()->Release(vidCap);      
00221       return false;
00222    }
00223 
00224    CVVidCapture::VIDCAP_DEVICE devInfo;
00225 
00226    int curDevIndex = 0;
00227    for (curDevIndex = 0; curDevIndex < numDevices; curDevIndex++)
00228    {
00229       if (CVSUCCESS(vidCap->GetDeviceInfo(curDevIndex,devInfo)))
00230       {
00231          printf("Device %d: %s\n",curDevIndex,devInfo.DeviceString);
00232       }
00233    }
00234 
00235    // Now connect to the selected device.
00236    if (CVSUCCESS(vidCap->Connect(1)))
00237    {
00238       int devNameLen = 0;
00239       vidCap->GetDeviceName(0,devNameLen);
00240       devNameLen++;
00241       char *devName = new char[devNameLen];
00242       vidCap->GetDeviceName(devName,devNameLen);
00243       
00244       printf("Connection succeeded to %s.\n",devName);
00245       delete [] devName;
00246    }
00247    else
00248    {
00249       printf("Connection failed.\n");
00250       vidCap->Uninit();
00251       CVPlatform::GetPlatform()->Release(vidCap);      
00252       return false;
00253    }
00254 
00255    // Get the number of supported modes.
00256    // Mode changes can be done any time we're not
00257    // grabbing.
00258    //
00259    CVVidCapture::VIDCAP_MODE modeInfo;
00260    int numModes = 0;
00261    vidCap->GetNumSupportedModes(numModes);
00262 
00263    // Dump each mode 
00264    for (int curmode = 0; curmode < numModes; curmode++)
00265    {
00266       if (CVSUCCESS(vidCap->GetModeInfo(curmode, modeInfo)))
00267       {
00268          printf(  "Available mode: %d, %dx%d @ %d frames/sec (%s)\n",
00269                   curmode, 
00270                   modeInfo.XRes, 
00271                   modeInfo.YRes,
00272                   modeInfo.EstFrameRate,
00273                   vidCap->GetFormatModeName(modeInfo.InputFormat));
00274       } 
00275    }
00276 
00277    
00278    if (CVFAILED(vidCap->SetMode(0)))    // Set to first available mode
00279    //if (CVFAILED(vidCap->SetMode(2)))      // Set to the third mode
00280    {
00281       printf("Error setting video mode.\n");
00282    }
00283 
00284    // Get the mode info of our selected mode and print it.
00285    if (CVFAILED(vidCap->GetCurrentMode(modeInfo)))
00286    {
00287       printf("Error activating mode!\n");
00288    }
00289    else
00290    {
00291       printf("Activated mode: %dx%d\n",modeInfo.XRes, modeInfo.YRes);   
00292    }
00293 
00294    // Set contrast to 50% if supported. Only some video capture devices
00295    // will support the properties.
00296    long minval,maxval;
00297    if (CVSUCCESS(vidCap->GetPropertyInfo( CVVidCapture::CAMERAPROP_CONTRAST,
00298                                           0,
00299                                           0,
00300                                           &minval, 
00301                                           &maxval)))
00302    {
00303       printf("Contrast supported\n", minval, maxval);    
00304       vidCap->SetProperty( CVVidCapture::CAMERAPROP_CONTRAST,
00305                            (minval+maxval)/2);
00306    }
00307    else
00308    {
00309       printf("Contrast unsupported.\n");
00310    }
00311 
00312    // Now set the brightness if available.
00313    if (CVSUCCESS(vidCap->GetPropertyInfo( CVVidCapture::CAMERAPROP_BRIGHT,
00314                                           0,
00315                                           0,
00316                                           &minval, 
00317                                           &maxval)))
00318    {
00319       printf("Brightness supported\n", minval, maxval);     
00320       vidCap->SetProperty( CVVidCapture::CAMERAPROP_BRIGHT,
00321                            (minval+maxval)/2);
00322    }
00323    else
00324    {
00325       printf("Brightness unsupported.\n");
00326    }
00327 
00328 
00329    // Grab a grey image
00330    CVImage* grabImage = 0;
00331 
00332    printf("Grabbing grey image...\n");
00333    if (CVSUCCESS(vidCap->Grab(CVImage::CVIMAGE_GREY, grabImage)))
00334    {            
00335       if (CVFAILED(CVImage::Save("GreyGrab",grabImage)))
00336       {
00337          printf("Failed saving grey image.");
00338       }
00339       // We're responsible for freeing the image,
00340       // so do so now.
00341       CVImage::ReleaseImage(grabImage);
00342    }
00343    else
00344    {
00345       printf("Grey Grab failed.\n");
00346    }
00347 
00348    // Grab a color image
00349    printf("Grabbing color image...\n");
00350    if (CVSUCCESS(vidCap->Grab(CVImage::CVIMAGE_RGB24, grabImage)))
00351    {            
00352       if (CVFAILED(CVImage::Save("ColorGrab",grabImage)))
00353       {
00354          printf("Failed saving color image.");
00355       }
00356       // We're responsible for freeing the image,
00357       // so do so now.
00358       CVImage::ReleaseImage(grabImage);
00359    }
00360    else
00361    {
00362       printf("Color Grab failed.\n");
00363    }
00364 
00365    // Start a continuous image capture.
00366    // As each image comes in, capCallback will be called with
00367    // a pointer to the converted image.
00368 
00369    // First, do 2 seconds of grey
00370    bool started = false;
00371 
00372    printf("Starting grey image capture...\n");
00373 
00374    started = CVSUCCESS(vidCap->StartImageCap(CVImage::CVIMAGE_GREY, capCallback,0));
00375    if (!started)
00376    {
00377       printf("Error starting capture....\n");
00378    }      
00379    else
00380    {
00381       // Let it capture in image mode for 2 seconds
00382       Sleep(2000);
00383    
00384       // Stop the capture
00385       printf("Stopping image capture...\n");
00386       vidCap->Stop();
00387    }
00388 
00389    // Now do 2 seconds of color...
00390    printf("Starting color image capture...\n");
00391    started = CVSUCCESS(vidCap->StartImageCap(CVImage::CVIMAGE_RGB24, capCallback,0));
00392    if (!started)
00393    {
00394       printf("Error starting capture....\n");
00395    }      
00396    else
00397    {
00398       // Let it capture in image mode for 2 seconds
00399       Sleep(2000);
00400    
00401       // Stop the capture
00402       printf("Stopping image capture...\n");
00403       vidCap->Stop();
00404    }
00405 
00406    // Always disconnect from the device when you're done
00407    printf("Disconnecting...\n");
00408    vidCap->Disconnect();   
00409 
00410    // And uninitialize before deleting it
00411    printf("Uninitializing video capture...\n");
00412    vidCap->Uninit();
00413 
00414    // Release video capture object.
00415    CVPlatform::GetPlatform()->Release(vidCap);      
00416    return true;
00417 }
00418 
00419 //-------------------------------------------------------------------------
00420 // Callback for enumeration of capture devices.
00421 //
00422 // We're just saving the first one that comes by 
00423 // into gDeviceName[] and using it.
00424 bool enumCallback(const char* devname, void* userParam)
00425 {      
00426    
00427   // if (gDevNum < 1)     // use the first device
00428    if (gDevNum <= 1)    // use the second device
00429    {
00430       strcpy(gDeviceName,devname);
00431    }
00432    
00433    gDevNum++;
00434 
00435    printf("Device: %s\n",devname);
00436    return true;
00437 }
00438 
00439 
00440 //-------------------------------------------------------------------------
00441 // capCallback is the main image capture callback.
00442 //
00443 // We play with the image a bit inside to test out
00444 // CVImage's functions.
00445 //
00446 bool capCallback( CVRES             status,
00447                   CVImage*          imagePtr,
00448                   void*             userParam)
00449 {
00450    static int xOffset  = 0;
00451    static int yOffset  = 0;
00452 
00453    // Only try to work with the image pointer if the
00454    // status is successful!
00455    if (CVSUCCESS(status))
00456    {      
00457       char framePath[_MAX_PATH];
00458       sprintf(framePath,"cap_frame_%d",gFrameNum);
00459 
00460       CVAssert(imagePtr != 0, "This shouldn't happen. Bad image pointer.");
00461 
00462       printf("Captured frame %d.\n", gFrameNum);
00463 
00464       // Create a sub image
00465       CVImage* subImg = 0;
00466       int subWidth = imagePtr->Width() / 4;
00467       int subHeight = imagePtr->Height() / 5;
00468       
00469       if (CVFAILED(CVImage::CreateSub( imagePtr,
00470                                        subImg, 
00471                                        xOffset, 
00472                                        yOffset, 
00473                                        subWidth, 
00474                                        subHeight)))
00475       {
00476          printf("Failed creating sub image!\n");
00477       }
00478       else
00479       {
00480          // Negate the sub image
00481          SlowNegateImage(subImg);
00482 
00483          // Create a sub image of the sub image 5 pixels in from each side
00484          CVImage *subSubImg = 0;
00485          if (CVFAILED(CVImage::CreateSub( subImg,
00486                                           subSubImg,
00487                                           5,
00488                                           5,
00489                                           subWidth-10,
00490                                           subHeight-10)))
00491          {
00492             printf("Failed creating sub image of sub image\n");
00493             // Release first sub image
00494             CVImage::ReleaseImage(subImg);
00495          }
00496          else
00497          {
00498             // Release first sub image 
00499             // (this shouldn't delete subImg - subSubImg holds a reference)
00500             CVImage::ReleaseImage(subImg);
00501             
00502             // Negate subSubImg - this should restore the center of subImg
00503             // area to its original colors, just leaving a 5 pixel border of
00504             // negative around it.
00505             SlowNegateImage(subSubImg);
00506 
00507             // Release subSubImg
00508             CVImage::ReleaseImage(subSubImg);
00509          }
00510                         
00511          // Setup offsets for next sub image
00512          xOffset += subWidth; 
00513          yOffset += subHeight;
00514 
00515          if (imagePtr->Width() - xOffset < subWidth)
00516          {
00517             xOffset = 0;
00518          }
00519          if (imagePtr->Height() - yOffset < subHeight)
00520          {
00521             yOffset = 0;
00522          }
00523 
00524       }
00525 
00526       // Save the base image
00527       if (CVFAILED(CVImage::Save(framePath, imagePtr)))
00528       {
00529          printf("Failed saving image!\n");
00530       }
00531             
00532       gFrameNum++;
00533    }
00534    else
00535    {
00536       // From here, you'd usually want to signal your main thread 
00537       // that the capture has been terminated. This is the only notice
00538       // you'll receive - no more callbacks after this.
00539       //
00540       // In this example, since we're just sleeping briefly, there's
00541       // no need to signal the main thread.
00542       // 
00543       printf("Capture failure in callback! Did you disconnect camera?\n");
00544    }
00545 
00546    // Halt on frame 25 just to test halting from within a callback.
00547    if (gFrameNum == 25)
00548    {
00549       printf("Halting prematurely to test callback exit codes.\n");
00550       printf("Returning false here should abort the capture.\n");
00551       // Of course, you'll still need to call CVVidCapture::Stop()
00552       // from the main thread to clean up.
00553       return false;
00554    }   
00555    return true;
00556 }
00557 
00558 //-------------------------------------------------------------------------
00559 // SlowNegateImage() is a slow routine to negate an image.
00560 //
00561 // Works on any image type where the pixel values are 0-255,
00562 // but it recalculates each pixel location in addition to 
00563 // having 2 subroutine calls per pixel - lots of overhead. 
00564 // Good for testing CVImage::GetPixel() and CVImage::SetPixel() though.
00565 //
00566 void SlowNegateImage(CVImage* image)
00567 {
00568    // Verify that our getpixel/setpixel stuff works even
00569    // on sub images by creating a negative within the
00570    // sub image, then saving the parent (which should
00571    // now have a negative rectangle in it)
00572    for (int x = 0; x < image->Width(); x++)
00573    {
00574       for (int y=0; y < image->Height(); y++)
00575       {
00576          float r,g,b;
00577          if (CVFAILED(image->GetPixel(x,y,r,g,b)))
00578          {
00579             printf("GetPixel Error!\n");
00580          }
00581          else
00582          {
00583             // Assumes images are 0-255. If not, this will
00584             // generate funky results.
00585             r = 255.0f - r;
00586             g = 255.0f - g;
00587             b = 255.0f - b;
00588          
00589             if (CVFAILED(image->SetPixel(x,y,r,g,b)))
00590             {
00591                printf("SetPixel Error!\n");
00592             }
00593          }
00594       }
00595    }
00596 }

Generated on Mon Mar 1 13:27:12 2004 for VidCapture Library by doxygen 1.3.3
CodeVis VidCapture 0.2 Copyright © 2003-2004 by Michael Ellison.