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

GenConvolImage.TCC

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------+
00002  | Library QgarLib, graphics analysis and recognition                  |
00003  | Copyright (C) 2002  Qgar Project, LORIA                             |
00004  |                                                                     |
00005  | This library is free software; you can redistribute it and/or       |
00006  | modify it under the terms of the GNU Lesser General Public          |
00007  | License version 2.1, as published by the Free Software Foundation.  |
00008  |                                                                     |
00009  | This library is distributed in the hope that it will be useful,     |
00010  | but WITHOUT ANY WARRANTY; without even the implied warranty of      |
00011  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                |
00012  | See the GNU Lesser General Public License for more details.         |
00013  |                                                                     |
00014  | The GNU Lesser General Public License is included in the file       |
00015  | LICENSE.LGPL, in the root directory of the Qgar packaging. See      |
00016  | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. |
00017  | To receive a paper copy, write to the Free Software Foundation,     |
00018  | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.       |
00019  |                                                                     |
00020  | Contact Project Qgar for any information:                           |
00021  |   LORIA - équipe Qgar                                               |
00022  |   B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France                |
00023  |   email: qgar-contact@loria.fr                                      |
00024  |   http://www.qgar.org/                                              |
00025  *---------------------------------------------------------------------*/
00026 
00027 
00028 /**
00029  * @file   GenConvolImage.TCC
00030  * @brief  Implementation of function members of class qgar::GenConvolImage.
00031  *
00032  * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a>
00033  * @date   January 27, 2005  20:54
00034  * @since  Qgar 2.2
00035  */
00036 
00037 
00038 
00039 // QGAR
00040 #include <qgarlib/GenImage.H>
00041 #include <qgarlib/GenMask1d.H>
00042 #include <qgarlib/GenMask2d.H>
00043 
00044 
00045 
00046 namespace qgar
00047 {
00048 
00049 
00050 // -------------------------------------------------------------------
00051 // C O N S T R U C T O R S
00052 // -------------------------------------------------------------------
00053 
00054 
00055 // CONSTRUCTOR FROM AN IMAGE AND A 1D MASK
00056 
00057 template<class T, template<class> class CheckingPolicy>
00058 template
00059 <
00060   class ImageType, 
00061   template<class> class ImageCheckPolicy, 
00062   class MaskType
00063 >
00064 GenConvolImage<T, CheckingPolicy>::GenConvolImage(
00065   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00066   const GenMask1d<MaskType>& aMask,
00067   QGEaxis anAxis)
00068 
00069   : GenImage<T, CheckingPolicy>(anImg.width(), anImg.height())
00070 
00071 {
00072   // Convert mask to a mask of doubles.
00073   DMask1d mask(aMask);
00074 
00075   if (anAxis == QGE_AXIS_X)
00076     {
00077       xconvol(anImg, mask);
00078     }
00079   else
00080     {
00081       yconvol(anImg, mask);
00082     }  
00083 }
00084 
00085 
00086 // CONSTRUCTOR SPECIALIZATION WITH A DOUBLE 1D MASK
00087 //
00088 // Since the mask coeffs are already in double format, there is no
00089 // need for converting it before calling the convolution
00090 
00091 template<class T, template<class> class CheckingPolicy>
00092 template
00093 <
00094   class ImageType, 
00095   template<class> class ImageCheckPolicy
00096 >
00097 GenConvolImage<T, CheckingPolicy>::GenConvolImage(
00098   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00099   const GenMask1d<double>& aMask,
00100   QGEaxis anAxis)
00101 
00102   : GenImage<T, CheckingPolicy>(anImg.width(), anImg.height())
00103 
00104 {
00105   if (anAxis == QGE_AXIS_X)
00106     {
00107       xconvol(anImg, aMask);
00108     }
00109   else
00110     {
00111       yconvol(anImg, aMask);
00112     }  
00113 }
00114 
00115 
00116 
00117 // 2D CONVOLUTION
00118 
00119 template<class T, template<class> class CheckingPolicy>
00120 template
00121 <
00122   class ImageType, 
00123   template<class> class ImageCheckPolicy, 
00124   class MaskType
00125 >
00126 GenConvolImage<T, CheckingPolicy>::GenConvolImage(
00127   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00128   const GenMask2d<MaskType>& aMask)
00129 
00130   : GenImage<T, CheckingPolicy>(anImg.width(), anImg.height())
00131 
00132 {
00133   // Convert mask to a mask of doubles.
00134   DMask2d mask(aMask);
00135 
00136   convol(anImg, mask);
00137 }
00138 
00139 
00140 // CONSTRUCTOR SPECIALIZATION WITH A DOUBLE 2D MASK
00141 //
00142 // Since the mask coeffs are already in double format, there is no
00143 // need for converting it before calling the convolution
00144 
00145 template<class T, template<class> class CheckingPolicy>
00146 template
00147 <
00148   class ImageType, 
00149   template<class> class ImageCheckPolicy
00150 >
00151 GenConvolImage<T, CheckingPolicy>::GenConvolImage(
00152   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00153   const GenMask2d<double>& aMask)
00154 
00155   : GenImage<T, CheckingPolicy>(anImg.width(), anImg.height())
00156 
00157 {
00158   convol(anImg, aMask);
00159 }
00160 
00161 
00162 // COPY CONSTRUCTOR
00163 
00164 template<class T, template<class> class CheckingPolicy>
00165 GenConvolImage<T, CheckingPolicy>::GenConvolImage(const GenConvolImage& other)
00166 
00167   : GenImage<T, CheckingPolicy>(other)
00168 
00169 {
00170   // EMPTY
00171 }
00172 
00173 
00174 // -------------------------------------------------------------------
00175 // D E S T R U C T O R 
00176 // -------------------------------------------------------------------
00177 
00178 
00179 template<class T, template<class> class CheckingPolicy>
00180 GenConvolImage<T, CheckingPolicy>::~GenConvolImage()
00181 {
00182   // EMPTY
00183 }
00184 
00185 
00186 // -------------------------------------------------------------------
00187 // 1 D   C O N V O L U T I O N S
00188 // -------------------------------------------------------------------
00189 
00190 
00191 // X AXIS
00192 
00193 template<class T, template<class> class CheckingPolicy>
00194 template
00195 <
00196   class ImageType, 
00197   template<class> class ImageCheckPolicy
00198 >
00199 void 
00200 GenConvolImage<T, CheckingPolicy>::xconvol(
00201   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00202   const DMask1d& aMask)
00203 {
00204   int r = 0;
00205   int c = 0;
00206   int sizeMask = aMask.width() / 2;
00207 
00208   // Inner region
00209   for (/* EMPTY */ ; r < this->_height ; ++r) 
00210     {
00211       ImageType *p = anImg.pPixMap() + r * this->_width;
00212       T         *q = this->_pPixMap + r * this->_width + sizeMask;
00213       for (c = sizeMask ; c < this->_width - sizeMask; ++c, ++p)
00214         {
00215           double sum = 0.0;
00216           ImageType * pp = p;
00217           double* mm = aMask.pCoeffMap();
00218           for (int j = 0 ; j < aMask.width() ; ++j)
00219             {
00220               sum += *pp * *mm;
00221               ++pp;
00222               ++mm;
00223             }
00224           *q = static_cast<T>(sum);
00225           ++q;
00226         }
00227     }
00228 
00229   // Border regions
00230   for (r = 0 ; r < this->_height; ++r)
00231     {
00232       T         *q = this->_pPixMap + r * this->_width;
00233       ImageType *p = anImg.pPixMap() + r * this->_width;
00234       for (c = 0 ; c < sizeMask ; ++c)
00235         {
00236           double sum = 0.0;
00237           double * mm = aMask.pCoeffMap();
00238           int cc = c - sizeMask;
00239           for (int j = 0 ; j < aMask.width() ; ++j, ++cc)
00240             {
00241               sum += *(p + this->borderCols(cc)) * *mm;
00242               ++mm;
00243             }
00244           *q = static_cast<T>(sum);
00245           ++q;
00246         }
00247 
00248       // Reset
00249       q = this->_pPixMap + r * this->_width + this->_width - sizeMask;
00250 
00251       for (c = this->_width - sizeMask ; c < this->_width ; ++c) 
00252         {
00253           double sum = 0.0;
00254           double * mm = aMask.pCoeffMap();
00255           int cc = c - sizeMask;
00256           for (int j = 0 ; j < aMask.width() ; ++j, ++cc)
00257             {
00258               sum += *(p + this->borderCols(cc)) * *mm;
00259               ++mm;
00260             }
00261           *q = static_cast<T>(sum);
00262           ++q;
00263         }
00264     }
00265 }
00266 
00267 
00268 // Y AXIS
00269 
00270 template<class T, template<class> class CheckingPolicy>
00271 template
00272 <
00273   class ImageType, 
00274   template<class> class ImageCheckPolicy
00275 >
00276 void 
00277 GenConvolImage<T, CheckingPolicy>::yconvol(
00278   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00279   const DMask1d& aMask)
00280 {
00281   int c = 0;
00282   int sizeMask = aMask.width() / 2;
00283   int r = sizeMask;
00284 
00285   // Inner region
00286   for ( ; r < this->_height - sizeMask ; ++r) 
00287     {
00288       ImageType *p = anImg.pPixMap() + (r - sizeMask) * this->_width;
00289       T         *q = this->_pPixMap + r * this->_width;
00290       for ( c = 0 ; c < this->_width; ++c, ++p)
00291         {
00292           double sum = 0.0;
00293           ImageType * pp = p;
00294           double * mm = aMask.pCoeffMap();
00295           for (int j = 0 ; j < aMask.width() ; ++j, pp += this->_width)
00296             {
00297               sum += *pp * *mm;
00298               ++mm;
00299             }
00300           *q = static_cast<T>(sum);
00301           ++q;
00302         }
00303     }
00304 
00305   // Border regions
00306   for (r = 0 ; r < sizeMask ; ++r)
00307     {
00308       T *q = this->_pPixMap + r * this->_width;
00309       for (c = 0 ; c < this->_width ; ++c)
00310         {
00311           double sum = 0.0;
00312           double * mm = aMask.pCoeffMap();
00313           int l = r - sizeMask;
00314           for (int j = 0 ; j < aMask.width() ; ++j, ++l)
00315             {
00316               sum +=
00317                 *(anImg.pPixMap() + this->borderRows(l) * this->_width + c) * *mm;
00318               ++mm;
00319             }
00320           *q = static_cast<T>(sum);
00321           ++q;
00322         }
00323     }
00324 
00325   for (r = this->_height - sizeMask ; r < this->_height ; ++r)
00326     {
00327       T *q = this->_pPixMap + r * this->_width;
00328       for (c = 0 ; c < this->_width ; ++c)
00329         {
00330           double sum = 0.0;
00331           double * mm = aMask.pCoeffMap();
00332           int l = r - sizeMask;
00333           for (int j = 0 ; j < aMask.width() ; ++j, ++l)
00334             {
00335               sum += 
00336                 *(anImg.pPixMap() + this->borderRows(l) * this->_width + c) * *mm;
00337               ++mm;
00338             }
00339           *q = static_cast<T>(sum);
00340           ++q;
00341         }
00342     }
00343 }
00344 
00345 
00346 // -------------------------------------------------------------------
00347 // 2 D   C O N V O L U T I O N S
00348 // -------------------------------------------------------------------
00349 
00350 
00351 template<class T, template<class> class CheckingPolicy>
00352 template
00353 <
00354   class ImageType,
00355   template<class> class OtherCheckPolicy
00356 >
00357 double
00358 GenConvolImage<T, CheckingPolicy>::applyMaskWithRowAndColMirroring
00359   (const GenImage<ImageType,OtherCheckPolicy>& img,
00360    const DMask2d& mask,
00361    int imgRow,
00362    int imgCol)
00363 {
00364   double sum = 0.;
00365   double * pMask = mask.pCoeffMap();
00366 
00367   for (int row=0; row < mask.height(); ++row)
00368     {
00369       ImageType * pRow = img.pRow(img.borderRows(imgRow + row));
00370       
00371       for(int col=0; col < mask.width(); ++col)
00372         {
00373           sum += pRow[img.borderCols(imgCol + col)] * (*pMask);
00374           ++pMask;
00375         }
00376     }
00377   
00378   return sum;
00379 }
00380 
00381 
00382 
00383 template<class T, template<class> class CheckingPolicy>
00384 template
00385 <
00386   class ImageType,
00387   template<class> class OtherCheckPolicy
00388 >
00389 double
00390 GenConvolImage<T, CheckingPolicy>::applyMaskWithColMirroring
00391   (const GenImage<ImageType,OtherCheckPolicy>& img,
00392    const DMask2d mask,
00393    int imgRow,
00394    int imgCol)
00395 {
00396   double sum = 0.;
00397   double * pMask = mask.pCoeffMap();
00398   
00399   for (int row=0; row < mask.height(); ++row)
00400     {
00401       ImageType * pRow = img.pRow(imgRow + row);
00402       
00403       for(int col=0; col < mask.width(); ++col)
00404         {
00405           sum += pRow[img.borderCols(imgCol + col)] * (*pMask);
00406           ++pMask;
00407         }
00408     }
00409   return sum;
00410 }
00411 
00412 
00413 
00414 template<class T, template<class> class CheckingPolicy>
00415 template
00416 <
00417   class ImageType,
00418   template<class> class OtherCheckPolicy
00419 >
00420 double
00421 GenConvolImage<T, CheckingPolicy>::applyMaskWithRowMirroring
00422   (const GenImage<ImageType,OtherCheckPolicy>& img,
00423    const DMask2d mask,
00424    int imgRow,
00425    int imgCol)
00426 {
00427   double sum = 0.;  
00428   double * pMask = mask.pCoeffMap();
00429 
00430   for (int row=0; row < mask.height(); ++row)
00431     {
00432       ImageType * pPix = img.pPixel(img.borderRows(imgRow + row), imgCol);
00433       
00434       for (int col = 0 ; col < mask.width() ; ++col)
00435         {
00436           sum += (*pPix) * (*pMask);
00437           ++pPix;
00438           ++pMask;
00439         }
00440       
00441     }
00442   return sum;
00443 }
00444   
00445 
00446 
00447 template<class T, template<class> class CheckingPolicy>
00448 template
00449 <
00450   class ImageType,
00451   template<class> class OtherCheckPolicy
00452 >
00453 double
00454 GenConvolImage<T, CheckingPolicy>::applyMask
00455  (const GenImage<ImageType,OtherCheckPolicy>& img,
00456   const DMask2d mask,
00457   int imgRow,
00458   int imgCol)
00459 {
00460   double sum = 0.;
00461   double * pMask = mask.pCoeffMap();
00462 
00463   for (int row=0; row < mask.height(); ++row)
00464     {
00465       ImageType * pPix = img.pPixel(imgRow + row, imgCol);      
00466 
00467       for (int col=0; col < mask.width(); ++col)
00468         {
00469           sum += (*pPix) * (*pMask);
00470           ++pPix;
00471           ++pMask;
00472         }      
00473     }  
00474   return sum;
00475 }
00476 
00477 
00478 
00479 template<class T, template<class> class CheckingPolicy>
00480 template
00481 <
00482   class ImageType, 
00483   template<class> class ImageCheckPolicy
00484 >
00485 void 
00486 GenConvolImage<T, CheckingPolicy>::convol(
00487   const GenImage<ImageType, ImageCheckPolicy>& anImg,
00488   const DMask2d& aMask)
00489 {
00490   //-- Init
00491 
00492   int row; // The current row
00493   int col; // The current column
00494 
00495   int maskWd = aMask.width()  / 2; // Half of the mask width
00496   int maskHt = aMask.height() / 2; // Half of the mask height
00497 
00498   unsigned int blockBeginRow = -maskHt;
00499   unsigned int blockBeginCol = -maskWd;
00500 
00501   T* imgPtr = this->_pPixMap;
00502 
00503   //-- Lines between 0 and half of the mask height
00504 
00505   for (row=0; row < maskHt; ++row, ++blockBeginRow)
00506     {
00507       blockBeginCol = -maskWd;
00508       // Cols in [0..mask_size/2[ (need border mirroring up and left)
00509       for(col=0; col < maskWd; ++col, ++blockBeginCol)
00510         {
00511           *imgPtr = 
00512             static_cast<T>(applyMaskWithRowAndColMirroring(anImg,
00513                                                            aMask,
00514                                                            blockBeginRow,
00515                                                            blockBeginCol));
00516           ++imgPtr;
00517         }
00518 
00519 
00520       // Inner Cols apply (need border mirroring up).
00521       for(/* EMPTY */; col < (this->_width - maskWd); ++col, ++blockBeginCol)
00522         {
00523           *imgPtr = 
00524             static_cast<T>(applyMaskWithRowMirroring(anImg,
00525                                                      aMask,
00526                                                      blockBeginRow,
00527                                                      blockBeginCol));
00528           ++imgPtr;
00529         }
00530 
00531       // Cols in [_width - maskWd.. _width] (need border mirroring up
00532       // and right
00533       for(/* EMPTY */; col < this->_width; ++col, ++blockBeginCol)
00534         {
00535           *imgPtr = 
00536             static_cast<T>(applyMaskWithRowAndColMirroring(anImg,
00537                                                            aMask,
00538                                                            blockBeginRow,
00539                                                            blockBeginCol));
00540           ++imgPtr;
00541         }
00542     }
00543 
00544 
00545   //-- Lines between [maskHt..height - maskHt[
00546 
00547   for (/* EMPTY */; row < (this->_height - maskHt); ++row, ++blockBeginRow)
00548     {
00549       blockBeginCol = -maskWd;
00550 
00551       // Cols in [0..mask_size/2[ (need border mirroring up and left)
00552       for(col=0; col < maskWd; ++col, ++blockBeginCol)
00553         {
00554           *imgPtr = 
00555             static_cast<T>(applyMaskWithColMirroring(anImg,
00556                                                      aMask,
00557                                                      blockBeginRow,
00558                                                      blockBeginCol));
00559           ++imgPtr;
00560         }
00561       
00562       // Inner Cols apply (need border mirroring up).
00563       for(/* EMPTY */; col < (this->_width - maskWd); ++col, ++blockBeginCol)
00564         {
00565           *imgPtr = 
00566             static_cast<T>(applyMask(anImg,
00567                                      aMask,
00568                                      blockBeginRow,
00569                                      blockBeginCol));
00570           ++imgPtr;
00571         }
00572 
00573       // Cols in [_width - maskWd.. _width]
00574       for(/* EMPTY */; col < this->_width; ++col, ++blockBeginCol)
00575         {
00576           *imgPtr = 
00577             static_cast<T>(applyMaskWithColMirroring(anImg,
00578                                                      aMask,
00579                                                      blockBeginRow,
00580                                                      blockBeginCol));
00581           ++imgPtr;
00582         }
00583     }
00584 
00585 
00586   //-- Lines between [height - maskHt..height[
00587   
00588   for(/* EMPTY */; row < this->_height; ++row, ++blockBeginRow)
00589     {
00590       blockBeginCol = -maskWd;
00591 
00592      // Cols in [0..mask_size/2[ (need border mirroring up and left)
00593       for(col=0; col < maskWd; ++col, ++blockBeginCol)
00594         {
00595           *imgPtr = 
00596             static_cast<T>(applyMaskWithRowAndColMirroring(anImg,
00597                                                            aMask,
00598                                                            blockBeginRow,
00599                                                            blockBeginCol));
00600           ++imgPtr;
00601         }
00602 
00603 
00604       // Inner Cols apply (need border mirroring up).
00605       for(/* EMPTY */; col < (this->_width - maskWd); ++col, ++blockBeginCol)
00606         {
00607           *imgPtr = 
00608             static_cast<T>(applyMaskWithRowMirroring(anImg,
00609                                                      aMask,
00610                                                      blockBeginRow,
00611                                                      blockBeginCol));
00612           ++imgPtr;
00613         }
00614 
00615       // Cols in [_width - maskWd.. _width]
00616       for(/* EMPTY */; col < this->_width; ++col, ++blockBeginCol)
00617         {
00618           *imgPtr = 
00619             static_cast<T>(applyMaskWithRowAndColMirroring(anImg,
00620                                                            aMask,
00621                                                            blockBeginRow,
00622                                                            blockBeginCol));
00623           ++imgPtr;
00624         }
00625     }
00626 }
00627 
00628 
00629 // -------------------------------------------------------------------
00630 
00631 
00632 } // namespace qgar