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

histogram_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 <histogram_Filter.h>
00033 
00034 #include <phError.h>
00035 #include <phMemory.h>
00036 #include <phPrint.h>
00037 
00038 #define HSV_TIMESTUFF() 0
00039 
00040 /* ---------------------------------------------------------------------- */
00041 histogram_Filter::histogram_Filter(uint32_t x1, uint32_t y1, 
00042                                    uint32_t x2, uint32_t y2, 
00043                                    uint32_t bins, uint32_t draw_rect,
00044                                    phColor *outcolor  ) :
00045     phFilter("histogram_Filter")
00046 
00047 {
00048     phFUNCTION("histogram_Filter::histogram_Filter")
00049     int locked = 0;
00050 
00051     phTHIS_LOOSE_LOCK(locked);
00052    
00053     /* Can only process/histogram packed image formats; i.e. where all the
00054      * channels are grouped together for each pixel */
00055     this->m_format = phImagePackedFormatMask;
00056 
00057     this->m_binVal  =   NULL;
00058     this->m_binCnt  =   NULL;
00059     this->m_binAvg  =   NULL;
00060     this->m_maxAvg  =   NULL;
00061     this->m_maxCnt  =   NULL;
00062     this->m_maxBin  =   NULL;
00063     this->m_binCnt_size = 0;
00064     this->m_binAvg_size = 0;
00065     this->m_maxAvg_size = 0;
00066     this->m_maxCnt_size = 0;
00067     this->m_maxBin_size = 0;
00068    
00069     this->m__x1         = 0;
00070     this->m__y1         = 0;
00071     this->m__x2         = 0;
00072     this->m__y2         = 0;
00073     this->m_lastWidth   = 0;
00074     this->m_lastHeight  = 0;
00075     this->m_updateBox   = 0;
00076     
00077     this->m_x1          = 0;
00078     this->m_x2          = 0;
00079     this->m_y1          = 0;
00080     this->m_y2          = 0;
00081     this->m_useCoords   = 1;
00082 
00083     this->m_x                   = 0;
00084     this->m_y                   = 0;
00085     this->m_x_boxSize           = 0.0;
00086     this->m_y_boxSize           = 0.0;
00087     this->m_useBox              = 0;
00088     this->m_useBoxWithCoords    = 0;
00089     
00090     this->m_draw_rect       = 0;
00091     this->m_outcolor        = NULL;
00092     this->m_outputFormat    = phImageNOFORMAT;
00093     this->m_outcolor_size   = 0;
00094 
00095     phDALLOC_RESIZE(this->m_outcolor,
00096                     this->m_outcolor_size,
00097                     1,
00098                     phColor );
00099 
00100 error:
00101     this->set(x1,y1,x2,y2,bins,draw_rect,outcolor);
00102 
00103     phTHIS_LOOSE_UNLOCK(locked);
00104 }
00105 
00106 /* ---------------------------------------------------------------------- */
00107 histogram_Filter::~histogram_Filter()
00108 {
00109     phFree(this->m_binVal);
00110     phFree(this->m_binCnt);
00111     phFree(this->m_binAvg);
00112     phFree(this->m_maxAvg);
00113     phFree(this->m_maxCnt);
00114     phFree(this->m_maxBin);
00115     phFree(this->m_outcolor);
00116 }
00117 
00118 /* ------------------------------------------------------------------------ */
00119 phFilter *histogram_Filter::cloneFilter()
00120 {
00121     phFUNCTION("histogram_Filter::cloneFilter")
00122     int         locked = 0;
00123     phFilter   *ret = NULL;
00124 
00125     phTHIS_LOCK(locked);
00126     
00127     ret = (phFilter *)new histogram_Filter(this->m_x1,
00128                                            this->m_y1, 
00129                                            this->m_x2, 
00130                                            this->m_y2, 
00131                                            this->m_binCount,
00132                                            this->m_draw_rect,
00133                                            this->m_outcolor );
00134     phCHECK_PTR(ret,NULL,"new histogram_Filter");
00135 
00136     phTHIS_UNLOCK(locked);
00137 
00138     return ret;
00139 error:
00140     phTHIS_ERROR_UNLOCK(locked);
00141     
00142     return NULL;
00143 }
00144 /* ---------------------------------------------------------------------- */
00145 /* This is thread safe because copy is a thread safe method and
00146    m_histogramData is always around; ie != NULL eva' */
00147 /* ---------------------------------------------------------------------- */
00148 int histogram_Filter::getHistogramData( phHistogramData &histData )
00149 {
00150     return histData.copy(this->m_histogramData );
00151 }
00152 
00153 /* ---------------------------------------------------------------------- */
00154 phLiveObject *histogram_Filter::getLiveHistogramOutput() 
00155 {
00156     return (phLiveObject *)&(this->m_histogramData);
00157 }
00158 
00159 /* ---------------------------------------------------------------------- */
00160 int histogram_Filter::set(uint32_t x1, uint32_t y1, 
00161                           uint32_t x2, uint32_t y2, 
00162                           uint32_t bins, uint32_t draw_rect,
00163                           phColor *outcolor )
00164 {
00165     phFUNCTION("histogram_Filter::set")
00166     int locked = 0;
00167     
00168     phTHIS_LOCK(locked);
00169 
00170     rc = this->setBoxCoords(x1,y1,x2,y2);
00171     rc = this->setDrawRect( draw_rect );
00172     rc = this->setBinCount( bins );
00173     
00174     if (outcolor != NULL)
00175     {
00176         rc = this->setOutcolor( *outcolor );
00177     }
00178 
00179     phTHIS_UNLOCK(locked);
00180 
00181     return phSUCCESS;
00182 error:
00183     phTHIS_ERROR_UNLOCK(locked);
00184     
00185     return phFAIL;
00186 }
00187 
00188 /* ---------------------------------------------------------------------- */
00189 int histogram_Filter::setBoxSize(double width_size, double height_size)
00190 {
00191     phFUNCTION("histogram_Filter::setBoxSize")
00192     int locked = 0;
00193 
00194     phTHIS_LOCK(locked);
00195    
00196     this->m_x_boxSize = width_size;
00197     this->m_y_boxSize = height_size;
00198     
00199     this->m_useCoords           = 0;
00200     this->m_useBox              = 1;
00201     this->m_useBoxWithCoords    = 0;
00202     this->m_updateBox           = 1;
00203 
00204     phTHIS_UNLOCK(locked);
00205     
00206     return phSUCCESS;
00207 error:
00208     phTHIS_ERROR_UNLOCK(locked);
00209 
00210     return phFAIL;
00211 }
00212 
00213 /* ---------------------------------------------------------------------- */
00214 int histogram_Filter::setBoxSize(double size)
00215 {
00216     return this->setBoxSize(size,size);
00217 }
00218 
00219 /* ---------------------------------------------------------------------- */
00220 int histogram_Filter::setBox(double width_size, double height_size,
00221                              uint32_t x, uint32_t y )
00222 {
00223     phFUNCTION("histogram_Filter::setBox")
00224     int locked = 0;
00225 
00226     phTHIS_LOCK(locked);
00227    
00228     this->m_x_boxSize = width_size;
00229     this->m_y_boxSize = height_size;
00230     this->m_x = x;
00231     this->m_y = y;
00232     
00233     this->m_useCoords           = 0;
00234     this->m_useBox              = 0;
00235     this->m_useBoxWithCoords    = 1;
00236     this->m_updateBox           = 1;
00237 
00238     phTHIS_UNLOCK(locked);
00239     
00240     return phSUCCESS;
00241 error:
00242     phTHIS_ERROR_UNLOCK(locked);
00243 
00244     return phFAIL;
00245 }
00246 
00247 /* ---------------------------------------------------------------------- */
00248 int histogram_Filter::setBox(double size, uint32_t x, uint32_t y )
00249 {
00250     return this->setBox(size,size,x,y);
00251 }
00252 
00253 
00254 /* ---------------------------------------------------------------------- */
00255 int histogram_Filter::setBoxCoords(uint32_t x1, uint32_t y1, 
00256                                    uint32_t x2, uint32_t y2 )
00257 {
00258     phFUNCTION("histogram_Filter::setBoxCoords")
00259     int locked = 0;
00260 
00261     phTHIS_LOCK(locked);
00262         
00263     if (x1 == x2) 
00264     {
00265         if (x1 == 0) 
00266         {
00267             x1 = 50;
00268             x2 = 100;
00269         }
00270         else 
00271             x1 = x2 - 1;
00272     }
00273     if (y1 == y2) 
00274     {
00275         if (y1 == 0) 
00276         {
00277             y1 = 50;
00278             y2 = 100;
00279         }
00280         else 
00281             y1 = y2 - 1;
00282     }
00283 
00284     this->m_x1 = x1;
00285     this->m_y1 = y1;
00286     this->m_x2 = x2;
00287     this->m_y2 = y2;
00288 
00289     this->m_useCoords           = 1;
00290     this->m_useBox              = 0;
00291     this->m_useBoxWithCoords    = 0;
00292     this->m_updateBox           = 1;
00293 
00294     phTHIS_UNLOCK(locked);
00295     
00296     return phSUCCESS;
00297 error:
00298     phTHIS_ERROR_UNLOCK(locked);
00299 
00300     return phFAIL;
00301 }
00302 
00303 /* ---------------------------------------------------------------------- */
00304 int histogram_Filter::setBinCount( uint32_t bins )
00305 {
00306     phFUNCTION("histogram_Filter::setBinCount")
00307     int locked = 0;
00308 
00309     phTHIS_LOCK(locked);
00310     
00311     if (bins == 0) bins = 64;
00312     this->m_binCount = bins;
00313 
00314     phTHIS_UNLOCK(locked);
00315     
00316     return phSUCCESS;
00317 error:
00318     phTHIS_ERROR_UNLOCK(locked);
00319 
00320     return phFAIL;
00321 }  
00322 
00323 /* ---------------------------------------------------------------------- */
00324 int histogram_Filter::setDrawRect( uint32_t draw_rect )
00325 {
00326     phFUNCTION("histogram_Filter::setDrawRect")
00327     int locked = 0;
00328 
00329     phTHIS_LOCK(locked);
00330     
00331     this->m_draw_rect = draw_rect;
00332     
00333     phTHIS_UNLOCK(locked);
00334     
00335     return phSUCCESS;
00336 error:
00337     phTHIS_ERROR_UNLOCK(locked);
00338 
00339     return phFAIL;
00340 }
00341 
00342 /* ---------------------------------------------------------------------- */
00343 int histogram_Filter::setOutcolor( phColor outcolor  )
00344 {
00345     phFUNCTION("histogram_Filter::setOutcolor")
00346     int locked = 0;
00347 
00348     phTHIS_LOCK(locked);
00349     
00350     phMemcpy( this->m_outcolor, 
00351               &outcolor,
00352               sizeof(phColor));
00353  
00354     if ((this->m_outcolor[0].type == phColorTypeArray) ||
00355         (this->m_outcolor[0].type == phColorTypeYUV9))
00356     {
00357         this->m_outputFormat = phImageNOFORMAT;
00358     }
00359     else
00360     {
00361         this->m_outputFormat = phColorToFormat(this->m_outcolor[0]);
00362     }
00363     
00364     phTHIS_UNLOCK(locked);
00365     
00366     return phSUCCESS;
00367 error:
00368     phTHIS_ERROR_UNLOCK(locked);
00369 
00370     return phFAIL;
00371 }
00372 
00373 /* ---------------------------------------------------------------------- */
00374 int histogram_Filter::do_draw_rect_maybe(uint32_t x1,
00375                                          uint32_t y1,
00376                                          uint32_t x2,
00377                                          uint32_t y2 )
00378 {
00379     phFUNCTION("histogram_Filter::do_draw_rect_maybe")
00380     
00381     /* draw a rectangle around the area being histogrammed */
00382     if (this->m_draw_rect)
00383     {
00384         phImageSurface  surface;
00385         phColor         outcolor;
00386         uint8_t        *imgptr = NULL;
00387 
00388         /* Convert the image format if it's required */
00389         rc = 1;
00390         if (this->m_outputFormat != (uint32_t)phImageNOFORMAT)
00391         {
00392             rc = this->m_workspaceImage->convert(this->m_outputFormat);
00393             phPRINT_RC(rc,NULL,"Image->convert(outputFormat) failed.");
00394         }
00395         
00396         /* rc == 0 means conversion happened */
00397         /* rc == 1 means no conversion */
00398         if (rc == phSUCCESS)
00399         {
00400             rc = this->setFilterVars();
00401             phPRINT_RC(rc,NULL,"setFilterVars");
00402         }
00403             
00404         imgptr = (uint8_t *)Image;
00405        
00406         /* Set up a black color struct if no color has been given */
00407         if (this->m_outcolor == NULL)
00408         {
00409             outcolor = phColor_new(phImageFormatToColorType(this->format));
00410         }
00411         else
00412         {
00413             outcolor = *this->m_outcolor;
00414         }
00415 
00416         surface.p = imgptr;
00417         surface.w = width;
00418         surface.h = height;
00419         surface.f = this->format;
00420         surface.d = phImageFormatToDepth(this->format);
00421 
00422         /*
00423         phPROGRESS("%s:(%d,%d):(%d,%d)\n",
00424           phImageFormatToString(surface.format),x1,y1,x2,y2 );
00425          */
00426         ph_draw_hollow_rect(&surface,
00427                          outcolor,
00428                          0,
00429                          x1,
00430                          y1,
00431                          x2,
00432                          y2 );
00433     }
00434     
00435     return phSUCCESS;
00436 /*
00437 error:
00438     return phFAIL;
00439 */
00440 }
00441  
00442 /* ---------------------------------------------------------------------- */
00443 int histogram_Filter::filter()
00444 {
00445     phFUNCTION("histogram_Filter::filter")
00446 
00447     uint8_t     *img            = 0;
00448    
00449     /* Temporary variables */
00450     uint32_t        x1  = 0;
00451     uint32_t        y1  = 0;
00452     uint32_t        x2  = 0;
00453     uint32_t        y2  = 0;
00454 
00455     /* I'm going to keep thse around in case they become useful:
00456      * They should be updated below and initialized here */
00457     /*
00458     uint32_t    box_w               = this->m_x2 - this->m_x1;
00459     uint32_t    box_h               = this->m_y2 - this->m_y1;
00460     uint32_t    box_pixels          = box_w * box_h;
00461     */
00462     
00463 #if HSV_TIMESTUFF()
00464     phTime  timedb("histogram_Filter");
00465 #endif /* HSV_TIMESTUFF() */
00466 
00467     /* Begin filter */
00468     
00469     
00470 #if HSV_TIMESTUFF()
00471     timedb.start("box calculations");
00472 #endif
00473     
00474     /* TODO: add more checks to this */
00475     if ((this->m_lastWidth != width) ||
00476         (this->m_lastHeight != height) ||
00477         (this->m_updateBox))
00478     {        
00479         if (this->m_useCoords)
00480         {
00481             /* Set the temporary variables */
00482             x1 = this->m_x1;
00483             y1 = this->m_y1;
00484             x2 = this->m_x2;
00485             y2 = this->m_y2;
00486         
00487             /* make sure Y coords are within bounds */
00488             if (y2 >= height)
00489                 y2 = height-1;
00490             if (y1 >= y2)
00491                 y1 = y2 - 1;
00492     
00493             /* make sure the X coords are within bounds */
00494             if (x2 >= width)
00495                 x2 = width-1;
00496             if (x1 >= x2)
00497                 x1 = x2 - 1;
00498         }
00499         else if (this->m_useBoxWithCoords)
00500         {
00501             int32_t bw = (int32_t)((double)width  / this->m_x_boxSize);
00502             int32_t bh = (int32_t)((double)height / this->m_y_boxSize);
00503             int32_t hbw = (int32_t)((double)bw / (double)2);
00504             int32_t hbh = (int32_t)((double)bh / (double)2);
00505             int32_t x = this->m_x;
00506             int32_t y = this->m_y;
00507             
00508             /* Make sure the calculations will fall within bounds */
00509             /* make sure the left side will be >= 0 */
00510             if ((x - hbw) < 0) x = hbw;
00511             /* make sure the right side will be < width */
00512             else if ((x + hbw) >= (int32_t)width) x = width - hbw;
00513             
00514             /* make sure the top will be >= 0 */
00515             if ((y - hbh) < 0) y = hbh;
00516             /* make sure the bottom will be < height */
00517             else if ((y + hbh) >= (int32_t)height) y = height - hbh;
00518             
00519             x1 = x - hbw;
00520             x2 = x + hbw;
00521             y1 = y - hbh;
00522             y2 = y + hbh;
00523         }
00524         else if (this->m_useBox)
00525         {
00526             int32_t bw = (uint32_t)((double)width  / this->m_x_boxSize);
00527             int32_t bh = (uint32_t)((double)height / this->m_y_boxSize);
00528             int32_t hbw = (uint32_t)((double)bw / (double)2);
00529             int32_t hbh = (uint32_t)((double)bh / (double)2);
00530             int32_t x = width / 2;
00531             int32_t y = height / 2;
00532             
00533             /* Make sure the calculations will fall within bounds */
00534             /* make sure the left side will be >= 0 */
00535             if ((x - hbw) < 0) x = hbw;
00536             /* make sure the right side will be < width */
00537             else if ((x + hbw) >= (int32_t)width) x = width - hbw;
00538             
00539             /* make sure the top will be >= 0 */
00540             if ((y - hbh) < 0) y = hbh;
00541             /* make sure the bottom will be < height */
00542             else if ((y + hbh) >= (int32_t)height) y = height - hbh;
00543             
00544             x1 = x - hbw;
00545             x2 = x + hbw;
00546             y1 = y - hbh;
00547             y2 = y + hbh;
00548             
00549             /*phPRINT("%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u\n",
00550                     x1,y1,x2,y2,bw,bh,hbw,hbh,x,y,width,height);
00551             */
00552         }
00553     
00554         /* Save the values so we don't have to calculate them next time if the
00555          * image dimensions/parameters don't change */
00556         this->m__x1 = x1;
00557         this->m__y1 = y1;
00558         this->m__x2 = x2;
00559         this->m__y2 = y2;
00560         this->m_lastWidth   = width;
00561         this->m_lastHeight  = height;
00562         this->m_updateBox   = 0;
00563     }
00564     else
00565     {
00566         x1 = this->m__x1;
00567         y1 = this->m__y1;
00568         x2 = this->m__x2;
00569         y2 = this->m__y2;
00570     }
00571     
00572 #if HSV_TIMESTUFF()
00573     timedb.stop();
00574 #endif
00575     
00576     
00577 #if HSV_TIMESTUFF()
00578     timedb.start("histogram loop");
00579 #endif
00580     rc = ph_histogram_data_gen_from_image(width,height,depth,Image,
00581                                           x1,y1,x2,y2,
00582                                           this->m_binCount,
00583                                           255.0,
00584                                           &this->m_binVal,
00585                                           &this->m_binVal_size,
00586                                           &this->m_binCnt,
00587                                           &this->m_binCnt_size,
00588                                           &this->m_binAvg,
00589                                           &this->m_binAvg_size );
00590     phPRINT_RC(rc,NULL,"ph_histogram_data_gen_from_image");
00591 #if HSV_TIMESTUFF()
00592     timedb.stop();
00593 #endif
00594 
00595 #if HSV_TIMESTUFF()
00596     timedb.start("averaging loop");
00597 #endif
00598     /* compute average; generate max bin info; create max color info */
00599     ph_histogram_data_gen_max(this->m_binCount, depth,     format,     255.0,
00600                               this->m_binVal,this->m_binCnt,
00601                               /* the following are returned/altered/allocated */
00602                               this->m_binAvg,
00603                               &this->m_maxbin_color,&this->m_maxbin_threshold,
00604                               &this->m_maxBin,      &this->m_maxBin_size,
00605                               &this->m_maxCnt,      &this->m_maxCnt_size,
00606                               &this->m_maxAvg,      &this->m_maxAvg_size );
00607     phPRINT_RC(rc,NULL,"ph_histogram_data_gen_max");
00608 
00609     rc = ph_histogram_data_bin_regions(this->m_binCount, depth, format, 255.0,
00610                               2, /* percent of the max bin count */
00611                               1, /* maximum # of breaks when searching */
00612                               this->m_binVal, this->m_binCnt, this->m_binAvg,
00613                               this->m_maxBin, this->m_maxCnt, this->m_maxAvg,
00614                               /* the following are returned/altered */
00615                               &this->m_color, &this->m_threshold
00616                               );
00617     phPRINT_RC(rc,NULL,"ph_histogram_regions");
00618 #if HSV_TIMESTUFF()
00619     timedb.stop();
00620 #endif
00621 
00622 #if HSV_TIMESTUFF()
00623     timedb.start("copy to histogramData");
00624 #endif
00625     rc = this->m_histogramData.setData( this->m_binCount,
00626                                         depth,
00627                                         this->m_maxbin_color,
00628                                         this->m_maxbin_threshold,
00629                                         this->m_color,
00630                                         this->m_threshold,
00631                                         this->m_binVal,
00632                                         this->m_binCnt,
00633                                         this->m_binAvg,
00634                                         this->m_maxBin,
00635                                         this->m_maxAvg,
00636                                         this->m_maxCnt );
00637     phPRINT_RC(rc,NULL,"histogramData.setData failed");
00638 #if HSV_TIMESTUFF()
00639     timedb.stop();
00640 #endif
00641 
00642 #if HSV_TIMESTUFF()
00643     timedb.start("do_draw_rect_maybe");
00644 #endif
00645     rc = this->do_draw_rect_maybe(x1,y1,x2,y2);
00646     phPRINT_RC(rc,NULL,"do_draw_rect_maybe");
00647 #if HSV_TIMESTUFF()
00648     timedb.stop();
00649 #endif   
00650     
00651 #if HSV_TIMESTUFF()
00652     timedb.report();
00653 #endif
00654     
00655     return phSUCCESS;
00656 #if 0
00657 error:
00658     return phFAIL;
00659 #endif
00660 }
00661 




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