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

medianBlur_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  ---------------------------------------------------------------------------
00010     <Add other copyrights here> 
00011  ---------------------------------------------------------------------------
00012 
00013     This file is part of Phission.
00014 
00015     Phission is free software; you can redistribute it and/or modify
00016     it under the terms of the GNU Lesser General Public License as published by
00017     the Free Software Foundation; either version 2 of the License, or
00018     (at your option) any later version.
00019 
00020     Phission is distributed in the hope that it will be useful,
00021     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023     GNU Lesser General Public License for more details.
00024 
00025     You should have received a copy of the GNU Lesser General Public License
00026     along with Phission; if not, write to the Free Software
00027     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 
00029  ---------------------------------------------------------------------------*/
00030 #ifdef HAVE_CONFIG_H
00031     #include <phissionconfig.h>
00032 #endif
00033 
00034 #include <phStandard.h>
00035 
00036 #include <medianBlur_Filter.h>
00037 #include <math.h>
00038 
00039 #include <phError.h>
00040 #include <phMemory.h>
00041 #include <phPrint.h>
00042 
00043 #define TIMESTUFF() 0
00044 
00045 /* ---------------------------------------------------------------------- */
00046 medianBlur_Filter::medianBlur_Filter(uint32_t kernel_size ) :
00047     phFilter("medianBlur_Filter")
00048 
00049 {
00050     this->m_format = (phImageRGB24    | 
00051                       phImageBGR24    |
00052                       phImageRGBA32   | 
00053                       phImageABGR32   |
00054                       phImageHSV24    |
00055                       phImageGREY8);
00056     
00057     this->m_out = NULL;
00058     this->m_out_size = 0;
00059        
00060     this->m_medianarr = NULL;
00061     this->m_medianarr_size = 0;
00062 
00063     this->m_rankTable = NULL;
00064     this->m_rankTable_size = 0;
00065 
00066     this->m_rankTable_init = NULL;
00067     this->m_rankTable_init_size = 0;
00068 
00069     this->m_kernelOffset = NULL;
00070     this->m_kernelOffset_size = 0;
00071 
00072     this->m_kernel_size = 3;
00073     this->set(kernel_size);
00074 }
00075 
00076 /* ---------------------------------------------------------------------- */
00077 medianBlur_Filter::~medianBlur_Filter()
00078 {
00079     phFree(this->m_out);
00080     phFree(this->m_medianarr);
00081     phFree(this->m_rankTable);
00082     phFree(this->m_rankTable_init);
00083     phFree(this->m_kernelOffset);
00084 }
00085 
00086 /* ------------------------------------------------------------------------ */
00087 phFilter *medianBlur_Filter::cloneFilter()
00088 {
00089     return (phFilter *)new medianBlur_Filter(this->m_kernel_size);
00090 }
00091 
00092 /* ---------------------------------------------------------------------- */
00093 int medianBlur_Filter::set(uint32_t kernel_size)
00094 {
00095     /* make sure the kernel at least of size 3,
00096      * it makes no sense to have a kernel any smaller */
00097     if(kernel_size < 3)
00098     {
00099         /* 3: default kernel size */
00100         this->m_kernel_size = 3;
00101     }
00102     /* make kernel size an odd value */
00103     else if ((kernel_size % 2) == 0) 
00104     {
00105         this->m_kernel_size = kernel_size - 1;
00106     }
00107     else
00108     {
00109         this->m_kernel_size = kernel_size;
00110     }
00111     
00112     return phSUCCESS;
00113 }
00114 
00115 /* ---------------------------------------------------------------------- */
00116 int medianBlur_Filter::filter()
00117 {
00118     phFUNCTION("medianBlur_Filter::filter")
00119 
00120     /* Pointer to the start of the kernel window */
00121     uint8_t *kwindowPtr   = NULL;
00122     /* Used to index through the kernel window elements */
00123     uint8_t *imagePtr   = NULL;
00124     /* Used to index through the output image */
00125     uint8_t *outptr     = NULL;
00126     /* Used to index through the medianarray */
00127     uint32_t *medptr    = NULL;
00128     
00129     const uint32_t order = (format & (phImageRGBA32 | phImageRGB24)) ? 0 : 1;
00130     const uint32_t d = depth;
00131     /* const uint32_t ai = (d == 4) ? (order ? 0 : 3) : (order ? 0 : 0); */
00132     const uint32_t bi = (d == 4) ? (order ? 1 : 2) : (order ? 0 : 2);
00133     const uint32_t gi = (d == 4) ? (order ? 2 : 1) : (order ? 1 : 1);
00134     const uint32_t ri = (d == 4) ? (order ? 3 : 0) : (order ? 2 : 0);
00135 
00136     uint32_t calc_intensity = 0;
00137     uint32_t intensity_i = 0;
00138 
00139     uint32_t w = 0;
00140     uint32_t h = 0;
00141     uint32_t i = 0;
00142     uint32_t j = 0;
00143     /* uint32_t k = 0; */
00144     
00145     const uint32_t x             = (uint32_t)((this->m_kernel_size)/2.0);
00146     const uint32_t kernelSquared = this->m_kernel_size*this->m_kernel_size;
00147     
00148     /* Add this to the image. We want to add at least width, to get one
00149      * row ahead, then we subtract the kernel width; */
00150     const uint32_t kernel_next_row = (width - this->m_kernel_size) * depth;
00151 
00152     const uint32_t height_limit     = height - this->m_kernel_size;
00153     const uint32_t width_limit      = width  - this->m_kernel_size;
00154     const uint32_t outptr_stepping  = (this->m_kernel_size * depth);
00155     
00156     const uint32_t rank_middle_index = (uint32_t)((float)kernelSquared/2.0);
00157     
00158 #if TIMESTUFF()
00159     const uint32_t nStamps = 4;
00160     char *tags[nStamps] = {
00161         "allocations",
00162         "kernel window img index calc",
00163         "medianBlur",
00164         "copy output to workspace"
00165     };
00166     ph_time_db      timedb = NULL;
00167     rc = ph_timedb_alloc(&timedb,"medianBlur_Filter");
00168     phPRINT_RC(rc,NULL,"ph_timedb_alloc");
00169 #endif /* TIMESTUFF() */
00170     
00171 #if TIMESTUFF()
00172     rc = ph_timedb_start(timedb,tags[0]);
00173     phPRINT_RC(rc,NULL,"ph_timedb_start");
00174 #endif
00175     phDALLOC_RESIZE(this->m_out,
00176                     this->m_out_size,
00177                     width*height*depth,
00178                     uint8_t);
00179 
00180     phDALLOC_RESIZE(this->m_medianarr,
00181                     this->m_medianarr_size,
00182                     kernelSquared,
00183                     uint32_t );
00184 
00185     phDALLOC_RESIZE(this->m_rankTable,
00186                     this->m_rankTable_size,
00187                     kernelSquared,
00188                     int32_t );
00189     
00190     phDALLOC_RESIZE(this->m_rankTable_init,
00191                     this->m_rankTable_init_size,
00192                     kernelSquared,
00193                     int32_t );
00194     
00195     phDALLOC_RESIZE(this->m_kernelOffset,
00196                     this->m_kernelOffset_size,
00197                     kernelSquared,
00198                     uint32_t );
00199 #if TIMESTUFF()
00200     rc = ph_timedb_stop(timedb);
00201     phPRINT_RC(rc,NULL,"ph_timedb_stop");
00202 #endif
00203 
00204     /* These will be phMemcpy'd to the rankTable to save time involved
00205      * with looping to reset the values */
00206     for(i = 0; i < kernelSquared; i++)  
00207     {
00208         this->m_rankTable_init[i] = i;
00209     }
00210 
00211     if (format & (phImageGREY8 | phImageYUV9))
00212     {
00213         intensity_i = 0;
00214     }
00215     else if (format & (phImageHSV24))
00216     {
00217         intensity_i = 2;
00218     }
00219     else if (format & (phImageRGB24 | phImageBGR24 |
00220                        phImageABGR32| phImageRGBA32))
00221     {
00222         calc_intensity = 1;
00223     } 
00224     
00225     /* Begin filter */
00226     
00227 #if TIMESTUFF()
00228     rc = ph_timedb_start(timedb,tags[1]);
00229     phPRINT_RC(rc,NULL,"ph_timedb_start");
00230 #endif
00231     for (i = 0; i < kernelSquared; i++ )
00232     {
00233         this->m_kernelOffset[i] = 
00234             (((uint32_t)floor((float)i / this->m_kernel_size) * width) + 
00235             i % this->m_kernel_size) * depth;
00236     }
00237 #if TIMESTUFF()
00238     rc = ph_timedb_stop(timedb);
00239     phPRINT_RC(rc,NULL,"ph_timedb_stop");
00240 #endif
00241     
00242 #if TIMESTUFF()
00243     rc = ph_timedb_start(timedb,tags[2]);
00244     phPRINT_RC(rc,NULL,"ph_timedb_start");
00245 #endif
00246     outptr  = this->m_out + ((x * width + x) * depth);
00247     
00248     for( h = 0; h < height_limit; h++)
00249     {
00250         /* We set the outptr to (x,x) where (x,x) is the pixel being set
00251          * to the median value at the center of the kernel */
00252 
00253         for( w = 0; w < width_limit; w++ )
00254         {
00255             /* Set image and median ptrs */
00256             /* we start the kernel window at (w,h) */
00257             kwindowPtr = imagePtr = Image + ((h * width)+w) * depth;
00258             medptr  = this->m_medianarr;
00259             
00260             /* find middle color of surrouding pixels */
00261             for( i = 0; i < this->m_kernel_size; i++, imagePtr += kernel_next_row )
00262             {
00263                 for( j = 0; j < this->m_kernel_size; j++, medptr++, imagePtr += depth )
00264                 {
00265                     if (calc_intensity)
00266                     {
00267                         *medptr = (uint32_t)((0.3 *  (*(imagePtr + ri))) + /* R */
00268                                              (0.59 * (*(imagePtr + gi))) + /* G */
00269                                              (0.11 * (*(imagePtr + bi))));  /* B */
00270                     }
00271                     else
00272                     {
00273                         *medptr = *(imagePtr + intensity_i);
00274                     }
00275                 }
00276             }
00277 
00278             phMemcpy(this->m_rankTable,
00279                      this->m_rankTable_init,
00280                      this->m_rankTable_size);
00281             
00282             /* Find the median value */
00283             for (i = 0; i < kernelSquared; i++ )
00284             {
00285                 for (j = i + 1; j < kernelSquared; j++ )
00286                 {
00287                     if(this->m_medianarr[this->m_rankTable[i]] > 
00288                             this->m_medianarr[this->m_rankTable[j]])
00289                     {
00290                         phXOR_SWAP(this->m_rankTable[i],this->m_rankTable[j]);
00291                     }
00292                 }
00293             }
00294             
00295             /* TODO: add YUV9 support */
00296             phMemcpy( outptr,
00297                     (kwindowPtr + 
00298                      this->m_kernelOffset[this->m_rankTable[rank_middle_index]]),
00299                     depth );
00300 
00301             outptr += depth;
00302         }
00303 
00304         outptr += outptr_stepping;
00305     }
00306 #if TIMESTUFF()
00307     rc = ph_timedb_stop(timedb);
00308     phPRINT_RC(rc,NULL,"ph_timedb_stop");
00309 #endif   
00310 
00311 #if TIMESTUFF()
00312     rc = ph_timedb_start(timedb,tags[3]);
00313     phPRINT_RC(rc,NULL,"ph_timedb_start");
00314 #endif
00315     /* Copy the median blur/filter output to the workspace */
00316     phMemcpy(Image,
00317            this->m_out,
00318            width * height * depth * sizeof(uint8_t));
00319 #if TIMESTUFF()
00320     rc = ph_timedb_stop(timedb);
00321     phPRINT_RC(rc,NULL,"ph_timedb_stop");
00322 #endif   
00323 
00324 #if TIMESTUFF()
00325     rc = ph_timedb_report( timedb, phTIME_REPORT_SUM | phTIME_REPORT_ALL );
00326     phPRINT_RC(rc,NULL,"ph_timedb_report");
00327     
00328     if (timedb)
00329     {
00330         rc = ph_timedb_free(&timedb);
00331         phPRINT_RC(rc,NULL,"ph_timedb_free");
00332     }
00333 #endif
00334     return phSUCCESS;
00335 error:
00336     
00337 #if TIMESTUFF()
00338     if (timedb)
00339     {
00340         rc = ph_timedb_free(&timedb);
00341         phPRINT_RC(rc,NULL,"ph_timedb_free");
00342     }
00343 #endif
00344     return phFAIL;
00345 }




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