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

gaussian3x3_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     gaussian 3x3:
00011     
00012     * This code is part of IPL, and is released under version 2 of the GPL.
00013     * Copyright (c) 2003-2006 John R. Watson.  See README and COPYING for more
00014     * information.
00015  ---------------------------------------------------------------------------
00016 
00017     This file is part of Phission.
00018 
00019     Phission is free software; you can redistribute it and/or modify
00020     it under the terms of the GNU Lesser General Public License as published by
00021     the Free Software Foundation; either version 2 of the License, or
00022     (at your option) any later version.
00023 
00024     Phission is distributed in the hope that it will be useful,
00025     but WITHOUT ANY WARRANTY; without even the implied warranty of
00026     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00027     GNU Lesser General Public License for more details.
00028 
00029     You should have received a copy of the GNU Lesser General Public License
00030     along with Phission; if not, write to the Free Software
00031     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00032 
00033  ---------------------------------------------------------------------------*/
00034 #ifdef HAVE_CONFIG_H
00035     #include <phissionconfig.h>
00036 #endif
00037 
00038 #include <phStandard.h>
00039 
00040 #include <gaussian3x3_Filter.h>
00041 
00042 #include <phError.h>
00043 #include <phMemory.h>
00044 #include <phPrint.h>
00045 
00046 /* ---------------------------------------------------------------------- *
00047  * From John R. Watson's IPL, included with Phission:                     *
00048  *          phission/filter/packages/ipl-1.0.0.tar.gz                     *
00049  * ---------------------------------------------------------------------- */
00050 #ifdef __cplusplus
00051 extern "C" 
00052 {
00053 #endif /* __cplusplus */
00054 /* ----------------------------------------------------------------------------
00055  * gauss.c -- Gaussian blur
00056  * ----------------------------------------------------------------------------
00057  * John R. Watson (jwatson@cs.uml.edu)
00058  * 91.549 Robotics II, Vision Project 1
00059  * DUE 11/13/03
00060  * ----------------------------------------------------------------------------
00061  * This code is part of IPL, and is released under version 2 of the GPL.
00062  * Copyright (c) 2003 John R. Watson.  See README and COPYING for more
00063  * information.
00064  */
00065 
00066 static void ipl__blur_gaussian_3x3(uint8_t *src,
00067                    uint8_t *dst,
00068                    const int w,
00069                    const int h);
00070 
00071 /* ----------------------------------------------------------------------------
00072  * ipl_blur_gaussian -- Gaussian blur
00073  * ----------------------------------------------------------------------------
00074  * This filter is hard-coded as a 3x3 because to support nxn kernels we would
00075  * have to either generate each kernel dynamically, or have a very large lut
00076  * filled with kernels for each size.  Since the original Pyro code was
00077  * hard-coded at 3x3, that seemed good enough.
00078  * ------------------------------------------------------------------------- */
00079 int ipl_blur_gaussian(uint8_t *src,
00080               uint8_t *dst,
00081               const int w,
00082               const int h,
00083               const int k)
00084 {
00085     phFUNCTION("ipl_blur_gaussian")
00086     
00087     /* we only support 3x3 */
00088     if (k != 3)
00089     {
00090         phERR_PRINT("only 3x3 kernels are supported");
00091         return -1;
00092     }
00093 
00094     ipl__blur_gaussian_3x3(src, dst, w, h);
00095 
00096     return 0;
00097 }
00098 
00099 /* ----------------------------------------------------------------------------
00100  * ipl__blur_gaussian_3x3 -- 3x3 Gaussian blur
00101  * ----------------------------------------------------------------------------
00102  * This filter is hard-coded as a 3x3 because to support nxn kernels we would
00103  * have to either generate each kernel dynamically, or have a very large lut
00104  * filled with kernels for each size.  Since the original Pyro code was
00105  * hard-coded at 3x3, that seemed good enough.
00106  * ------------------------------------------------------------------------- */
00107 static void ipl__blur_gaussian_3x3(uint8_t *src,
00108                                    uint8_t *dst,
00109                                    const int w,
00110                                    const int h)
00111 {
00112     /* To perform a Gaussian blur we convolve this kernel over a 3x3
00113      * window in the src image, i.e. we add each weight to the proper
00114      * pixel and then divide the result by 16 (sum of the weights)
00115      *
00116      * const uint8_t k[3][3] = { { 1, 2, 1 },
00117      *               { 2, 4, 2 },
00118      *               { 1, 2, 1 } };
00119      *
00120      * Because this is a static 3x3 filter, it's cheaper to unroll the
00121      * convolution loop below.
00122      */
00123     
00124     uint8_t *srcp;
00125     /* this is the row stride for the src window */
00126     const int stride = w * 3;
00127     int x;
00128     int y;
00129     int r;
00130     int g;
00131     int b;
00132     const int y_lim=h-2;
00133     const int x_lim=w-2;
00134 
00135     /* 3x3 kernels have a 1 pixel border because we don't compute edge
00136      * pixels, so adjust the dst pointer down and in 1 pixel
00137      */
00138     dst += (w + 1) * 3;
00139     
00140     for (y=0; y<y_lim; y++)
00141     {
00142         for (x=0; x<x_lim; x++)
00143         {
00144             srcp = src;
00145             src += 3; /* move the real src in one pixel for the next loop */
00146 
00147             /* compute the RGB values for the first row of pixels
00148              * in the 3x3 window
00149              */
00150             r  = *srcp     + (2 * *(srcp+3)) + *(srcp+6);
00151             g  = *(srcp+1) + (2 * *(srcp+4)) + *(srcp+7);
00152             b  = *(srcp+2) + (2 * *(srcp+5)) + *(srcp+8);
00153 
00154             /* move down to the next row */
00155             srcp += stride;
00156 
00157             r += (2 * (*srcp)) + (4 * *(srcp+3)) +
00158                  (2 * *(srcp + 6));
00159             
00160             g += (2 * *(srcp+1)) + (4 * *(srcp+4)) +
00161                  (2 * *(srcp+7));
00162                 
00163             b += (2 * (*srcp+2)) + (4 * *(srcp+5)) +
00164                  (2 * *(srcp+8));
00165 
00166             srcp += stride;
00167 
00168             /* compute the final row, then average the pixel
00169              * values and set it in the dst image
00170              */
00171             r += *srcp     + (2 * *(srcp+3)) + *(srcp+6);
00172             g += *(srcp+1) + (2 * *(srcp+4)) + *(srcp+7);
00173             b += *(srcp+2) + (2 * *(srcp+5)) + *(srcp+8);
00174                 
00175             *dst++ = r / 16;
00176             *dst++ = g / 16;
00177             *dst++ = b / 16;
00178         }
00179         src += 6;
00180         dst += 6;
00181     }
00182 }
00183     
00184 #ifdef __cplusplus
00185 }; /* extern "C" */
00186 #endif /* __cplusplus */
00187 
00188 /* ---------------------------------------------------------------------- */
00189 gaussian3x3_Filter::gaussian3x3_Filter() :
00190     phFilter("gaussian3x3_Filter")
00191 
00192 {
00193     this->m_format = phImageRGB24 | 
00194                      phImageBGR24 |
00195                      phImageHSV24 |
00196                      phImageSCT24;
00197     this->m_output = NULL;
00198     this->m_outputSize = 0;
00199 }
00200 
00201 /* ---------------------------------------------------------------------- */
00202 gaussian3x3_Filter::~gaussian3x3_Filter()
00203 {
00204     phFree(this->m_output);
00205 }
00206 
00207 /* ------------------------------------------------------------------------ */
00208 phFilter *gaussian3x3_Filter::cloneFilter()
00209 {
00210     return (phFilter *)new gaussian3x3_Filter();
00211 }
00212 
00213 /* ---------------------------------------------------------------------- */
00214 int gaussian3x3_Filter::filter() 
00215 {
00216     phFUNCTION("gaussian3x3::filter")
00217 
00218     phDALLOC_RESIZE(this->m_output,
00219                     this->m_outputSize,
00220                     width*height*depth,
00221                     uint8_t);
00222 
00223     rc = ipl_blur_gaussian( (uint8_t *)Image, 
00224                             (uint8_t *)this->m_output,
00225                             width,
00226                             height,
00227                             3 );
00228     phCHECK_RC(rc,NULL,"ipl_blur_gaussian error.");
00229     
00230     phMemcpy(Image,
00231            this->m_output,
00232            this->m_outputSize);
00233 
00234     return phSUCCESS;
00235 
00236 error:
00237 
00238     return phFAIL;
00239 } 
00240 




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