MorphOps.C

Go to the documentation of this file.
00001 /*!@file Image/MorphOps.C functions for binary morphology (dilate, erode, open, close) */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/MorphOps.C $
00035 // $Id: MorphOps.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 #ifndef IMAGE_MORPHOPS_C_DEFINED
00039 #define IMAGE_MORPHOPS_C_DEFINED
00040 
00041 #include "Image/MorphOps.H"
00042 
00043 #include "Image/Image.H"
00044 #include "rutz/trace.h"
00045 
00046 // ######################################################################
00047 template <class T>
00048 Image<T> dilateImg(const Image<T>& img, const Image<T>& se, Point2D<int> origin)
00049 {
00050 GVX_TRACE(__PRETTY_FUNCTION__);
00051   ASSERT(img.initialized() && se.initialized());
00052 
00053   int iw = img.getWidth(); int ih = img.getHeight();
00054   int sw =  se.getWidth(); int sh =  se.getHeight();
00055 
00056   if (origin == Point2D<int>(-1,-1))
00057     {
00058       origin.i = (sw - 1) / 2;
00059       origin.j = (sh - 1) / 2;
00060     }
00061   ASSERT((origin.i < sw) && (origin.j < sh));
00062 
00063   Image<T> result(iw,ih,ZEROS);
00064 
00065   typename Image<T>::const_iterator iptr, sptr1, sptr2;
00066   typename Image<T>::iterator rptr1, rptr2;
00067   iptr = img.begin();
00068 
00069   for (int iy = 0; iy < ih; ++iy)
00070     {
00071       // initialize height
00072       int rYstart = iy - origin.j;
00073       int rYend = rYstart + sh;
00074       int sYstart = 0;
00075       if (rYstart < 0)
00076         {
00077           sYstart -= rYstart;
00078           rYstart = 0;
00079         }
00080       if (rYend > ih) rYend = ih;
00081 
00082       for (int ix = 0; ix < iw; ++ix)
00083         {
00084           // do we have to do anything?
00085           if (*iptr != T())
00086             {
00087               //initialize pointers and width
00088               int rXstart = ix - origin.i;
00089               int rXend = rXstart + sw;
00090               int sXstart = 0;
00091               if (rXstart < 0)
00092                 {
00093                   sXstart -= rXstart;
00094                   rXstart = 0;
00095                 }
00096               if (rXend > iw) rXend = iw;
00097 
00098               rptr1 = result.beginw() + rYstart * iw + rXstart;
00099               sptr1 = se.begin() + sYstart * sw + sXstart;
00100 
00101               for (int ry = rYstart; ry < rYend; ++ry)
00102                 {
00103                   rptr2 = rptr1; sptr2 = sptr1;
00104                   for (int rx = rXstart; rx < rXend; ++rx)
00105                     {
00106                       *rptr2 = std::max(*rptr2,*sptr2);
00107                       ++rptr2; ++sptr2;
00108                     }
00109                   rptr1 += iw; sptr1 += sw;
00110                 }
00111             }  // end: we have to do something
00112           ++iptr;
00113         }  // end: for ix
00114     }  // end: for iy
00115   return result;
00116 }
00117 
00118 // ######################################################################
00119 template <class T>
00120 Image<T> erodeImg(const Image<T>& img, const Image<T>& se, Point2D<int> origin)
00121 {
00122 GVX_TRACE(__PRETTY_FUNCTION__);
00123   ASSERT(img.initialized() && se.initialized());
00124 
00125   int iw = img.getWidth(); int ih = img.getHeight();
00126   int sw =  se.getWidth(); int sh =  se.getHeight();
00127 
00128   if (origin == Point2D<int>(-1,-1))
00129     {
00130       origin.i = (sw - 1) / 2;
00131       origin.j = (sh - 1) / 2;
00132     }
00133   ASSERT((origin.i < sw) && (origin.j < sh));
00134 
00135   Image<T> result(iw,ih,ZEROS);
00136 
00137   typename Image<T>::const_iterator iptr1, iptr2, sptr1, sptr2;
00138   typename Image<T>::iterator rptr = result.beginw();
00139   T se_orig_val = se.getVal(origin);
00140 
00141   //loop over result X
00142   for (int ry = 0; ry < ih; ++ry)
00143     {
00144       // initialize height
00145       int iYstart = ry - origin.j;
00146       int iYend = iYstart + sh;
00147       int sYstart = 0;
00148       if (iYstart < 0)
00149         {
00150           sYstart -= iYstart;
00151           iYstart = 0;
00152         }
00153       if (iYend > ih) iYend = ih;
00154 
00155 
00156       // loop over result Y
00157       for (int rx = 0; rx < iw; ++rx)
00158         {
00159           int iXstart = rx - origin.i;
00160           int iXend = iXstart + sw;
00161           int sXstart = 0;
00162           if (iXstart < 0)
00163             {
00164               sXstart -= iXstart;
00165               iXstart = 0;
00166             }
00167           if (iXend > iw) iXend = iw;
00168 
00169           bool flag = true;   // reset the flag
00170           iptr1 = img.begin() + iYstart * iw + iXstart;
00171           sptr1 = se.begin() + sYstart * sw + sXstart;
00172 
00173           //loop over the image covered by the structuring element
00174           for (int iy = iYstart; iy < iYend; ++iy)
00175             {
00176 
00177               iptr2 = iptr1; sptr2 = sptr1;
00178               for (int ix = iXstart; ix < iXend; ++ ix)
00179                 {
00180                   if ((*sptr2 != 0) && (*iptr2 == 0))
00181                     {
00182                       flag = false;
00183                       break;
00184                     } // end: if (*iptr2 == 0)
00185                   ++iptr2; ++sptr2;
00186                 } // end: for ix
00187 
00188               if (!flag) break;
00189               iptr1 += iw; sptr1 += sw;
00190 
00191             } // end: for iy
00192 
00193           // should we set the pixel?
00194           if (flag) *rptr = std::max(*rptr, se_orig_val);
00195 
00196           ++rptr;
00197 
00198         } // end: for rx
00199     } // end: for ry
00200   return result;
00201 }
00202 
00203 // ######################################################################
00204 template <class T>
00205 Image<T> openImg(const Image<T>& img, const Image<T>& se, Point2D<int> origin)
00206 {
00207   return dilateImg(erodeImg(img,se,origin),se,origin);
00208 }
00209 
00210 // ######################################################################
00211 template <class T>
00212 Image<T> closeImg(const Image<T>& img, const Image<T>& se, Point2D<int> origin)
00213 {
00214   return erodeImg(dilateImg(img,se,origin),se,origin);
00215 }
00216 
00217 // Include the explicit instantiations
00218 #include "inst/Image/MorphOps.I"
00219 
00220 // ######################################################################
00221 /* So things look consistent in everyone's emacs... */
00222 /* Local Variables: */
00223 /* mode: c++ */
00224 /* indent-tabs-mode: nil */
00225 /* End: */
00226 
00227 #endif // IMAGE_MORPHOPS_C_DEFINED
Generated on Sun May 8 08:05:14 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3