Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

HistogramBlobTest.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011  ---------------------------------------------------------------------------*/
00012 #include <HistogramBlobTest.h>
00013 #include <phission.h>
00014 
00015 /* ------------------------------------------------------------------------ */
00016 int glbl_disable_displays = 0;
00017 int glbl_print_histogram = 0;
00018 int glbl_print_blobs = 1;
00019 
00020 /* ------------------------------------------------------------------------ */
00021 /* ------------------------------------------------------------------------ */
00022 int usage ()
00023 {
00024     printf("\n\nUsage:\n");
00025     printf("\t--help            Display usage\n");
00026     printf("\t--nodisplay       Disable the allocation, opening or any use of a display.\n");
00027     printf("\t--test <value>    Sleep <value> seconds and then close test\n");
00028     printf("\t--count <value>   Loop <value> times during histogram before sleeping\n");
00029     printf("\n\n");
00030     exit(1);
00031 }
00032         
00033 /* ------------------------------------------------------------------------ */
00034 int main( int argc, char *argv[] )
00035 {
00036     phFUNCTION("main")
00037 
00038     uint32_t        i           = 0;
00039     uint32_t        j           = 0;
00040 
00041     char            *capture_path   = NULL;
00042     int             channel         = 0;
00043     
00044     /* Display variables */
00045     int             displaysOpen= 1;
00046     char            title[255];
00047     
00048     /* --------------------------------------------------------------------- */
00049     /* HISTOGRAM Variables ------------------------------------------------- */
00050     /* Filters to run in the pipeline */
00051     uint32_t            nTrainDisplays  = 1;
00052     phDisplayInterface  **train_display = NULL;
00053  
00054     /* fractional size of the main window */
00055     const uint32_t      box_size = 8;
00056    
00057     /* histogram rect coords */
00058     uint32_t            bw = 0;
00059     uint32_t            bh = 0;
00060     uint32_t            x1 = 0;
00061     uint32_t            y1 = 0;
00062     uint32_t            x2 = 0;
00063     uint32_t            y2 = 0;
00064     
00065     /* --------------------------------------------------------------------- */
00066 #ifdef WIN32
00067     VFWSource           *capture = new VFWSource();
00068 #else
00069     V4LCapture          *capture = new V4LCapture();
00070 #endif
00071 
00072     phHistogramData     hist_data;
00073     histogram_Filter    *histogram          = new histogram_Filter();
00074     convert_Filter      *convert            = new convert_Filter();
00075     gaussian3x3_Filter  *gauss              = new gaussian3x3_Filter();
00076     
00077     phColor             outcolor            = phColorRGB24_new(0,255,255);
00078     
00079     phPipeline          *train_pipeline     = new phPipeline();
00080 
00081     /* Utility class to ease the starting and stopping of displays, captures and
00082      * pipelines */
00083     phSystem            train_system;
00084    
00085     /* These are used to store N phColor samples from the histogram data */
00086     /* At the end of the train stage they are averaged together and the
00087      * deviation caculated to create a color and threshold to match */
00088     const uint32_t      sample_count        = 1;
00089     phColor             color_samples[sample_count];
00090     uint32_t            sample_index        = 0;
00091     uint32_t            waiting_for_samples = 1;
00092     
00093     /* --------------------------------------------------------------------- */
00094     /* BLOB Variables ------------------------------------------------------ */
00095     phImage             tempimage;
00096 
00097     uint32_t            nTrackDisplays          = 1;
00098     phDisplayInterface  **track_display         = NULL;
00099     
00100     blob_Filter         *blob_find              = new blob_Filter();
00101     phColor             blob_this_color;
00102     phColor             threshold               = phColorRGBA32_new(10,64,64,0);
00103     phColor             blob_highlight_color    = phColorRGB24_new(0,0,0);
00104     
00105     /* blob data output from the blob filter */
00106     phBlobData          blob_data;
00107     const int32_t       min_size                = 100;
00108 
00109     phPipeline          *track_pipeline         = new phPipeline();
00110 
00111     /* Utility class to ease the starting and stopping of displays, captures and
00112      * pipelines */
00113     phSystem            track_system;
00114     
00115     /* Remove the code below when using this code as an example.
00116      * 
00117      * This just checks whether "--test" has been specified with
00118      * a time value argument. It's for testing all the examples
00119      * without the need for human intervention. */
00120     int             test = 0;
00121     int             test_loop_count = 0;
00122     int             count = 0;
00123 
00124     phArgTable      *arg_parser = new phArgTable();
00125     
00126     /* Setup and parse all the arguments */
00127     rc = arg_parser->add("--test",&test,phARG_INT);
00128     phCHECK_RC(rc,NULL,"arg_parser->add");
00129     rc = arg_parser->add("--count",&count,phARG_INT);
00130     phCHECK_RC(rc,NULL,"arg_parser->add");
00131     rc = arg_parser->add("--nodisplay",&glbl_disable_displays,phARG_BOOL);
00132     phCHECK_RC(rc,NULL,"arg_parser->add");
00133     rc = arg_parser->add("--help",(void *)&usage,phARG_FUNC);
00134     phCHECK_RC(rc,NULL,"arg_parser->add");
00135     
00136     rc = arg_parser->add("--path",&capture_path,phARG_CHAR);
00137     phCHECK_RC(rc,NULL,"arg_parser->add");
00138 
00139     rc = arg_parser->add("--channel",&channel,phARG_INT);
00140     phCHECK_RC(rc,NULL,"arg_parser->add");
00141     
00142     rc = arg_parser->parse(argc,argv);
00143     phCHECK_RC(rc,NULL,"arg_parser->parse");
00144 
00145     if (test)
00146     {
00147         glbl_print_histogram = 0;
00148         glbl_print_blobs = 1;
00149     }
00150     
00151     if (glbl_disable_displays) 
00152     {
00153         nTrainDisplays = 0;
00154         nTrackDisplays = 0;
00155     }
00156     
00157     capture->set(320,240,capture_path);
00158     capture->setChannel(channel);
00159     capture->setColour(35000);
00160     capture->setHue(22700);
00161     capture->setContrast(32000);
00162     capture->setBrightness(28000);
00163 
00164     rc = train_system.addCapture(capture);
00165     phPRINT_RC(rc,NULL,"train_system.addCapture(capture)");
00166     
00167     train_display = new phDisplayInterface *[nTrainDisplays];
00168     phCHECK_NULLPTR(train_display,"new","new phDisplayInterface *[nTrainDisplays];");
00169     
00170     for (i = 0; i < nTrainDisplays; i++ )
00171     {
00172         sprintf(title,"HistogramBlobTest::train[%lu]",i);
00173 #if defined(PH_HAVE_X11)
00174         train_display[i] = new X11Display(320,240,title);
00175 #elif defined(PH_HAVE_GDI)
00176         train_display[i] = new GDIDisplay(320,240,title);
00177 #endif
00178         
00179         rc = train_system.addDisplay(train_display[i]);
00180         phPRINT_RC(rc,NULL,"train_system.addDisplay(train_display[i:%u])",i);
00181     }
00182 
00183     rc = train_system.addPipeline(train_pipeline);
00184     phPRINT_RC(rc,NULL,"train_system.addPipeline(train_pipeline)");
00185 
00186     /* --------------------------------------------------------------------- */
00187     /* BEGIN HISTOGRAM / "TRAINING" Section */
00188     /* --------------------------------------------------------------------- */
00189     
00190     /* [] Attach the displays to the live sources */
00191     /* Image -> (b)phPipeline -> (a)Processed Output Display */
00192     
00193     /* [] Attach the Pipeline output image to the display so the
00194      * display updates when a processing has been completed
00195      * for each loop */
00196     if (nTrainDisplays > 0)
00197     {
00198         train_display[0]->setLiveSourceInput(train_pipeline->getLiveSourceOutput());
00199     }
00200    
00201     if (nTrainDisplays > 1)
00202     { 
00203         train_display[1]->setLiveSourceInput(capture->getLiveSourceOutput());
00204     }
00205 
00206     /* 2b.) Attach the image to the live source input of the
00207      * Pipeline so processing is done automatically once the 
00208      * pipeline is started. */
00209     
00210     train_pipeline->setLiveSourceInput(capture->getLiveSourceOutput());
00211     
00212     /* 3.) Add the filter(s) into the pipeline in the order they will 
00213      * be used */
00214     /* Add the gaussian blur to the pipeline */
00215     train_pipeline->add(gauss);
00216 
00217     /* Set the convert filter parameters to convert to HSV before histogramming */
00218     convert->set(phImageHSV24);
00219     /* Add the convert filter to the pipeline */
00220     train_pipeline->add(convert);
00221    
00222     /* Set the histogram parameters */
00223     bw = (capture->getWidth() / box_size);
00224     bh = (capture->getHeight() / box_size);
00225     x1 = (capture->getWidth() / 2) - (bw / 2);
00226     y1 = (capture->getHeight() / 2) - (bh / 2);
00227     x2 = x1 + bw;
00228     y2 = y1 + bh;
00229     
00230     histogram->set( x1,/* x1 */
00231                     y1,/* y1 */
00232                     x2,/* x2 */
00233                     y2,/* y2 */
00234                     64, /* bins */
00235                     1,/* draw_rect */
00236                     &outcolor /* histogram rectangle output color & format */
00237                     );
00238                     
00239     /* Add the histogram to the pipeline */                  
00240     rc = train_pipeline->add(histogram);
00241     phCHECK_RC(rc,NULL,"train_pipeline->add()");
00242 
00243     rc = hist_data.connect(histogram->getLiveHistogramOutput());
00244     phCHECK_RC(rc,NULL,"hist_data.connect()");
00245           
00246     /* 4.) Startup the system */
00247     rc = train_system.startup();
00248     phPRINT_RC(rc,NULL,"train_system.startup()");
00249     
00250     /* 5.) Keep going until all the windows are closed */
00251     phPROGRESS( "Close the display to begin tracking the color\n");
00252     
00253     displaysOpen = 1;
00254     while (displaysOpen || waiting_for_samples)
00255     {
00256         /* Yielding is optional. This gives up the thread's timeslice
00257          * to prevent slow response in other threads. It consumes more
00258          * CPU cycles than sleeping. Use it instead of sleeping if
00259          * this loop is processing anything */
00260         
00261         phYield();
00262 
00263         /* Get the most recent histogram data */
00264         rc = hist_data.update();
00265         phPRINT_RC(rc,NULL,"hist_data.update()");
00266 
00267         if (glbl_print_histogram)
00268         {
00269             if (rc == phLiveObjectUPDATED)
00270             {
00271                 hist_data.print_data();
00272             }
00273         }
00274         
00275         color_samples[sample_index] = hist_data.getColor();
00276         if (sample_index == (sample_count - 1)) 
00277             waiting_for_samples = 0;
00278         sample_index = (sample_index + 1) % sample_count;
00279         
00280         if (nTrainDisplays > 0)
00281         {
00282             displaysOpen = 0;
00283             for (i = 0; (i < nTrainDisplays) && (displaysOpen == 0); i++)
00284             {
00285                 if (train_display[i]->isOpen() == 1)
00286                 {
00287                     displaysOpen = 1;
00288                 }
00289             }
00290         }
00291         
00292         /* Remove this if block when using this code as an example */
00293         /* Set the loop control value to end the loop when testing */
00294         if ((test > 0) && (!waiting_for_samples))
00295         { 
00296             displaysOpen = 0;
00297             phSleep(test); /* test's value should be a time (in secs) value > 0*/
00298         }
00299     }
00300     
00301     /* 6.) Shutdown the system */
00302     rc = train_system.shutdown();
00303     phPRINT_RC(rc,NULL,"train_system.shutdown()");
00304 
00305     rc = hist_data.disconnect();
00306     phPRINT_RC(rc,NULL,"hist_data.disconnect()");
00307 
00308     /* 7.) Calculate the COLOR and THRESHOLDS */
00309     
00310     /* Set the color type */
00311     blob_this_color.type = threshold.type = color_samples[0].type;
00312     
00313     /* Average each possible channel */
00314     for (j = 0; j < phCOLOR_MAXBYTES; j++ )
00315     {
00316         uint32_t sample_total = 0;
00317         
00318         for (i = 0; i < sample_count; i++)
00319         {
00320             sample_total += color_samples[i].array.v[j];
00321             
00322             DEBUG_PRINT("color_samples[i:%u].array.v[j:%u] : %u\ttotal:%u\n",
00323                     i,j,color_samples[i].array.v[j],sample_total);
00324         }
00325        
00326         blob_this_color.array.v[j] = 0;
00327         if (sample_total > 0)
00328         {
00329             blob_this_color.array.v[j] = sample_total / sample_count;
00330             DEBUG_PRINT("blob_this_color.array.v[j:%u] = %u\n",
00331                       j,blob_this_color.array.v[j]);
00332         }
00333 
00334         /* Calculate the thresholds */
00335         for (i = 0; i < sample_count; i++ )
00336         {
00337             int32_t dev = blob_this_color.array.v[j] - color_samples[i].array.v[j];
00338 
00339             DEBUG_PRINT("dev:%d\t x:%u - y:%u\n",
00340                      dev,
00341                      blob_this_color.array.v[j],
00342                      color_samples[i].array.v[j]);
00343 
00344             if (dev < 0) dev *= -1;
00345             
00346             DEBUG_PRINT("dev:%d\n", dev);
00347 
00348             if (dev > threshold.array.v[j])
00349                 threshold.array.v[j] = (dev >= 255 ? 255 : dev);
00350                 
00351             DEBUG_PRINT("threshold.array.v[j:%u] = %u\n",
00352                         j,threshold.array.v[j]);
00353 //            threshold.array.v[j] *= 2;
00354 //            threshold.array.v[j] = 20;
00355         }
00356     }
00357 
00358     phPROGRESS("blob_this_color[ %u, %u, %u, %u ]\n",
00359               blob_this_color.array.v[0],
00360               blob_this_color.array.v[1],
00361               blob_this_color.array.v[2],
00362               blob_this_color.array.v[3] );
00363     phPROGRESS("threshold[ %u, %u, %u, %u ]\n",
00364               threshold.array.v[0],
00365               threshold.array.v[1],
00366               threshold.array.v[2],
00367               threshold.array.v[3] );
00368               
00369 #if 0          
00370     blob_this_color.array.v[0] = 240;
00371     blob_this_color.array.v[1] = 200;
00372     blob_this_color.array.v[2] = 200;
00373     blob_this_color.array.v[3] = 0;
00374     
00375     threshold.array.v[0] = 60;
00376     threshold.array.v[1] = 60;
00377     threshold.array.v[2] = 60;
00378     threshold.array.v[3] = 0;
00379 
00380     phPROGRESS("blob_this_color[ %u, %u, %u, %u ]\n",
00381               blob_this_color.array.v[0],
00382               blob_this_color.array.v[1],
00383               blob_this_color.array.v[2],
00384               blob_this_color.array.v[3] );
00385     phPROGRESS("threshold[ %u, %u, %u, %u ]\n",
00386               threshold.array.v[0],
00387               threshold.array.v[1],
00388               threshold.array.v[2],
00389               threshold.array.v[3] );
00390 #endif
00391     /* --------------------------------------------------------------------- */
00392     /* BEGIN BLOB / "TRACKING" SECTION */
00393     /* --------------------------------------------------------------------- */
00394     rc = track_system.addCapture(capture);
00395     phPRINT_RC(rc,NULL,"track_system.addCapture(capture)");
00396 
00397     track_display = new phDisplayInterface *[nTrackDisplays];
00398     phCHECK_NULLPTR(track_display,"new","new phDisplayInterface *[nDisplays];");
00399     
00400     for (i = 0; i < nTrackDisplays; i++ )
00401     {
00402         sprintf(title,"HistogramBlobTest::track[%lu]",i);
00403         
00404 #if defined(PH_HAVE_X11)
00405         track_display[i] = new X11Display(320,240,title);
00406 #elif defined(PH_HAVE_GDI)
00407         track_display[i] = new GDIDisplay(320,240,title);
00408 #endif
00409 
00410         rc = track_system.addDisplay(track_display[i]);
00411         phPRINT_RC(rc,NULL,"track_system.addDiaplay(track_display[i:%u]",i);
00412     }
00413 
00414     rc = track_system.addPipeline(track_pipeline);
00415     phPRINT_RC(rc,NULL,"track_system.addPipeline(track_pipeline");
00416     
00417     /* [] Attach the displays to the live sources */
00418     /* Image -> (b)phPipeline -> (a)Processed Output Display */
00419     
00420     /* [] Attach the Pipeline output image to the display so the
00421      * display updates when a processing has been completed
00422      * for each loop */
00423     if (track_display > 0)
00424     {
00425         track_display[0]->setLiveSourceInput(track_pipeline->getLiveSourceOutput());
00426     }
00427    
00428     if (nTrackDisplays > 1)
00429     { 
00430         track_display[1]->setLiveSourceInput(capture->getLiveSourceOutput());
00431     }
00432 
00433     /* 2b.) Attach the image to the live source input of the
00434      * Pipeline so processing is done automatically once the 
00435      * pipeline is started. */
00436     track_pipeline->setLiveSourceInput(capture->getLiveSourceOutput());
00437     
00438     /* 3.) Add the filter(s) into the pipeline in the order they will 
00439      * be used */
00440     track_pipeline->add(gauss);
00441     
00442     blob_find->set(&blob_this_color,&threshold,1,&outcolor,1,1,min_size);
00443     track_pipeline->add(blob_find);
00444          
00445     rc = blob_data.connect(blob_find->getLiveBlobOutput());
00446     phCHECK_RC(rc,NULL,"blob_data.connect()");
00447          
00448     /* 4.) Startup the TRACK system */
00449     rc = track_system.startup();
00450     phPRINT_RC(rc,NULL,"track_system.startup()");
00451     
00452     /* 5.) Keep going until all the windows are closed */
00453     displaysOpen = 1;
00454     while (displaysOpen)
00455     {
00456         //capture->getImage(tempimage);
00457 #if 0
00458         track_pipeline->copyInputImage(tempimage);
00459         if (tempimage.isNull() == 0)
00460             tempimage.save("tempin.ppm");
00461 
00462         track_pipeline->copyOutputImage(tempimage);
00463         if (tempimage.isNull() == 0)
00464             tempimage.save("tempout.ppm");
00465 #endif
00466 
00467         if (glbl_print_blobs)
00468         {
00469             /* Get the most recent blob data */
00470             rc = blob_data.update();
00471             phPRINT_RC(rc,NULL,"blob_data->update()");
00472             
00473             if ((rc == phLiveObjectUPDATED) && 
00474                 (blob_data.getTotalBlobs(min_size)))
00475             {
00476                 blob_data.print_data(min_size);
00477             }
00478         }
00479         
00480         /* Yielding is optional. This gives up the thread's timeslice
00481          * to prevent slow response in other threads. It consumes more
00482          * CPU cycles than sleeping. Use it instead of sleeping if
00483          * this loop is processing anything */
00484         
00485         phYield();
00486 
00487         if (nTrackDisplays > 0)
00488         {
00489             displaysOpen = 0;
00490             for (i = 0; (i < nTrackDisplays) && (displaysOpen == 0); i++)
00491             {
00492                 if (track_display[i]->isOpen() == 1)
00493                 {
00494                     displaysOpen = 1;
00495                 }
00496             }
00497         }
00498         
00499         /* Remove this if block when using this code as an example */
00500         /* Set the loop control value to end the loop when testing */
00501         if (test > 0)
00502         { 
00503             if (test_loop_count > count)
00504             {
00505                 displaysOpen = 0;
00506                 phSleep(test); /* test's value should be a time (in secs) value > 0*/
00507             }
00508             test_loop_count++;
00509         }
00510     }
00511     
00512     /* 6.) Shutdown the system */
00513     rc = track_system.shutdown();
00514     phPRINT_RC(rc,NULL,"track_system.shutdown()");
00515 
00516 error:
00517     rc = blob_data.disconnect();
00518     phPRINT_RC(rc,NULL,"blob_data.disconnect()");
00519     
00520 
00521     for (i = 0; (i < nTrainDisplays) && (train_display != NULL); i++)
00522     {
00523         phDelete(train_display[i]);
00524     }
00525   
00526     phDeleteArray(train_display);
00527 
00528     for (i = 0; (i < nTrackDisplays) && (track_display != NULL); i++)
00529     {
00530         phDelete(track_display[i]);
00531     }
00532    
00533     phDeleteArray(track_display);
00534 
00535     phDelete(convert);
00536     phDelete(gauss);
00537     phDelete(blob_find);
00538     phDelete(histogram);
00539     
00540     phDelete(train_pipeline);
00541     phDelete(track_pipeline);
00542     
00543     phDelete(capture);
00544 
00545     phFree(capture_path);
00546     phDelete(arg_parser);
00547 
00548     return phSUCCESS;
00549 }




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:05 2007 for phission by  doxygen 1.4.4