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

blob_Filter.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission :
00003         Realtime Vision Processing System
00004 
00005     Copyright (C) 2003-2006 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     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #include <phStandard.h>
00031 
00032 #include <blob_Filter.h>
00033 
00034 #include <phError.h>
00035 #include <phMemory.h>
00036 #include <phPrint.h>
00037 
00038 #define TIMESTUFF() 0
00039 
00040 /* ---------------------------------------------------------------------- */
00041 blob_Filter::blob_Filter() :
00042     phFilter("blob_Filter")
00043 {
00044     phFUNCTION("blob_Filter::blob_Filter")
00045     int locked = 0;
00046     
00047     phTHIS_LOOSE_LOCK(locked);
00048     
00049     /* Set the list of acceptable input formats */
00050     /* Can only process/histogram packed image formats; i.e. where all the
00051      * channels are grouped together for each pixel */
00052     this->m_format = phImagePackedFormatMask;
00053    
00054     this->m_incolor         = NULL;
00055     this->m_incolor_size    = 0;
00056     this->m_threshold       = NULL;
00057     this->m_threshold_size  = 0;
00058     this->m_outcolor        = NULL;
00059     this->m_outputFormat    = this->m_inputFormat = phImageNOFORMAT;
00060 
00061     this->m_nColors = 0;
00062 
00063     this->m_data = NULL;
00064     rc = phblob_data_new(&(this->m_data));
00065     phPRINT_RC(rc,NULL,"phblob_data_new");
00066 
00067     /* Initialize the argument structure that gets passed to
00068      * phblob_find_line_segments */
00069     /*
00070     this->m_args.imgptr                = NULL;
00071     this->m_args.width                 = 1;
00072     this->m_args.height                = 1;
00073     this->m_args.depth                 = 1;
00074     this->m_args.format                = phImageNOFORMAT;
00075     this->m_args.color_count           = 0;
00076     */
00077     this->m_args.incolor               = &(this->m_incolor);
00078     this->m_args.threshold             = &(this->m_threshold);
00079     this->m_args.nColors               = &(this->m_nColors);
00080 
00081     this->m_lower_threshold = phColorArray32_new(5,5,5,0);
00082     this->m_upper_threshold = phColorArray32_new(5,5,5,0);
00083     this->m_loop_threshold  = phColorArray32_new(1,0,0,0);
00084     blob_Filter::phColor_to_int32_array(this->m_lower_threshold,
00085                                         (int32_t*)this->m_lower_thresh);
00086     blob_Filter::phColor_to_int32_array(this->m_upper_threshold,
00087                                         (int32_t*)this->m_upper_thresh);
00088     blob_Filter::phColor_to_int32_array(this->m_loop_threshold,
00089                                         (int32_t*)this->m_loop_thresh);
00090 
00091     this->setOutcolor(phColor32_new(phColorTypeArray,128,128,128,0));
00092 
00093     phTHIS_LOOSE_UNLOCK(locked);
00094 }
00095 
00096 /* ---------------------------------------------------------------------- */
00097 blob_Filter::blob_Filter(phColor    lower_threshold,
00098                          phColor    upper_threshold,
00099                          phColor    loop_threshold,
00100                          phColor    outcolor,
00101                          int        draw_rects,
00102                          int        color_blobs,
00103                          uint32_t   color_min_size ) :
00104     phFilter("blob_Filter")
00105 {
00106     phFUNCTION("blob_Filter::blob_Filter")
00107     int locked = 0;
00108     
00109     phTHIS_LOOSE_LOCK(locked);
00110 
00111     ::blob_Filter();
00112    
00113     this->set( lower_threshold, upper_threshold, loop_threshold,
00114                outcolor, draw_rects, color_blobs, color_min_size );
00115     
00116     phTHIS_LOOSE_UNLOCK(locked);
00117 }
00118 
00119 /* ---------------------------------------------------------------------- */
00120 blob_Filter::blob_Filter(phColor   *incolor,
00121                          phColor   *threshold,
00122                          uint32_t   nColors,
00123                          phColor   *outcolor,
00124                          int        draw_rects,
00125                          int        color_blobs,
00126                          uint32_t   color_min_size ) :
00127     phFilter("blob_Filter")
00128 {
00129     phFUNCTION("blob_Filter::blob_Filter")
00130     int locked = 0;
00131     
00132     phTHIS_LOOSE_LOCK(locked);
00133    
00134     ::blob_Filter();
00135    
00136     this->set( incolor, threshold, 
00137                nColors, 
00138                outcolor, 
00139                draw_rects, color_blobs, color_min_size );
00140     
00141     phTHIS_LOOSE_UNLOCK(locked);
00142 }
00143 
00144 /* ---------------------------------------------------------------------- */
00145 blob_Filter::~blob_Filter()
00146 {
00147     phFUNCTION("blob_Filter::~blob_Filter")
00148     int locked = 0;
00149     
00150     phTHIS_LOOSE_LOCK(locked);
00151     
00152     rc = phblob_data_free(&(this->m_data));
00153     phPRINT_RC(rc,NULL,"phblob_data_free");
00154 
00155     phFree(this->m_threshold);
00156     phFree(this->m_incolor);
00157     phFree(this->m_outcolor);
00158     
00159     phTHIS_LOOSE_UNLOCK(locked);
00160 }
00161 
00162 /* ------------------------------------------------------------------------ */
00163 phFilter *blob_Filter::cloneFilter()
00164 {
00165     phFUNCTION("blob_Filter::cloneFilter")
00166     int locked = 0;
00167 
00168     blob_Filter *valret = NULL;
00169     
00170     phTHIS_LOOSE_LOCK(locked);
00171     
00172     if (this->m_neighborblob == 0)
00173     {
00174         valret =  new blob_Filter(this->m_incolor,
00175                                   this->m_threshold,
00176                                   this->m_nColors,
00177                                   this->m_outcolor,
00178                                   this->m_draw_rects,
00179                                   this->m_color_blobs,
00180                                   this->m_color_min_size
00181                                   );
00182     }
00183     else
00184     {
00185         phColor outcolor = phColorArray32_new(255,0,0,0);
00186         if (this->m_outcolor != NULL)
00187             outcolor = *(this->m_outcolor);
00188         valret =  new blob_Filter(this->m_lower_threshold,
00189                                   this->m_upper_threshold,
00190                                   this->m_loop_threshold,
00191                                   outcolor,
00192                                   this->m_draw_rects,
00193                                   this->m_color_blobs,
00194                                   this->m_color_min_size
00195                                   );
00196     }
00197     
00198     phTHIS_LOOSE_UNLOCK(locked);
00199 
00200     return (phFilter *)valret;
00201 }
00202 
00203 /* ---------------------------------------------------------------------- */
00204 int blob_Filter::reset()
00205 {
00206     phFUNCTION("blob_Filter::reset")
00207     int locked = 0;
00208     
00209     phTHIS_LOOSE_LOCK(locked);
00210    
00211     rc = this->m_blobData.reset();
00212     phPRINT_RC(rc,NULL,"this->m_blobData.reset()");
00213     
00214     rc = this->removeColors();
00215     phPRINT_RC(rc,NULL,"this->removeColors()");
00216     
00217     rc = this->setLowerThreshold(phColorArray32_new(5,5,5,0));
00218     phPRINT_RC(rc,NULL,"this->setLowerThreshold()");
00219 
00220     rc = this->setUpperThreshold(phColorArray32_new(5,5,5,0));
00221     phPRINT_RC(rc,NULL,"this->setUpperThreshold()");
00222     
00223     rc = this->setLoopThreshold(phColorArray32_new(1,0,0,0));
00224     phPRINT_RC(rc,NULL,"this->setLoopThreshold()");
00225 
00226     phTHIS_LOOSE_UNLOCK(locked);
00227 
00228     return phSUCCESS;
00229 }
00230 
00231 /* ---------------------------------------------------------------------- */
00232 int blob_Filter::set(phColor    lower_threshold,
00233                      phColor    upper_threshold,
00234                      phColor    loop_threshold )
00235 {
00236     phFUNCTION("blob_Filter::set")
00237     int         locked  = 0;
00238     
00239     phTHIS_LOOSE_LOCK(locked);
00240    
00241     rc = this->setLowerThreshold(lower_threshold);
00242     phPRINT_RC(rc,NULL,"this->setLowerThreshold()");
00243 
00244     rc = this->setUpperThreshold(upper_threshold);
00245     phPRINT_RC(rc,NULL,"this->setUpperThreshold()");
00246     
00247     rc = this->setLoopThreshold(loop_threshold);
00248     phPRINT_RC(rc,NULL,"this->setLoopThreshold()");
00249        
00250     this->m_neighborblob = 1;
00251     
00252     phTHIS_LOOSE_UNLOCK(locked);
00253 
00254     return phSUCCESS;
00255 #if 0
00256 error:
00257     phTHIS_ERROR_UNLOCK(locked);
00258 
00259     return phFAIL;
00260 #endif
00261 }
00262 
00263 /* ---------------------------------------------------------------------- */
00264 int blob_Filter::set(phColor    lower_threshold,
00265                      phColor    upper_threshold,
00266                      phColor    loop_threshold,
00267                      phColor    outcolor,
00268                      int        draw_rects,
00269                      int        color_blobs,
00270                      uint32_t   color_min_size )
00271 {
00272     phFUNCTION("blob_Filter::set")
00273     int         locked  = 0;
00274     
00275     phTHIS_LOOSE_LOCK(locked);
00276 
00277     rc = this->set(lower_threshold,upper_threshold,loop_threshold);
00278     phPRINT_RC(rc,NULL,"this->set(phColor,phColor,phColor)");
00279    
00280     rc = this->setOutcolor(outcolor);
00281     phPRINT_RC(rc,NULL,"this->setOutcolor");
00282     
00283     this->m_draw_rects      = draw_rects;
00284     this->m_color_blobs     = color_blobs;
00285     this->m_color_min_size  = color_min_size;
00286   
00287     this->m_neighborblob = 1;
00288     
00289     phTHIS_LOOSE_UNLOCK(locked);
00290 
00291     return phSUCCESS;
00292 #if 0
00293 error:
00294     phTHIS_ERROR_UNLOCK(locked);
00295 
00296     return phFAIL;
00297 #endif
00298 }
00299 
00300 /* ---------------------------------------------------------------------- */
00301 int blob_Filter::set(phColor   *incolor,
00302                      phColor   *threshold,
00303                      uint32_t   nColors,
00304                      phColor   *outcolor,
00305                      int        draw_rects,
00306                      int        color_blobs,
00307                      uint32_t   color_min_size )
00308 {
00309     phFUNCTION("blob_Filter::set")
00310     int         locked  = 0;
00311     uint32_t    i       = 0;
00312     uint32_t    type    = 0;
00313     
00314     phTHIS_LOOSE_LOCK(locked);
00315     
00316     if (nColors > 0)
00317     {
00318         /* check to make sure all the input colors are the same */
00319         type  = incolor[0].type;
00320         for (i = 1; i < nColors; i++ )
00321         {
00322             if ((type != incolor[i].type) && 
00323                 (type != phColorTypeArray) &&
00324                 (incolor[i].type != phColorTypeArray))
00325                       
00326             {
00327                 phCHECK_RC(rc,NULL,"All input colors must be of the same type."
00328                          "Input Color [%d]:%lu doesn't match Input Color [0]:%lu",
00329                          i,(long unsigned)incolor[i].type,(long unsigned)type );
00330             }
00331         }
00332         /* always make sure they have the same amount of memory and
00333          * enough memory for indexing in nColors */
00334         phDALLOC_RESIZE(this->m_incolor,
00335                         this->m_incolor_size,
00336                         nColors,
00337                         phColor );
00338         phDALLOC_RESIZE(this->m_threshold,
00339                         this->m_threshold_size,
00340                         nColors,
00341                         phColor );
00342         
00343         if (incolor != NULL)
00344         {
00345             phMemcpy(this->m_incolor, incolor,
00346                     nColors * sizeof(phColor));
00347         }
00348         
00349         if (threshold != NULL)
00350         {
00351             phMemcpy(this->m_threshold, threshold,
00352                    nColors * sizeof(phColor));
00353         }
00354 
00355         /* This assumes that all the rest of the input colors are the same.
00356          * A assumption based on the fact this function will fail 
00357          * if they aren't all the same. */
00358         /* Not supported */
00359         if ((this->m_incolor[0].type == phColorTypeArray) ||
00360             (this->m_incolor[0].type == phColorTypeYUV9))
00361         {
00362             this->m_inputFormat = phImageNOFORMAT;
00363             /*
00364             phERR_PRINT("incolor: unsupported Color Type."
00365                       "unexpected results may occur.\n");
00366              */
00367         }
00368         else
00369         {
00370             this->m_inputFormat = phColorToFormat(this->m_incolor[0]);
00371         }
00372     }
00373     
00374     this->m_nColors = nColors;
00375     
00376     #if 0
00377     /* Warn the user about a mismatch between in color and thresholds */
00378     for (i = 0; i < this->m_nColors; i++)
00379     {
00380         /*
00381         if (this->m_threshold[i].type != this->m_incolor[i].type)
00382         {
00383             phERR_PRINT("threshold[%lu]:%lu:%s type isn't the same as "
00384                     "incolor[%lu]:%lu:%s type. "
00385                     "This may cause errors in matching.\n",
00386                     (long unsigned)i,
00387                     (long unsigned)this->m_threshold[i].type,
00388                     phColorToString(this->m_threshold[i]),
00389                     (long unsigned)i,
00390                     (long unsigned)this->m_incolor[i].type,
00391                     phColorToString(this->m_incolor[i])
00392                     );
00393         }
00394         */
00395     }
00396     #endif
00397  
00398     if (outcolor != NULL)
00399     {
00400         rc = this->setOutcolor(*outcolor);
00401         phPRINT_RC(rc,NULL,"this->setOutcolor");
00402     }
00403     
00404     this->m_draw_rects      = draw_rects;
00405     this->m_color_blobs     = color_blobs;
00406     this->m_color_min_size  = color_min_size;
00407 
00408     this->m_neighborblob = 0;
00409     
00410     phTHIS_LOOSE_UNLOCK(locked);
00411 
00412     return phSUCCESS;
00413 error:
00414     phTHIS_ERROR_UNLOCK(locked);
00415 
00416     return phFAIL;
00417 }
00418 
00419 /* ---------------------------------------------------------------------- */
00420 int blob_Filter::setDrawRects(uint32_t draw_rects )
00421 {
00422     phFUNCTION("blob_Filter::setDrawRects")
00423     int locked = 0;
00424     
00425     phTHIS_LOOSE_LOCK(locked);
00426     
00427     this->m_draw_rects      = draw_rects;
00428 
00429     phTHIS_LOOSE_UNLOCK(locked);
00430 
00431     return phSUCCESS;
00432 /*
00433 error:
00434     rc = this->unlock();
00435 
00436     return phFAIL;
00437 */
00438 }
00439 
00440 /* ---------------------------------------------------------------------- */
00441 int blob_Filter::setColorBlobs(uint32_t color_blobs )
00442 {
00443     phFUNCTION("blob_Filter::setColorBlobs")
00444     int locked = 0;
00445     
00446     phTHIS_LOOSE_LOCK(locked);
00447     
00448     this->m_color_blobs     = color_blobs;
00449 
00450     phTHIS_LOOSE_UNLOCK(locked);
00451 
00452     return phSUCCESS;
00453 /*
00454 error:
00455     rc = this->unlock();
00456 
00457     return phFAIL;
00458 */
00459 }
00460 
00461 /* ---------------------------------------------------------------------- */
00462 int blob_Filter::setColorMinSize( uint32_t color_min_size )
00463 {
00464     phFUNCTION("blob_Filter::setColorMinSize")
00465     int locked = 0;
00466     
00467     phTHIS_LOOSE_LOCK(locked);
00468 
00469     this->m_color_min_size = color_min_size;
00470     
00471     phTHIS_LOOSE_UNLOCK(locked);
00472 
00473     return phSUCCESS;
00474 }
00475 
00476 /* ---------------------------------------------------------------------- */
00477 int blob_Filter::setOutcolor(phColor outcolor )
00478 {
00479     phFUNCTION("blob_Filter::setOutcolor")
00480     int locked = 0;
00481     
00482     phTHIS_LOOSE_LOCK(locked);
00483  
00484     phDALLOC_RESIZE(this->m_outcolor,
00485                     this->m_outcolor_size,
00486                     1,
00487                     phColor );
00488     this->m_outcolor[0] = outcolor;
00489  
00490     if (this->m_outcolor[0].type == phColorTypeYUV9)
00491     {
00492         this->m_outputFormat = phImageNOFORMAT;
00493             
00494         /*
00495         phERR_PRINT("outcolor: unsupported Color Type. "
00496                   "unexpected results may occur.\n");
00497          */
00498     }
00499     else
00500     {
00501         this->m_outputFormat = phColorToFormat(this->m_outcolor[0]);
00502     }
00503     
00504     phTHIS_LOOSE_UNLOCK(locked);
00505 
00506     return phSUCCESS;
00507 error:
00508     phTHIS_ERROR_UNLOCK(locked);
00509 
00510     return phFAIL;
00511 }
00512 
00513 /* ---------------------------------------------------------------------- */
00514 void blob_Filter::phColor_to_int32_array(phColor color,int32_t *array)
00515 {
00516     int i = 0;
00517     if (array != NULL)
00518         for (i = 0; i < phCOLOR_MAXELEMS; i++ )
00519             array[i] = (int32_t)color.array.v[i];
00520 }
00521 
00522 /* ---------------------------------------------------------------------- */
00523 int blob_Filter::setNeighborBlob( int neighborblob )
00524 {
00525     phFUNCTION("blob_Filter::setNeighborBlob")
00526     int locked = 0;
00527 
00528     phTHIS_LOCK(locked);
00529 
00530     this->m_neighborblob = neighborblob;
00531 
00532     phTHIS_UNLOCK(locked);
00533 
00534     return phSUCCESS;
00535 error:
00536     phTHIS_ERROR_UNLOCK(locked);
00537 
00538     return phFAIL;
00539 }
00540 /* ---------------------------------------------------------------------- */
00541 int blob_Filter::setThresholds( phColor lower_threshold,
00542                                     phColor upper_threshold,
00543                                     phColor loop_threshold )
00544 {
00545     phFUNCTION("blob_Filter::setThresholds")
00546     int locked = 0;
00547 
00548     phTHIS_LOCK(locked);
00549 
00550     this->m_lower_threshold = lower_threshold;
00551     blob_Filter::phColor_to_int32_array(this->m_lower_threshold,
00552                                             (int32_t*)this->m_lower_thresh);
00553 
00554     this->m_upper_threshold = upper_threshold;
00555     blob_Filter::phColor_to_int32_array(this->m_upper_threshold,
00556                                             (int32_t*)this->m_upper_thresh);
00557 
00558     this->m_loop_threshold = loop_threshold;
00559     blob_Filter::phColor_to_int32_array(this->m_loop_threshold,
00560                                             (int32_t*)this->m_loop_thresh);
00561 
00562     phTHIS_UNLOCK(locked);
00563 
00564     return phSUCCESS;
00565 error:
00566     phTHIS_ERROR_UNLOCK(locked);
00567 
00568     return phFAIL;
00569 }
00570 /* ---------------------------------------------------------------------- */
00571 int blob_Filter::setLowerThreshold( phColor lower_threshold )
00572 {
00573     phFUNCTION("blob_Filter::setLowerThreshold")
00574     int locked = 0;
00575 
00576     phTHIS_LOCK(locked);
00577 
00578     this->m_lower_threshold = lower_threshold;
00579     blob_Filter::phColor_to_int32_array(this->m_lower_threshold,
00580                                             (int32_t*)this->m_lower_thresh);
00581 
00582     phTHIS_UNLOCK(locked);
00583 
00584     return phSUCCESS;
00585 error:
00586     phTHIS_ERROR_UNLOCK(locked);
00587 
00588     return phFAIL;
00589 }
00590 
00591 /* ---------------------------------------------------------------------- */
00592 int blob_Filter::setUpperThreshold( phColor upper_threshold )
00593 {
00594     phFUNCTION("blob_Filter::setUpperThreshold")
00595     int locked = 0;
00596 
00597     phTHIS_LOCK(locked);
00598 
00599     this->m_upper_threshold = upper_threshold;
00600     blob_Filter::phColor_to_int32_array(this->m_upper_threshold,
00601                                             (int32_t*)this->m_upper_thresh);
00602 
00603     phTHIS_UNLOCK(locked);
00604 
00605     return phSUCCESS;
00606 error:
00607     phTHIS_ERROR_UNLOCK(locked);
00608 
00609     return phFAIL;
00610 }
00611 
00612 /* ---------------------------------------------------------------------- */
00613 int blob_Filter::setLoopThreshold( phColor loop_threshold )
00614 {
00615     phFUNCTION("blob_Filter::setLoopThreshold")
00616     int locked = 0;
00617 
00618     phTHIS_LOCK(locked);
00619 
00620     this->m_loop_threshold = loop_threshold;
00621     blob_Filter::phColor_to_int32_array(this->m_loop_threshold,
00622                                             (int32_t*)this->m_loop_thresh);
00623 
00624     phTHIS_UNLOCK(locked);
00625 
00626     return phSUCCESS;
00627 error:
00628     phTHIS_ERROR_UNLOCK(locked);
00629 
00630     return phFAIL;
00631 }
00632 
00633  
00634 /* ---------------------------------------------------------------------- */
00635 int blob_Filter::setColor( phColor incolor,
00636                            phColor threshold )
00637 {
00638     phFUNCTION("blob_Filter::setColor")
00639     int locked = 0;
00640     
00641     phTHIS_LOOSE_LOCK(locked);
00642     
00643     this->m_nColors = 0;
00644     if (this->m_nColors == 0)
00645     {
00646         /* This assumes that all the rest of the input colors are the same.
00647          * A assumption based on the fact this function will fail 
00648          * if they aren't all the same. */
00649             
00650         /* Not supported */
00651         if ((incolor.type == phColorTypeArray) ||
00652             (incolor.type == phColorTypeYUV9))
00653         {
00654             this->m_inputFormat = phImageNOFORMAT;
00655         }
00656         else
00657         {
00658             this->m_inputFormat = phColorToFormat(incolor);
00659         }
00660     }
00661 
00662     this->m_nColors++;
00663     phDALLOC_RESIZE(this->m_incolor, this->m_incolor_size,
00664                     this->m_nColors, phColor );
00665     phDALLOC_RESIZE(this->m_threshold, this->m_threshold_size,
00666                     this->m_nColors, phColor );
00667     this->m_incolor[this->m_nColors -1] = incolor;
00668     this->m_threshold[this->m_nColors -1] = threshold;
00669     
00670     phTHIS_LOOSE_UNLOCK(locked);
00671 
00672     return phSUCCESS;
00673 error:
00674     phTHIS_ERROR_UNLOCK(locked);
00675 
00676     return phFAIL;
00677 }
00678 
00679 /* ---------------------------------------------------------------------- */
00680 int blob_Filter::addColor(phColor incolor,
00681                           phColor threshold )
00682 {
00683     phFUNCTION("blob_Filter::addColor")
00684     int         locked  = 0;
00685     uint32_t    i       = 0;
00686     
00687     phTHIS_LOOSE_LOCK(locked);
00688     
00689     if (this->m_nColors == 0)
00690     {
00691         /* This assumes that all the rest of the input colors are the same.
00692          * A assumption based on the fact this function will fail 
00693          * if they aren't all the same. */
00694             
00695         /* Not supported */
00696         if ((incolor.type == phColorTypeArray) ||
00697             (incolor.type == phColorTypeYUV9))
00698         {
00699             this->m_inputFormat = phImageNOFORMAT;
00700             /*
00701             phERR_PRINT("incolor: unsupported Color Type. "
00702                       "unexpected results may occur.\n");
00703              */
00704         }
00705         else
00706         {
00707             this->m_inputFormat = phColorToFormat(incolor);
00708         }
00709     }
00710 
00711     this->m_nColors++;
00712     phDALLOC_RESIZE(this->m_incolor, this->m_incolor_size,
00713                     this->m_nColors, phColor );
00714     phDALLOC_RESIZE(this->m_threshold, this->m_threshold_size,
00715                     this->m_nColors, phColor );
00716     this->m_incolor[this->m_nColors -1] = incolor;
00717     this->m_threshold[this->m_nColors -1] = threshold;
00718   
00719 /*
00720     if (threshold.type != incolor.type)
00721     {
00722         phERR_PRINT("threshold:%lu:%s type isn't the same as "
00723                   "incolor:%lu:%s type. "
00724                   "This may cause errors in matching.\n",
00725                   (long unsigned)threshold.type,
00726                   phColorToString(threshold),
00727                   (long unsigned)incolor.type,
00728                   phColorToString(incolor)
00729                 );
00730     }
00731 */
00732     phTHIS_LOOSE_UNLOCK(locked);
00733 
00734     return phSUCCESS;
00735 error:
00736     phTHIS_ERROR_UNLOCK(locked);
00737 
00738     return phFAIL;
00739 }
00740 
00741 /* ---------------------------------------------------------------------- */
00742 int blob_Filter::replaceColor(phColor old_incolor,
00743                               phColor old_threshold,
00744                               phColor new_incolor,
00745                               phColor new_threshold )
00746 {
00747     phFUNCTION("blob_Filter::replaceColor")
00748     int         locked  = 0;
00749     uint32_t    i       = 0;
00750     uint32_t    replaced= 0;
00751     
00752     phTHIS_LOOSE_LOCK(locked);
00753 
00754     if (this->m_nColors > 0)
00755     {
00756         for (i = 0; (i < this->m_nColors) && (replaced == 0); i++ )
00757         {
00758             if (phColorEqual(this->m_incolor[i],    old_incolor  ) && 
00759                 phColorEqual(this->m_threshold[i],  old_threshold))
00760             {
00761                 this->m_incolor[i] = new_incolor;
00762                 this->m_threshold[i] = new_threshold;
00763 
00764                 /* This assumes that all the rest of the input colors are the same.
00765                  * An assumption based on the fact this function will fail 
00766                  * if they aren't all the same. */
00767                 
00768                 /* Not supported */
00769                 if ((new_incolor.type == phColorTypeArray) ||
00770                     (new_incolor.type == phColorTypeYUV9))
00771                 {
00772                     this->m_inputFormat = phImageNOFORMAT;
00773                     /*
00774                     phERR_PRINT("incolor: unsupported Color Type. "
00775                               "unexpected results may occur.\n");
00776                      */
00777                 }
00778                 else
00779                 {
00780                     this->m_inputFormat = phColorToFormat(new_incolor);
00781                 }
00782             }
00783 /*
00784             if (new_threshold.type != new_incolor.type)
00785             {
00786                 phERR_PRINT("new_threshold:%lu:%s type isn't the same as "
00787                           "new_incolor:%lu:%s type. "
00788                           "This may cause errors in matching.\n",
00789                           (long unsigned)new_threshold.type,
00790                           phColorToString(new_threshold),
00791                           (long unsigned)new_incolor.type,
00792                           phColorToString(new_incolor)
00793                          );
00794             }
00795 */
00796             replaced = 1;
00797         }
00798     }
00799     
00800     phTHIS_LOOSE_UNLOCK(locked);
00801 
00802     return (replaced == 1 ? phSUCCESS : phFAIL);
00803 /*
00804 error:
00805     phTHIS_ERROR_UNLOCK(locked);
00806 
00807     return phFAIL;
00808 */
00809 }
00810 
00811 /* ---------------------------------------------------------------------- */
00812 int blob_Filter::removeColor(phColor incolor,
00813                              phColor threshold )
00814 {
00815     phFUNCTION("blob_Filter::removeColor")
00816     int         locked  = 0;
00817     uint32_t    i       = 0;
00818     uint32_t    removed = 0;
00819     
00820     phTHIS_LOOSE_LOCK(locked);
00821 
00822     if (this->m_nColors > 0)
00823     {
00824         for (i = 0; (i < this->m_nColors) && (removed == 0); i++ )
00825         {
00826             if (phColorEqual(this->m_incolor[i],    incolor  ) && 
00827                 phColorEqual(this->m_threshold[i],  threshold))
00828             {
00829                 /* Copy the end of the list over the removed color */
00830                 /* Ex:
00831                  *
00832                  *  [0][1][2][3][4]
00833                  *           ^------remove this
00834                  *           i == 3
00835                  *           m_nColors == 5
00836                  *            copyCount == 5 - ( 3 + 1 ) == 5 - 4 == 1 
00837                  */
00838                              
00839                 uint32_t copyCount = (this->m_nColors - (i+1));
00840 
00841                 if (copyCount > 0)
00842                 {
00843                     phMemcpy(&(this->m_incolor[i]),   &(this->m_incolor[i + 1]),  copyCount);
00844                     phMemcpy(&(this->m_threshold[i]), &(this->m_threshold[i + 1]),copyCount);
00845                 }
00846                 
00847                 this->m_nColors--;
00848 
00849                 if (this->m_nColors > 0)
00850                 {                
00851                     /* This will shrink the memory of the list down if it needs to be */
00852                     phDALLOC_RESIZE(this->m_incolor,    this->m_incolor_size,
00853                                     this->m_nColors,    phColor );
00854                     phDALLOC_RESIZE(this->m_threshold,  this->m_threshold_size,
00855                                     this->m_nColors,    phColor );
00856                 }
00857                 else
00858                 {
00859                     this->m_inputFormat = phImageNOFORMAT;
00860                 }
00861                     
00862                 removed = 1;
00863             }
00864         }
00865     }
00866     
00867     phTHIS_LOOSE_UNLOCK(locked);
00868 
00869     return (removed == 1 ? phSUCCESS : phFAIL);
00870 error:
00871     phTHIS_ERROR_UNLOCK(locked);
00872 
00873     return phFAIL;
00874 }
00875 
00876 /* ---------------------------------------------------------------------- */
00877 int blob_Filter::removeColors()
00878 {
00879     phFUNCTION("blob_Filter::removeColors")
00880     int locked = 0;
00881     
00882     phTHIS_LOOSE_LOCK(locked);
00883     
00884     phFree(this->m_threshold);
00885     phFree(this->m_incolor);
00886     phFree(this->m_outcolor);
00887 
00888     this->m_nColors         = 0;
00889     this->m_incolor_size    = 0;
00890     this->m_threshold_size  = 0;
00891     this->m_outputFormat    = this->m_inputFormat = phImageNOFORMAT;
00892 
00893     phTHIS_LOOSE_UNLOCK(locked);
00894 
00895     return phSUCCESS;
00896 }
00897 
00898 
00899 /* ---------------------------------------------------------------------- */
00900 int blob_Filter::getBlobData( phBlobData &blobData )
00901 {
00902     int rc = 0;
00903 
00904     rc = blobData.copy(this->m_blobData);
00905 
00906     return rc;
00907 }
00908     
00909 /* ---------------------------------------------------------------------- */
00910 phLiveObject *blob_Filter::getLiveBlobOutput() 
00911 {
00912     return (phLiveObject *)&(this->m_blobData);
00913 }
00914 
00915 /* ---------------------------------------------------------------------- */
00916 /* Definitions:
00917  *      Line Segment: 
00918  *          a series of horizontal neighboring pixels that match a color 
00919  *          value within a given threshold.
00920  *          Line segments are connected to each other only if they overlap.
00921  *          
00922  *      Blob Group:
00923  *          a group of line segments that can be reached through any 
00924  *          other line segment using the line segment pointer connections
00925  *          made during 
00926  *          
00927  * This filter involves the implementation of several steps:
00928  *
00929  *  1.) Line segment discovery 
00930  *  2.) Line segment connecting
00931  *  3.) Blob identification
00932  *  4.) Image Blob Colorizing 
00933  *  5.) Rectangle outlining of the rectangles
00934  */
00935 /* ---------------------------------------------------------------------- */
00936 int blob_Filter::filter()
00937 {
00938     phFUNCTION("blob_Filter::blob")
00939 
00940     /* Defined by phFilter:
00941      * width
00942      * height
00943      * depth (for RGB variations only)
00944      * format
00945      * Image
00946      *
00947      * Object is locked prior to calling the filter() method
00948      * */
00949     /*phblob_find_args find_args;*/
00950     
00951 #if TIMESTUFF()
00952     uint32_t       timestamp = 0;
00953     const uint32_t nStamps = 7;
00954     char *tags[nStamps] = {
00955         "phblob_find_line_segments_x",
00956         "phblob_link_line_segments",
00957         "phblob_create_blobs",
00958         "phblob_sort_blobs",
00959         "phBlobData->setData()",
00960         "phblob_color_lines",
00961         "phblob_draw_blob_rects"
00962     };
00963     ph_time_db      timedb = NULL;
00964     rc = ph_timedb_alloc(&timedb,"blob_Filter");
00965     phPRINT_RC(rc,NULL,"ph_timedb_alloc");
00966 #endif /* TIMESTUFF() */
00967     
00968     phImage     tempImage;
00969     uint8_t    *imgptr              = (uint8_t*)Image;
00970     uint32_t    imgformat           = format;
00971     uint8_t     imgdepth            = depth;
00972     uint32_t    input_format        = this->m_inputFormat;
00973     uint32_t    output_format       = this->m_outputFormat;
00974     uint32_t    final_output_format = this->m_outputFormat;
00975    
00976     /* Make sure there is a color to match against */
00977     if ((this->m_nColors <= 0) && (this->m_neighborblob == 0))
00978     {
00979 #if TIMESTUFF() /* phTIME_REPORT_ALL & */
00980         if (timedb)
00981         {
00982             rc = ph_timedb_free(&timedb);
00983             phPRINT_RC(rc,NULL,"ph_timedb_free");
00984         }
00985 #endif
00986         return phFAIL;
00987         /* phCHECK_RC(-1,NULL,"No color to match against"); */
00988     }
00989    
00990     /* Make sure the user properly initialized this filter */
00991     if ((!this->m_neighborblob) && (input_format == (uint32_t)phImageNOFORMAT))
00992     {
00993         phERR_PRINT("(%s) Warning: input format not set properly. \n",
00994                     this->getName());
00995         /*
00996         phCHECK_RC(-1,NULL,"input format not set properly. "
00997                  "Must set the color(s) to match.");
00998                  */
00999     }
01000     
01001     /* 0.) Make sure the input format to the phblob_find_line_segments
01002      * function is compatible with the incolor format */
01003     /* if there is no set color, just use the incoming format */
01004     if ((input_format != format) &&
01005         (input_format != (uint32_t)phImageNOFORMAT))
01006     {
01007         rc = tempImage.setImage(*this->m_workspaceImage);
01008         phCHECK_RC(rc,NULL,"Error setting temp image.");
01009         
01010         /* rc == 0 means conversion happened */
01011         /* rc == 1 means no conversion */
01012         rc = tempImage.convert(input_format);
01013         phCHECK_RC(rc,NULL,"Error converting image");
01014         
01015         imgptr      = (uint8_t *)tempImage.getData();        
01016         imgformat   = input_format;
01017         imgdepth    = depth;
01018     }
01019     
01020     /* -------------------------------------------------------------------- */
01021     /* 1.) Find all the line segments in the rows of the image */    
01022     /* -------------------------------------------------------------------- */
01023 #if TIMESTUFF()
01024     rc = ph_timedb_start(timedb,tags[0]);
01025     phPRINT_RC(rc,NULL,"ph_timedb_start");
01026 #endif
01027     /* XXX: Why &imgptr ? */
01028     this->m_args.imgptr    = &imgptr;
01029     this->m_args.width     = width;
01030     this->m_args.height    = height;
01031     this->m_args.depth     = imgdepth;
01032     this->m_args.format    = imgformat;
01033 
01034     if (this->m_neighborblob == 0)
01035     {
01036         rc = phblob_find_line_segments_color(&this->m_args,
01037                                              this->m_data);
01038         phCHECK_RC(rc,NULL,"phblob_find_line_segments failed.");
01039     }
01040     else
01041     {
01042         phMemcpy(this->m_args.lower_threshold,
01043                  this->m_lower_thresh,
01044                  sizeof(int32_t) * phCOLOR_MAXELEMS);
01045         phMemcpy(this->m_args.upper_threshold,
01046                  this->m_upper_thresh,
01047                  sizeof(int32_t) * phCOLOR_MAXELEMS);
01048         phMemcpy(this->m_args.loop_threshold,
01049                  this->m_loop_thresh,
01050                  sizeof(int32_t) * phCOLOR_MAXELEMS);
01051         
01052         rc = phblob_find_line_segments_neighbor(&this->m_args,
01053                                                 this->m_data);
01054         phCHECK_RC(rc,NULL,"phblob_find_line_segments failed.");
01055     }
01056     
01057 #if TIMESTUFF()
01058     rc = ph_timedb_stop(timedb);
01059     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01060 #endif
01061  
01062     /* -------------------------------------------------------------------- */
01063     /* 2.) Link the overlapping segments to each other */
01064     /* connects ->left, ->right, ->first/last_down and 
01065      * ->first/last_up pointers to segments that overlap */
01066     /* -------------------------------------------------------------------- */
01067 #if TIMESTUFF()
01068     rc = ph_timedb_start(timedb,tags[1]);
01069     phPRINT_RC(rc,NULL,"ph_timedb_start");
01070 #endif
01071     rc = phblob_link_line_segments(&this->m_args, this->m_data );
01072     phPRINT_RC(rc,NULL,"phblob_link_line_segments");
01073 #if TIMESTUFF()
01074     rc = ph_timedb_stop(timedb);
01075     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01076 #endif
01077     
01078   
01079     /* -------------------------------------------------------------------- */
01080     /* 3a.) Identify the blobs                                              */
01081     /* -------------------------------------------------------------------- */
01082 #if TIMESTUFF()
01083     rc = ph_timedb_start(timedb,tags[2]);
01084     phPRINT_RC(rc,NULL,"ph_timedb_start");
01085 #endif
01086     rc = phblob_create_blobs(width, height, this->m_data );
01087     phPRINT_RC(rc,NULL,"phblob_create_blobs");
01088 #if TIMESTUFF()
01089     rc = ph_timedb_stop(timedb);
01090     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01091 #endif
01092 
01093     /* -------------------------------------------------------------------- */
01094     /* 3b.) Color in the matching segments before sorting them */
01095     /* -------------------------------------------------------------------- */
01096 #if TIMESTUFF()
01097     rc = ph_timedb_start(timedb,tags[5]);
01098     phPRINT_RC(rc,NULL,"ph_timedb_start");
01099 #endif
01100     if (this->m_color_blobs)
01101     {
01102         rc = 1;
01103         if (output_format != (uint32_t)phImageNOFORMAT)
01104         {
01105             rc = this->m_workspaceImage->convert(output_format);
01106             phPRINT_RC(rc,NULL,"Image->convert(outputFormat) failed.");
01107         }
01108 
01109         /* rc == 0 means conversion happened */
01110         /* rc == 1 means no conversion */
01111         if (rc == phSUCCESS)
01112         {
01113             rc = this->setFilterVars();
01114             phPRINT_RC(rc,NULL,"setFilterVars");
01115         }
01116             
01117         imgptr = (uint8_t *)Image;
01118         
01119         rc = phblob_color_lines(imgptr,width,height,format,
01120                                 this->m_outcolor,
01121                                 this->m_data,
01122                                 this->m_color_min_size,
01123                                 0,
01124                                 phBLOB_DRAW_ALL );
01125         phPRINT_RC(rc,NULL,"phblob_color_lines failed.");
01126     }
01127 
01128 #if TIMESTUFF()
01129     rc = ph_timedb_stop(timedb);
01130     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01131 #endif
01132    
01133 
01134     /* -------------------------------------------------------------------- */
01135     /* 3c.) Sort the blobs                                                  */
01136     /* -------------------------------------------------------------------- */
01137 #if TIMESTUFF()
01138     rc = ph_timedb_start(timedb,tags[3]);
01139     phPRINT_RC(rc,NULL,"ph_timedb_start");
01140 #endif
01141     rc = phblob_sort_blobs( this->m_data, 1 /*iterative*/ );
01142     phPRINT_RC(rc,NULL,"phblob_sort_blobs");
01143 #if TIMESTUFF()
01144     rc = ph_timedb_stop(timedb);
01145     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01146 #endif
01147         
01148     /* -------------------------------------------------------------------- */
01149     /* 4.) Copy the data <strike>before performing any image altering</strike>*/
01150     /* -------------------------------------------------------------------- */
01151 #if TIMESTUFF()
01152     rc = ph_timedb_start(timedb,tags[4]);
01153     phPRINT_RC(rc,NULL,"ph_timedb_start");
01154 #endif
01155     rc = this->m_blobData.setData( this->m_data );
01156     phPRINT_RC(rc,NULL,"m_blobData.setData failed.");
01157 #if TIMESTUFF()
01158     rc = ph_timedb_stop(timedb);
01159     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01160 #endif
01161         
01162     /* -------------------------------------------------------------------- */
01163     /* 5.) Put rectangles around all the blobs */
01164     /* -------------------------------------------------------------------- */
01165 #if TIMESTUFF()
01166     rc = ph_timedb_start(timedb,tags[6]);
01167     phPRINT_RC(rc,NULL,"ph_timedb_start");
01168 #endif
01169     if (this->m_draw_rects)
01170     {
01171         rc = 1;
01172         if (final_output_format != (uint32_t)phImageNOFORMAT)
01173         {
01174             rc = this->m_workspaceImage->convert(output_format);
01175             phPRINT_RC(rc,NULL,"Image->convert(outputFormat) failed.");
01176         }
01177         
01178         /* rc == 0 means conversion happened */
01179         /* rc == 1 means no conversion */
01180         if (rc == phSUCCESS)
01181         {
01182             rc = this->setFilterVars();
01183             phPRINT_RC(rc,NULL,"setFilterVars");
01184         }
01185             
01186         imgptr = (uint8_t *)Image;
01187         
01188         /* NULL arg == black */
01189         rc = phblob_draw_blob_rects(imgptr,width,height,format,
01190                                     this->m_outcolor,
01191                                     this->m_data,
01192                                     0,
01193                                     this->m_color_min_size,
01194                                     phBLOB_DRAW_ALL );
01195         phPRINT_RC(rc,NULL,"phblob_draw_blob_rects failed.");
01196     }
01197 #if TIMESTUFF()
01198     rc = ph_timedb_stop(timedb);
01199     phPRINT_RC(rc,NULL,"ph_timedb_stop");
01200 #endif
01201     
01202 #if TIMESTUFF() /* phTIME_REPORT_ALL & */
01203     rc = ph_timedb_report( timedb, phTIME_REPORT_SUM | phTIME_REPORT_ALL );
01204     phPRINT_RC(rc,NULL,"ph_timedb_report");
01205     
01206     if (timedb)
01207     {
01208         rc = ph_timedb_free(&timedb);
01209         phPRINT_RC(rc,NULL,"ph_timedb_free");
01210     }
01211 #endif
01212     
01213     return phSUCCESS; 
01214 error:
01215 #if TIMESTUFF() /* phTIME_REPORT_ALL & */
01216     if (timedb)
01217     {
01218         rc = ph_timedb_free(&timedb);
01219         phPRINT_RC(rc,NULL,"ph_timedb_free");
01220     }
01221 #endif
01222     return phFAIL;
01223 }  
01224 
01225 




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:09 2007 for phission by  doxygen 1.4.4