Basic Image AlgorithmS Library 2.8.0

Convolution.cpp

00001 /*
00002 This file is part of the BIAS library (Basic ImageAlgorithmS).
00003 
00004 Copyright (C) 2004 (see file CONTACT for details)
00005   Johan Skoglund
00006   skoglund@isy.liu.se
00007   CVL/isy
00008   university of Linkoeping
00009   sweden
00010 
00011   Multimediale Systeme der Informationsverarbeitung
00012   Institut fuer Informatik
00013   Christian-Albrechts-Universitaet Kiel
00014 
00015 BIAS 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.1 of the License, or
00018 (at your option) any later version.
00019 
00020 BIAS 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 BIAS; if not, write to the Free Software
00027 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 */
00029 
00030 /// \todo This file contains no kind of optimization at all for the moment.
00031 /// To be added later on
00032 
00033 #include "Convolution.hh"
00034 
00035 #ifdef BIAS_DEBUG
00036 #include "Base/Image/ImageIO.hh"
00037 #endif
00038 
00039 #include <Base/Common/BIASpragma.hh>
00040 
00041 using namespace BIAS;
00042 using namespace std;
00043 
00044 //calculates the center pixel in the convolution kernel.
00045 #define KERNCENTER(thesize) ((thesize-1)>>1)
00046 
00047 
00048 template <class InputStorageType,class OutputStorageType>
00049 int Convolution<InputStorageType,OutputStorageType>::
00050 ConvIntMat_(const Image<InputStorageType> &src, Image<OutputStorageType> &dst) 
00051 {
00052   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::ConvIntMat_\n");
00053   const InputStorageType **srcstart=src.GetImageDataArray();
00054   OutputStorageType **dststart=dst.GetImageDataArray();
00055   const Matrix<FM_INT> *kernel=_fm.GetKerneli();
00056   int kern_width=kernel->GetCols();
00057   int kern_height=kernel->GetRows();
00058   int img_width=src.GetWidth();
00059   int img_height=src.GetHeight();
00060   int channelcount=src.GetChannelCount();
00061 
00062   int kern_center_x=KERNCENTER(kern_width);
00063   int kern_center_y=KERNCENTER(kern_height);
00064 
00065   signed char rightshift=_fm.GetKernelRightShift();
00066   const InputStorageType **srcida = NULL;
00067   OutputStorageType **dstida = NULL;
00068   
00069   // distance between neighboring pixels in storagetypes
00070   const int PixelSpacing = (src.IsInterleaved())? channelcount : 1;
00071 
00072   int offset = 0;
00073   for(int chloop=0;chloop<channelcount;chloop++) {
00074     if (src.IsInterleaved()) {
00075       srcida = srcstart;
00076       dstida = dststart;
00077       // ida[y][PixelSpacing*x] gives first channel, need an offset
00078       offset = chloop;
00079     } else {
00080       // get start of plane:
00081       srcida = srcstart + chloop*img_height;
00082       dstida = dststart + chloop*img_height;
00083       offset = 0;
00084     }
00085     for(int img_x=0;img_x<img_width;img_x++)
00086       for(int img_y=0;img_y<img_height;img_y++) {
00087         register CONV_INT sum=0;
00088         for(int kern_x=0;kern_x<kern_width;kern_x++)
00089           for(int kern_y=0;kern_y<kern_height;kern_y++) {
00090             //kern_center_x-kern_x -> img_offset
00091             int img_offset_x=kern_center_x-kern_x;
00092             int img_offset_y=kern_center_y-kern_y;
00093             if(img_offset_x+img_x<0)
00094               continue;
00095             if(img_offset_y+img_y<0)
00096               continue;
00097             if(img_x+img_offset_x>=img_width)
00098               continue;
00099             if(img_y+img_offset_y>=img_height)
00100               continue;
00101             sum +=(CONV_INT) (srcida[img_y+img_offset_y][(img_x+img_offset_x)
00102                                                          *PixelSpacing+offset]*
00103                               ((*kernel)[kern_y][kern_x]));
00104           }
00105         dstida[img_y][img_x*PixelSpacing+offset]=
00106           (OutputStorageType)((sum)>>rightshift);
00107       }
00108   }
00109 
00110   return 0;
00111 }
00112 
00113 template <class InputStorageType,class OutputStorageType>
00114 int Convolution<InputStorageType,OutputStorageType>::
00115 ConvIntHori_(const Image<InputStorageType> &src, Image<CONV_INT> &dst) 
00116 { 
00117   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::ConvIntHori_\n");
00118   const InputStorageType **srcstart=src.GetImageDataArray();
00119   CONV_INT **dststart=dst.GetImageDataArray();
00120   const Vector<FM_INT> *kernel=_fm.GetSepih();
00121   int kern_width=kernel->Size();
00122   int img_width=src.GetWidth();
00123   int img_height=src.GetHeight();
00124   int channelcount=src.GetChannelCount();
00125 
00126   int kern_center_x=KERNCENTER(kern_width);
00127 
00128   signed char rightshift=_fm.GetHorizRightShift();
00129   const InputStorageType **srcida = NULL;
00130   CONV_INT **dstida = NULL;
00131   
00132   // distance between neighboring pixels in storagetypes
00133   const int PixelSpacing = (src.IsInterleaved())? channelcount : 1;
00134   int offset = 0;
00135   for(int chloop=0;chloop<channelcount;chloop++) {
00136     if (src.IsInterleaved()) {
00137       srcida = srcstart;
00138       dstida = dststart;
00139       // ida[y][PixelSpacing*x] gives first channel, need an offset
00140       offset = chloop;
00141     } else {
00142       // get start of plane:
00143       srcida = srcstart + chloop*img_height;
00144       dstida = dststart + chloop*img_height;
00145       offset = 0;
00146     }
00147     
00148     for(int img_y=0;img_y<img_height;img_y++) {
00149       for(int img_x=0;img_x<img_width;img_x++) {
00150         int kern_xmax=min((kern_center_x+img_x+1),kern_width);
00151         int kern_xmin=max(0,(img_x+kern_center_x-img_width+1));
00152         register CONV_INT sum=0;
00153 
00154         for(int kern_x=kern_xmin;kern_x<kern_xmax;kern_x++) {
00155           int img_offset_x=kern_center_x-kern_x;
00156           sum += 
00157             (CONV_INT)(srcida[img_y][(img_x+img_offset_x)*PixelSpacing+offset])
00158             *((*kernel)[kern_x]);
00159         }
00160         dstida[img_y][img_x*PixelSpacing+offset] = 
00161           (CONV_INT)((sum)>>rightshift);
00162       }
00163     }
00164   }
00165 
00166   return 0;
00167 }
00168 
00169 template <class InputStorageType,class OutputStorageType>
00170 int Convolution<InputStorageType,OutputStorageType>::
00171 ConvIntVert_(const Image<CONV_INT> &src, Image<OutputStorageType> &dst) 
00172 { 
00173   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::ConvIntVert_\n");
00174   const CONV_INT **srcstart=src.GetImageDataArray();
00175   OutputStorageType **dststart=dst.GetImageDataArray();
00176   const Vector<FM_INT> *kernel=_fm.GetSepiv();
00177   int kern_height=kernel->Size();
00178   int img_width=src.GetWidth();
00179   int img_height=src.GetHeight();
00180   int channelcount=src.GetChannelCount();
00181 
00182   int kern_center_y=KERNCENTER(kern_height);
00183 
00184   signed char rightshift=_fm.GetVertRightShift();
00185   const CONV_INT **srcida = NULL;
00186   OutputStorageType **dstida = NULL;
00187   
00188   // distance between neighboring pixels in storagetypes
00189   const int PixelSpacing = (src.IsInterleaved())? channelcount : 1;
00190 
00191   int offset = 0;
00192 
00193   for(int chloop=0;chloop<channelcount;chloop++) {
00194     if (src.IsInterleaved()) {
00195       srcida = srcstart;
00196       dstida = dststart;
00197       // ida[y][PixelSpacing*x] gives first channel, need an offset
00198       offset = chloop;
00199     } else {
00200       // get start of plane:
00201       srcida = srcstart + chloop*img_height;
00202       dstida = dststart + chloop*img_height;
00203       offset = 0;
00204     }
00205      
00206     for(int img_y=0;img_y<img_height;img_y++) {
00207       int kern_ymax=min((kern_center_y+img_y+1),kern_height);
00208       int kern_ymin=max(0,(img_y+kern_center_y-img_height+1));
00209       
00210       for(int img_x=0;img_x<img_width;img_x++) {
00211         register CONV_INT sum=0;
00212         for(int kern_y=kern_ymin;kern_y<kern_ymax;kern_y++)  {
00213           int img_offset_y=kern_center_y-kern_y;
00214           sum += 
00215             (CONV_INT)(srcida[img_y+img_offset_y][img_x*PixelSpacing+offset])*
00216             ((*kernel)[kern_y]);
00217         }
00218         dstida[img_y][img_x*PixelSpacing+offset]=
00219           (OutputStorageType)((sum)>>rightshift);
00220       }
00221     }
00222   }
00223   return 0;
00224 }
00225 
00226 template <class InputStorageType,class OutputStorageType>
00227 int Convolution<InputStorageType,OutputStorageType>::
00228 ConvFloatMat_(const Image<InputStorageType> &src,
00229               Image<OutputStorageType> &dst) { 
00230   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::ConvFloatMat_\n");
00231   const InputStorageType **srcstart  = src.GetImageDataArray();
00232   OutputStorageType **dststart = dst.GetImageDataArray();
00233   const Matrix<FM_FLOAT> *kernel=_fm.GetKernelf();
00234   const int kern_width   = kernel->GetCols();
00235   const int kern_height  = kernel->GetRows();
00236   const int img_width    = src.GetWidth();
00237   const int img_height   = src.GetHeight();
00238   const int channelcount = src.GetChannelCount();
00239   const int kern_center_x = KERNCENTER(kern_width);
00240   const int kern_center_y = KERNCENTER(kern_height);
00241 
00242   const InputStorageType **srcida = NULL;
00243   OutputStorageType **dstida = NULL;
00244   
00245   // distance between neighboring pixels in storagetypes
00246   const int PixelSpacing = (src.IsInterleaved())? channelcount : 1;
00247 
00248   int offset = 0;
00249   for(int chloop=0;chloop<channelcount;chloop++) {
00250     if (src.IsInterleaved()) {
00251       srcida = srcstart;
00252       dstida = dststart;
00253       // ida[y][PixelSpacing*x] gives first channel, need an offset
00254       offset = chloop;
00255     } else {
00256       // get start of plane:
00257       srcida = srcstart + chloop*img_height;
00258       dstida = dststart + chloop*img_height;
00259       offset = 0;
00260     }
00261     for(int img_x=0;img_x<img_width;img_x++)
00262       for(int img_y=0;img_y<img_height;img_y++) {
00263         register CONV_FLOAT sum=0;
00264         for(int kern_x=0;kern_x<kern_width;kern_x++)
00265           for(int kern_y=0;kern_y<kern_height;kern_y++) {
00266             //kern_center_x-kern_x -> img_offset
00267             int img_offset_x=kern_center_x-kern_x*PixelSpacing;
00268             int img_offset_y=kern_center_y-kern_y;
00269             if(img_offset_x+img_x<0)
00270               continue;
00271             if(img_offset_y+img_y<0)
00272               continue;
00273             if(img_x+img_offset_x>=img_width)
00274               continue;
00275             if(img_y+img_offset_y>=img_height)
00276               continue;
00277             sum += (CONV_FLOAT)srcida[img_y+img_offset_y][(img_x+img_offset_x)*
00278                                                           PixelSpacing+offset] 
00279               * ((*kernel)[kern_y][kern_x]);
00280           }
00281         dstida[img_y][img_x*PixelSpacing+offset] = (OutputStorageType)sum;
00282       }
00283   }
00284 
00285   return 0;
00286 }
00287 
00288 template <class InputStorageType,class OutputStorageType>
00289 int Convolution<InputStorageType,OutputStorageType>::
00290 ConvFloatHori_(const Image<InputStorageType> &src, Image<CONV_FLOAT> &dst)
00291 { 
00292   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::ConvFloatHori_\n");
00293   const InputStorageType **srcstart=src.GetImageDataArray();
00294   CONV_FLOAT **dststart=dst.GetImageDataArray();
00295   const Vector<FM_FLOAT> *kernel=_fm.GetSepfh();
00296   int kern_width=kernel->Size();
00297   int img_width=src.GetWidth();
00298   int img_height=src.GetHeight();
00299   int channelcount=src.GetChannelCount();
00300 
00301   int kern_center_x=KERNCENTER(kern_width);
00302   const InputStorageType **srcida = NULL;
00303   CONV_FLOAT **dstida = NULL;
00304   int offset = 0;
00305   // distance between neighboring pixels in storagetypes
00306   const int PixelSpacing = (src.IsInterleaved())? channelcount : 1;
00307   
00308 
00309   for(int chloop=0;chloop<channelcount;chloop++)  {
00310     if (src.IsInterleaved()) {
00311       srcida = srcstart;
00312       dstida = dststart;
00313       // ida[y][PixelSpacing*x] gives first channel, need an offset
00314       offset = chloop;
00315     } else {
00316       // get start of plane:
00317       srcida = srcstart + chloop*img_height;
00318       dstida = dststart + chloop*img_height;
00319       offset = 0;
00320     }
00321 
00322     
00323     for(int img_y=0;img_y<img_height;img_y++){
00324       for(int img_x=0;img_x<img_width;img_x++) {
00325         int kern_xmax=min((kern_center_x+img_x+1),kern_width);
00326         int kern_xmin=max(0,(img_x+kern_center_x-img_width+1));
00327         register CONV_FLOAT sum=0;
00328         for(int kern_x=kern_xmin;kern_x<kern_xmax;kern_x++)       {
00329           int img_offset_x=kern_center_x-kern_x;
00330           sum+=CONV_FLOAT(srcida[img_y]
00331                           [(img_x+img_offset_x)*PixelSpacing+offset])*
00332             ((*kernel)[kern_x]);
00333         }
00334         dstida[img_y][img_x*PixelSpacing+offset]=(CONV_FLOAT)sum;
00335       }
00336     }
00337   }
00338 
00339   return 0;
00340 }
00341 
00342 template <class InputStorageType,class OutputStorageType>
00343 int Convolution<InputStorageType,OutputStorageType>::
00344 ConvFloatVert_(const Image<CONV_FLOAT> &src, Image<OutputStorageType> &dst) 
00345 { 
00346   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::ConvFloatVert_\n");
00347   const CONV_FLOAT **srcstart=src.GetImageDataArray();
00348   OutputStorageType **dststart=dst.GetImageDataArray();
00349   const Vector<FM_FLOAT> *kernel=_fm.GetSepfv();
00350   int kern_height=kernel->Size();
00351   int img_width=src.GetWidth();
00352   int img_height=src.GetHeight();
00353   int channelcount=src.GetChannelCount();
00354 
00355   int kern_center_y=KERNCENTER(kern_height);
00356   const CONV_FLOAT **srcida = NULL;
00357   OutputStorageType **dstida = NULL;
00358   int offset = 0;
00359   // distance between neighboring pixels in storagetypes
00360   const int PixelSpacing = (src.IsInterleaved())? channelcount : 1;
00361   for(int chloop=0;chloop<channelcount;chloop++)    { 
00362     if (src.IsInterleaved()) {
00363       srcida = srcstart;
00364       dstida = dststart;
00365       // ida[y][PixelSpacing*x] gives first channel, need an offset
00366       offset = chloop;
00367     } else {
00368       // get start of plane:
00369       srcida = srcstart + chloop*img_height;
00370       dstida = dststart + chloop*img_height;
00371       offset = 0;
00372     }
00373     for(int img_y=0;img_y<img_height;img_y++) {
00374       int kern_ymax=min((kern_center_y+img_y+1),kern_height);
00375       int kern_ymin=max(0,(img_y+kern_center_y-img_height+1));
00376       for(int img_x=0;img_x<img_width;img_x++) {
00377         register CONV_FLOAT sum=0;
00378     for(int kern_y=kern_ymin;kern_y<kern_ymax;kern_y++)  {
00379       //         for(int kern_y=0;kern_y<kern_height;kern_y++)        {
00380           int img_offset_y=kern_center_y-kern_y;
00381          
00382           sum += 
00383             (CONV_FLOAT)(srcida[img_y+img_offset_y][img_x*PixelSpacing+offset])
00384             * ((*kernel)[kern_y]);
00385   
00386     }
00387         dstida[img_y][img_x*PixelSpacing+offset] = (OutputStorageType)sum;
00388       }
00389     }
00390   }
00391   return 0;
00392 }
00393 
00394 template <class InputStorageType, class OutputStorageType> 
00395 Convolution<InputStorageType,OutputStorageType>::
00396 Convolution()
00397   : FilterNToN<InputStorageType,OutputStorageType>()
00398 {
00399   _fm.SetZero();
00400 }
00401 
00402 template <class InputStorageType, class OutputStorageType> 
00403 Convolution<InputStorageType,OutputStorageType>::
00404 Convolution(const Convolution<InputStorageType, OutputStorageType>& other)
00405   : FilterNToN<InputStorageType, OutputStorageType>(other), _fm(other._fm)
00406 {
00407 }
00408 
00409 template <class InputStorageType, class OutputStorageType> 
00410 Convolution<InputStorageType,OutputStorageType>::~Convolution()
00411 {
00412  _fm.SetZero();
00413 }
00414 
00415 template <class InputStorageType, class OutputStorageType> 
00416 int Convolution<InputStorageType,OutputStorageType>::
00417 Filter(const Image<InputStorageType>& src, Image<OutputStorageType>& dst) 
00418 {
00419   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::Filter\n");
00420 #ifdef BIAS_DEBUG
00421   if (typeid(InputStorageType)!=typeid(OutputStorageType)) {
00422     BIASDOUT(D_CONV_TYPES, "Implicit storage type conversion during filtering."
00423              <<" input=" << PRINTTYPE(InputStorageType)
00424              <<", output=" << PRINTTYPE(OutputStorageType));
00425   } else {
00426     BIASDOUT(D_CONV_TYPES, "filtering same storage type: "
00427              <<PRINTTYPE(InputStorageType));
00428   }
00429 #endif
00430   // check if output image is floating point, if so, do float convolution:
00431   // and also if the input image is float, we must use this, because the
00432   // int mask approximation comes into trouble with float input images
00433   if (CalculationInFloat()) {
00434     BIASDOUT(D_CONV_TYPES,"Convolution is done with floating point numbers.");
00435     return Convolution<InputStorageType,OutputStorageType>::FilterFloat(src,dst);
00436   }
00437   // no float => integer type, do integer arithmetic convolution
00438   BIASDOUT(D_CONV_TYPES, "Convolution is done with integer arithmetic.");
00439   return Convolution<InputStorageType,OutputStorageType>::FilterInt(src,dst);
00440 }
00441 
00442 template <class InputStorageType, class OutputStorageType> 
00443 int Convolution<InputStorageType,OutputStorageType>::
00444 FilterInt(const Image<InputStorageType>& src, Image<OutputStorageType>& dst) 
00445 {
00446   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::FilterInt\n");
00447   BIASDOUT(D_CONV_KERNEL,"Kernel is "<<_fm);
00448 
00449   if(!dst.SamePixelAndChannelCount(src)) {
00450     dst.Release();
00451     dst.Init(src.GetWidth(),src.GetHeight(),src.GetChannelCount(),
00452              src.GetStorageType(),src.IsInterleaved());
00453   }
00454   if(this->GetBorderHandling()==Convolution<InputStorageType,OutputStorageType>::TBH_full) {
00455     BIASERR("BorderHandling TBH_full not implemented");
00456     return -1;
00457   }
00458 
00459   if(_fm.IsSeparable()) {
00460     if(!_tmpInt.SamePixelAndChannelCount(src)) {
00461       _tmpInt.Release();
00462       _tmpInt.Init(src.GetWidth(),src.GetHeight(),src.GetChannelCount(),
00463                    src.GetStorageType(),src.IsInterleaved());
00464     }
00465     ConvIntHori_(src, _tmpInt);
00466     ConvIntVert_(_tmpInt, dst);
00467 #ifdef BIAS_DEBUG
00468     if (this->DebugLevelIsSet(D_WRITE_IMAGES)) {
00469       //ImageIO::Save("tmp_i_separated_after_hori",_tmpInt);
00470       ImageIO::Save("tmp_i_separated_after_hori",_tmpInt);
00471     }
00472 #endif
00473   } else ConvIntMat_(src,dst);
00474 
00475   unsigned int ulx,uly,lrx,lry;
00476   src.GetROICorners(ulx,uly,lrx,lry);
00477   if(this->GetBorderHandling()==Convolution<InputStorageType,OutputStorageType>::TBH_same) {
00478     dst.GetROI()->SetCorners(ulx,uly,lrx,lry);
00479   } else if(this->GetBorderHandling()==Convolution<InputStorageType,OutputStorageType>::TBH_valid) {
00480     int kwidth,kheight;
00481     if(_fm.IsSeparable()) {
00482       kwidth  = _fm.GetSepih()->Size();
00483       kheight = _fm.GetSepiv()->Size();
00484     } else {
00485       kwidth  = _fm.GetKerneli()->GetCols();
00486       kheight = _fm.GetKerneli()->GetRows();
00487     }
00488     dst.SetROICorners(ulx+KERNCENTER(kwidth),uly+KERNCENTER(kheight),
00489                lrx-KERNCENTER(kwidth),lry-KERNCENTER(kheight));
00490   }
00491 #ifdef BIAS_DEBUG
00492     if (this->DebugLevelIsSet(D_WRITE_IMAGES)) {
00493       //ImageIO::Save("tmp_i_final",dst);
00494       ImageIO::Save("tmp_i_final",dst);
00495     }
00496 #endif
00497   return 0;
00498 }
00499 
00500 template <class InputStorageType, class OutputStorageType> 
00501 int Convolution<InputStorageType,OutputStorageType>::
00502 FilterFloat(const Image<InputStorageType>& src, Image<OutputStorageType>& dst) 
00503 {
00504 #ifdef BIAS_DEBUG
00505   if (this->DebugLevelIsSet(D_WRITE_IMAGES)) {
00506     Image<InputStorageType> tmp=src;
00507     //ImageIO::Save("FilterFloat_Input", tmp);
00508     ImageIO::Save("FilterFloat_Input", tmp);
00509   }
00510 #endif
00511   BIASCDOUT(D_FILTERBASE_CALLSTACK,"Convolution::FilterFloat\n");
00512   BIASDOUT(D_CONV_KERNEL,"Kernel is "<<_fm);
00513   if(!dst.SamePixelAndChannelCount(src)) {
00514     dst.Release();
00515     dst.Init(src.GetWidth(),src.GetHeight(),src.GetChannelCount(),
00516              dst.GetStorageType(),src.IsInterleaved());
00517   }
00518   if(this->GetBorderHandling()==Convolution<InputStorageType,OutputStorageType>::TBH_full) {
00519     BIASERR("BorderHandling TBH_full not implemented");
00520     return -1;
00521   }
00522 
00523   if(_fm.IsSeparable()) {
00524     if(!_tmpFloat.SamePixelAndChannelCount(src)) {
00525       _tmpFloat.Release();
00526       _tmpFloat.Init(src.GetWidth(),src.GetHeight(),src.GetChannelCount(),
00527                      ImageBase::ST_float, src.IsInterleaved());
00528     }
00529     ConvFloatHori_(src, _tmpFloat);
00530 #ifdef BIAS_DEBUG
00531     if (this->DebugLevelIsSet(D_WRITE_IMAGES)) {
00532       //ImageIO::Save("FilterFloat_Separated_AfterHorizontal",_tmpFloat);
00533       ImageIO::Save("FilterFloat_Separated_AfterHorizontal",_tmpFloat);
00534     }
00535 #endif
00536     ConvFloatVert_(_tmpFloat, dst);
00537 #ifdef BIAS_DEBUG
00538     if (this->DebugLevelIsSet(D_WRITE_IMAGES)) {
00539       //ImageIO::Save("FilterFloat_Separated_Final", dst);
00540       ImageIO::Save("FilterFloat_Separated_Final", dst);
00541     }
00542 #endif
00543   } else {
00544     ConvFloatMat_(src, dst);
00545 #ifdef BIAS_DEBUG
00546     if (this->DebugLevelIsSet(D_WRITE_IMAGES)) {
00547       //ImageIO::Save("FilterFloat_Final", dst);
00548       ImageIO::Save("FilterFloat_Final", dst);
00549     }
00550 #endif
00551   }
00552 
00553   unsigned int ulx,uly,lrx,lry;
00554   src.GetROICorners(ulx,uly,lrx,lry);
00555   
00556   if(this->GetBorderHandling()==Convolution<InputStorageType,OutputStorageType>::TBH_same) {
00557     dst.GetROI()->SetCorners(ulx,uly,lrx,lry);
00558   } else if(this->GetBorderHandling()==Convolution<InputStorageType,OutputStorageType>::TBH_valid)  {
00559     int kwidth,kheight;
00560     if(_fm.IsSeparable())  {
00561       kwidth=_fm.GetSepfh()->Size();
00562       kheight=_fm.GetSepfv()->Size();
00563     } else {
00564       kwidth=_fm.GetKernelf()->GetCols();
00565       kheight=_fm.GetKernelf()->GetRows();
00566     }
00567     dst.GetROI()->SetCorners(ulx+KERNCENTER(kwidth),uly+KERNCENTER(kheight),
00568                lrx-KERNCENTER(kwidth),lry-KERNCENTER(kheight));
00569   }
00570   return 0;
00571 }
00572 
00573 template <class InputStorageType, class OutputStorageType> 
00574 void Convolution<InputStorageType,OutputStorageType>:: 
00575 PrintKernel() const
00576 {
00577   if (CalculationInFloat()) { // float
00578     cout << "float: ";
00579     if (_fm.IsSeparable()){
00580       cout << "sep horiz: "<< *_fm.GetSepfh()<<"  vert: "<<*_fm.GetSepfv();
00581     } else {
00582       cout << "kernel: "<<*_fm.GetKernelf();
00583     }
00584   } else { // int
00585     cout << "int: ";
00586     if (_fm.IsSeparable()){
00587       cout << "sep horiz: "<< *_fm.GetSepih()<<"  vert: "<<*_fm.GetSepiv();
00588     } else {
00589       cout << "kernel: "<<*_fm.GetKerneli();
00590     }
00591   }
00592   cout << endl;
00593 }
00594 
00595 #define FILTER_INSTANTIATION_CLASS Convolution
00596 #include "Filterinst.hh"
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends