Weights.C

00001 /*!@file ModelNeuron/NeuralLayer.C Class implementation of neural weights*/
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // 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: David Berg <dberg@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ModelNeuron/Weights.C $
00035 
00036 #include "Image/Kernels.H"
00037 #include "Image/MathOps.H"
00038 #include "Image/LowPass.H"
00039 #include "Image/LowPassLpt.H"
00040 
00041 #include "ModelNeuron/Weights.H"
00042 
00043 // ######################################################################
00044 // Copies from filtering routines from Image/ but with type modifications
00045 // ######################################################################
00046 namespace WeightFilter
00047 {
00048   //copies from Convolutions.H but for type double
00049 Image<double>
00050 convolveHmax(const Image<double>& src, const Image<double>& filter)
00051 {
00052   ASSERT(src.initialized());
00053   const int Nx = filter.getWidth(), Ny = filter.getHeight();
00054   ASSERT((Nx & 1) && (Ny & 1));
00055 
00056   const int w = src.getWidth(), h = src.getHeight();
00057 
00058   Image<double> result(w, h, NO_INIT);
00059   Image<double>::const_iterator sptr = src.begin();
00060   Image<double>::iterator dptr = result.beginw();
00061   Image<double>::const_iterator const filt = filter.begin();
00062 
00063   int kkk = Nx * Ny - 1;
00064   int Nx2 = (Nx - 1) / 2, Ny2 = (Ny - 1) / 2;
00065   // very inefficient implementation; one has to be crazy to use non
00066   // separable filters anyway...
00067   for (int j = 0; j < h; ++j)
00068     for (int i = 0; i < w; ++i)
00069       {
00070         double sum = 0.0, sumw = 0.0;
00071         for (int kj = 0; kj < Ny; ++kj)
00072           {
00073             int kjj = kj + j - Ny2;
00074             if (kjj >= 0 && kjj < h)
00075               for (int ki = 0; ki < Nx; ++ki)
00076                 {
00077                   int kii = ki + i - Nx2;
00078                   if (kii >= 0 && kii < w)
00079                     {
00080                       double fil = filt[kkk - ki - Nx*kj];
00081                       double img = sptr[kii + w * kjj];
00082                       sum += img * fil; sumw += img * img;
00083                     }
00084                 }
00085           }
00086         //if (sumw > 0.0F) sum /= fastSqrt(sumw);
00087         if (sumw > 0.0) sum = fabs(sum)/sqrt(sumw);
00088         *dptr++ = sum;
00089       }
00090   return result;
00091 }
00092 
00093 // ######################################################################
00094 Image<double>
00095 optConvolve(const Image<double>& src, const Image<double>& f)
00096 {
00097   ASSERT(src.initialized());
00098 
00099   const int src_w = src.getWidth();
00100   const int src_h = src.getHeight();
00101 
00102   Image<double>::const_iterator filter = f.begin();
00103   const int fil_w = f.getWidth();
00104   const int fil_h = f.getHeight();
00105 
00106   ASSERT((fil_w & 1) && (fil_h & 1));
00107 
00108   Image<double> result(src_w, src_h, NO_INIT);
00109   Image<double>::const_iterator sptr = src.begin();
00110   Image<double>::iterator dptr = result.beginw();
00111 
00112   const int fil_end = fil_w * fil_h - 1;
00113   const int Nx2 = (fil_w - 1) / 2;
00114   const int Ny2 = (fil_h - 1) / 2;
00115 
00116   const int srow_skip = src_w-fil_w;
00117 
00118   for (int dst_y = 0; dst_y < src_h; ++dst_y)
00119     {
00120       // Determine if we're safely inside the image in the y-direction:
00121       const bool y_clean = dst_y >= Ny2 && dst_y <  (src_h - Nx2);
00122 
00123       for (int dst_x = 0; dst_x < src_w; ++dst_x, ++dptr)
00124         {
00125           // Determine if we're safely inside the image in the x-direction:
00126           const bool x_clean = dst_x >= Nx2 && dst_x <  (src_w - Nx2);
00127 
00128           // Here is where we pick whether we can use the optimized inner
00129           // loop (in cases where the filter and image patch overlap
00130           // completely) or whether we must use the inner loop that can
00131           // handle boundary conditions.
00132 
00133           if (x_clean && y_clean)
00134             {
00135               double dst_val = 0.0;
00136 
00137               Image<double>::const_iterator fptr = filter+fil_end;
00138 
00139               Image<double>::const_iterator srow_ptr =
00140                 sptr + src_w*(dst_y-Nx2) + dst_x - Nx2;
00141 
00142               for (int f_y = 0; f_y < fil_h; ++f_y)
00143                 {
00144                   for (int f_x = 0; f_x < fil_w; ++f_x)
00145                     dst_val += (*srow_ptr++) * (*fptr--);
00146 
00147                   srow_ptr += srow_skip;
00148                 }
00149               *dptr = dst_val;
00150               continue;
00151             }
00152           else
00153             {
00154               // OK, we're at an image boundary, so what do we do to make
00155               // up for the missing pixels? The approach here is to
00156               // compute the average value of the non-missing pixels, and
00157               // proceed as if the missing pixels had that value. This
00158               // minimizes the introduction of edge artifacts e.g. when
00159               // convolving with an oriented filter.
00160 
00161               double dst_val = 0.0;
00162               double src_sum = 0.0;
00163               int src_cnt = 0;
00164               double fil_sum_skipped = 0.0;
00165 
00166               for (int f_y = 0; f_y < fil_h; ++f_y)
00167                 {
00168                   const int src_y = f_y + dst_y - Ny2;
00169                   if (src_y >= 0 && src_y < src_h)
00170                     {
00171                       for (int f_x = 0; f_x < fil_w; ++f_x)
00172                         {
00173                           const double fil = filter[fil_end - f_x - fil_w*f_y];
00174 
00175                           const int src_x = f_x + dst_x - Nx2;
00176                           if (src_x >= 0 && src_x < src_w)
00177                             {
00178                               const double src_val = sptr[src_x + src_w * src_y];
00179                               dst_val += src_val * fil;
00180                               src_sum += src_val;
00181                               ++src_cnt;
00182                             }
00183                           else
00184                             {
00185                               fil_sum_skipped += fil;
00186                             }
00187                         }
00188                     }
00189                   else
00190                     {
00191                       for (int f_x = 0; f_x < fil_w; ++f_x)
00192                         fil_sum_skipped += filter[fil_end - f_x - fil_w*f_y];
00193                     }
00194                 }
00195               const double src_avg = src_sum / src_cnt;
00196               *dptr = dst_val + (fil_sum_skipped * src_avg);
00197             }
00198         }
00199     }
00200   return result;
00201 }
00202 
00203   // ######################################################################
00204   static Image<double>
00205   xFilter(const Image<double>& src, const double* hFilt, const int hfs,
00206           ConvolutionBoundaryStrategy boundary)
00207   {
00208     const int w = src.getWidth(), h = src.getHeight();
00209     
00210     if (hfs == 0) return src;  // no filter
00211     Image<double> result(w, h, NO_INIT);
00212     Image<double>::const_iterator sptr = src.begin();
00213     Image<double>::iterator dptr = result.beginw();
00214 
00215     const int hfs2 = (hfs - 1) / 2;
00216 
00217     // flip the filter to accelerate convolution:
00218     double *hFilter = new double[hfs]; double sumh = 0.0;
00219     for (int x = 0; x < hfs; x ++)
00220       { sumh += hFilt[x]; hFilter[hfs-1-x] = hFilt[x]; }
00221 
00222     // *** horizontal pass ***
00223     if (w < hfs)  // special function for very small images
00224       {
00225         switch (boundary)
00226           {
00227           case CONV_BOUNDARY_ZERO:
00228             {
00229               for (int j = 0; j < h; j ++)
00230                 for (int i = 0; i < w; i ++)
00231                   {
00232                     double val = 0;
00233                     for (int k = 0; k < hfs; k ++)
00234                       if (i + k - hfs2 >= 0 && i + k - hfs2 < w)
00235                         {
00236                           val += sptr[k - hfs2] * hFilter[k];
00237                         }
00238                     *dptr++ = val; sptr ++;
00239                   }
00240             }
00241             break;
00242           case CONV_BOUNDARY_CLEAN:
00243             {
00244               for (int j = 0; j < h; j ++)
00245                 for (int i = 0; i < w; i ++)
00246                   {
00247                     double val = 0.0; double sum = 0.0;
00248                     for (int k = 0; k < hfs; k ++)
00249                       if (i + k - hfs2 >= 0 && i + k - hfs2 < w)
00250                         {
00251                           val += sptr[k - hfs2] * hFilter[k];
00252                           sum += hFilter[k];
00253                         }
00254                     *dptr++ = val * sumh / sum; sptr ++;
00255                   }
00256             }
00257             break;
00258           case CONV_BOUNDARY_REPLICATE:
00259             {
00260               for (int j = 0; j < h; j ++)
00261                 for (int i = 0; i < w; i ++)
00262                   {
00263                     double val = 0.0;
00264                     for (int k = 0; k < hfs; k ++)
00265                       if (i + k - hfs2 < 0)
00266                         {
00267                           val += sptr[-i] * hFilter[k];
00268                         }
00269                       else if (i + k - hfs2 >= w)
00270                         {
00271                           val += sptr[w-1-i] * hFilter[k];
00272                         }
00273                       else
00274                         {
00275                           val += sptr[k - hfs2] * hFilter[k];
00276                         }
00277                     *dptr++ = val; sptr ++;
00278                   }
00279             }
00280             break;
00281           default:
00282             LFATAL("invalid convolution boundary strategy %d",
00283                    (int) boundary);
00284           }
00285       }
00286     else  // function for reasonably large images
00287       for (int jj = 0; jj < h; jj ++)
00288         {
00289           // leftmost points:
00290           switch (boundary)
00291             {
00292             case CONV_BOUNDARY_ZERO:
00293               {
00294                 for (int j = hfs2; j > 0; --j)
00295                   {
00296                     double val = 0.0;
00297                     for (int k = j; k < hfs; ++k)
00298                       {
00299                         val += sptr[k - j] * hFilter[k];
00300                       }
00301                     *dptr++ = val;
00302                   }
00303               }
00304               break;
00305             case CONV_BOUNDARY_CLEAN:
00306               {
00307                 for (int j = hfs2; j > 0; --j)
00308                   {
00309                     double val = 0.0; double sum = 0.0;
00310                     for (int k = j; k < hfs; ++k)
00311                       {
00312                         val += sptr[k - j] * hFilter[k];
00313                         sum += hFilter[k];
00314                       }
00315                     *dptr++ = val * sumh / sum;
00316                   }
00317               }
00318               break;
00319             case CONV_BOUNDARY_REPLICATE:
00320               {
00321                 for (int j = hfs2; j > 0; --j)
00322                   {
00323                     double val = 0.0;
00324                     for (int k = 0; k < j; ++k)
00325                       {
00326                         val += sptr[0] * hFilter[k];
00327                       }
00328                     for (int k = j; k < hfs; ++k)
00329                       {
00330                         val += sptr[k - j] * hFilter[k];
00331                       }
00332                     *dptr++ = val;
00333                   }
00334               }
00335               break;
00336             default:
00337               LFATAL("invalid convolution boundary strategy %d",
00338                      (int) boundary);
00339             }
00340           // bulk (far from the borders):
00341           for (int i = 0; i < w - hfs + 1; i ++)
00342             {
00343               double val = 0.0;
00344               for (int k = 0; k < hfs; k ++) val += sptr[k] * hFilter[k];
00345               *dptr++ = val; sptr++;
00346             }
00347           // rightmost points:
00348           switch (boundary)
00349             {
00350             case CONV_BOUNDARY_ZERO:
00351               {
00352                 for (int j = hfs - 1; j > hfs2; --j)
00353                   {
00354                     double val = 0.0;
00355                     for (int k = 0; k < j; ++k)
00356                       {
00357                         val += sptr[k] * hFilter[k];
00358                       }
00359                     *dptr++ = val;
00360                     sptr++;
00361                   }
00362               }
00363               break;
00364             case CONV_BOUNDARY_CLEAN:
00365               {
00366                 for (int j = hfs - 1; j > hfs2; --j)
00367                   {
00368                     double val = 0.0; double sum = 0.0;
00369                     for (int k = 0; k < j; ++k)
00370                       {
00371                         val += sptr[k] * hFilter[k];
00372                         sum += hFilter[k];
00373                       }
00374                     *dptr++ = val * sumh / sum;
00375                     sptr++;
00376                   }
00377               }
00378               break;
00379             case CONV_BOUNDARY_REPLICATE:
00380               {
00381                 for (int j = hfs - 1; j > hfs2; --j)
00382                   {
00383                     double val = 0.0;
00384                     for (int k = 0; k < j; ++k)
00385                       {
00386                         val += sptr[k] * hFilter[k];
00387                       }
00388                     for (int k = j; k < hfs; ++k)
00389                       {
00390                         val += sptr[j-1] * hFilter[k];
00391                       }
00392                     *dptr++ = val;
00393                     sptr++;
00394                   }
00395               }
00396               break;
00397             default:
00398               LFATAL("invalid convolution boundary strategy %d",
00399                      (int) boundary);
00400             }
00401           sptr += hfs2;  // sptr back to same as dptr (start of next line)
00402         }
00403     delete [] hFilter;
00404     return result;
00405   }
00406 
00407   // ######################################################################
00408   static Image<double>
00409   yFilter(const Image<double>& src, const double* vFilt, const int vfs,
00410           ConvolutionBoundaryStrategy boundary)
00411   {
00412     const int w = src.getWidth(), h = src.getHeight();
00413 
00414     if (vfs == 0) return src;  // no filter
00415     Image<double> result(w, h, NO_INIT);
00416     Image<double>::const_iterator sptr = src.begin();
00417     Image<double>::iterator dptr = result.beginw();
00418 
00419     const int vfs2 = (vfs - 1) / 2;
00420 
00421     // flip the filter to accelerate convolution:
00422     double *vFilter = new double[vfs]; double sumv = 0.0;
00423     for (int x = 0; x < vfs; x ++)
00424       { sumv += vFilt[x]; vFilter[vfs-1-x] = vFilt[x]; }
00425 
00426     int ww[vfs];
00427     for (int i = 0; i < vfs; i ++) ww[i] = w * i; // speedup precompute
00428 
00429     if (h < vfs)  // special function for very small images
00430       {
00431         switch (boundary)
00432           {
00433           case CONV_BOUNDARY_ZERO:
00434             {
00435               for (int j = 0; j < h; j ++)
00436                 for (int i = 0; i < w; i ++)
00437                   {
00438                     double val = 0.0;
00439                     for (int k = 0; k < vfs; k ++)
00440                       if (j + k - vfs2 >= 0 && j + k - vfs2 < h)
00441                         {
00442                           val += sptr[w * (k - vfs2)] * vFilter[k];
00443                         }
00444                     *dptr++ = val; sptr ++;
00445                   }
00446             }
00447             break;
00448           case CONV_BOUNDARY_CLEAN:
00449             {
00450               for (int j = 0; j < h; j ++)
00451                 for (int i = 0; i < w; i ++)
00452                   {
00453                     double val = 0.0; double sum = 0.0;
00454                     for (int k = 0; k < vfs; k ++)
00455                       if (j + k - vfs2 >= 0 && j + k - vfs2 < h)
00456                         {
00457                           val += sptr[w * (k - vfs2)] * vFilter[k];
00458                           sum += vFilter[k];
00459                         }
00460                     *dptr++ = val * sumv / sum; sptr ++;
00461                   }
00462             }
00463             break;
00464           case CONV_BOUNDARY_REPLICATE:
00465             {
00466               for (int j = 0; j < h; j ++)
00467                 for (int i = 0; i < w; i ++)
00468                   {
00469                     double val = 0.0;
00470                     for (int k = 0; k < vfs; k ++)
00471                       if (j + k - vfs2 < 0)
00472                         {
00473                           val += sptr[w * (-j)] * vFilter[k];
00474                         }
00475                       else if (j + k - vfs2 >= h)
00476                         {
00477                           val += sptr[w * (h-1-j)] * vFilter[k];
00478                         }
00479                       else
00480                         {
00481                           val += sptr[w * (k - vfs2)] * vFilter[k];
00482                         }
00483                     *dptr++ = val; sptr ++;
00484                   }
00485             }
00486             break;
00487           default:
00488             LFATAL("invalid convolution boundary strategy %d",
00489                    (int) boundary);
00490           }
00491       }
00492     else  // function for reasonably large images
00493       {
00494         // top points:
00495         switch (boundary)
00496           {
00497           case CONV_BOUNDARY_ZERO:
00498             {
00499               for (int j = vfs2; j > 0; --j)
00500                 {
00501                   for (int i = 0; i < w; ++i)  // scan all points of given horiz
00502                     {
00503                       double val = 0.0;
00504                       for (int k = j; k < vfs; ++k)
00505                         {
00506                           val += sptr[ww[k - j]] * vFilter[k];
00507                         }
00508                       *dptr++ = val;
00509                       sptr++;
00510                     }
00511                   sptr -= w;   // back to top-left corner
00512                 }
00513             }
00514             break;
00515           case CONV_BOUNDARY_CLEAN:
00516             {
00517               for (int j = vfs2; j > 0; --j)
00518                 {
00519                   for (int i = 0; i < w; ++i)  // scan all points of given horiz
00520                     {
00521                       double val = 0.0; double sum = 0.0;
00522                       for (int k = j; k < vfs; ++k)
00523                         {
00524                           val += sptr[ww[k - j]] * vFilter[k];
00525                           sum += vFilter[k];
00526                         }
00527                       *dptr++ = val * sumv / sum;
00528                       sptr++;
00529                     }
00530                   sptr -= w;   // back to top-left corner
00531                 }
00532             }
00533             break;
00534           case CONV_BOUNDARY_REPLICATE:
00535             {
00536               for (int j = vfs2; j > 0; --j)
00537                 {
00538                   for (int i = 0; i < w; ++i)  // scan all points of given horiz
00539                     {
00540                       double val = 0.0;
00541                       for (int k = 0; k < j; ++k)
00542                         {
00543                           val += sptr[ww[0]] * vFilter[k];
00544                         }
00545                       for (int k = j; k < vfs; ++k)
00546                         {
00547                           val += sptr[ww[k - j]] * vFilter[k];
00548                         }
00549                       *dptr++ = val;
00550                       sptr++;
00551                     }
00552                   sptr -= w;   // back to top-left corner
00553                 }
00554             }
00555             break;
00556           default:
00557             LFATAL("invalid convolution boundary strategy %d",
00558                    (int) boundary);
00559           }
00560         // bulk (far from edges):
00561         for (int j = 0; j < h - vfs + 1; j ++)
00562           for (int i = 0; i < w; i ++)
00563             {
00564               double val = 0.0;
00565               for (int k = 0; k < vfs; k ++) val += sptr[ww[k]] * vFilter[k];
00566               *dptr++ = val; sptr ++;
00567             }
00568         // bottommost points:
00569         switch (boundary)
00570           {
00571           case CONV_BOUNDARY_ZERO:
00572             {
00573               for (int j = vfs - 1; j > vfs2; --j)
00574                 for (int i = 0; i < w; ++i)
00575                   {
00576                     double val = 0.0;
00577                     for (int k = 0; k < j; ++k)
00578                       {
00579                         val += sptr[ww[k]] * vFilter[k];
00580                       }
00581                     *dptr++ = val;
00582                     sptr ++;
00583                   }
00584             }
00585             break;
00586           case CONV_BOUNDARY_CLEAN:
00587             {
00588               for (int j = vfs - 1; j > vfs2; --j)
00589                 for (int i = 0; i < w; ++i)
00590                   {
00591                     double val = 0.0; double sum = 0.0;
00592                     for (int k = 0; k < j; ++k)
00593                       {
00594                         val += sptr[ww[k]] * vFilter[k];
00595                         sum += vFilter[k];
00596                       }
00597                     *dptr++ = val * sumv / sum;
00598                     sptr ++;
00599                   }
00600             }
00601             break;
00602           case CONV_BOUNDARY_REPLICATE:
00603             {
00604               for (int j = vfs - 1; j > vfs2; --j)
00605                 for (int i = 0; i < w; ++i)
00606                   {
00607                     double val = 0.0;
00608                     for (int k = 0; k < j; ++k)
00609                       {
00610                         val += sptr[ww[k]] * vFilter[k];
00611                       }
00612                     for (int k = j; k < vfs; ++k)
00613                       {
00614                         val += sptr[ww[j-1]] * vFilter[k];
00615                       }
00616                     *dptr++ = val;
00617                     sptr ++;
00618                   }
00619             }
00620             break;
00621           default:
00622             LFATAL("invalid convolution boundary strategy %d",
00623                    (int) boundary);
00624           }
00625       }
00626     delete [] vFilter;
00627     return result;
00628   }
00629 
00630   // ######################################################################
00631   Image<double>
00632   sepFilter(const Image<double>& src, const Image<double>& hFilter,
00633             const Image<double>& vFilter,
00634             ConvolutionBoundaryStrategy boundary)
00635   {
00636     ASSERT(hFilter.is1D() || hFilter.getSize() == 0);
00637     ASSERT(vFilter.is1D() || vFilter.getSize() == 0);
00638 
00639     Image<double> result = src;
00640     const int hfs = hFilter.getSize();
00641     const int vfs = vFilter.getSize();
00642     if (hfs > 0) result = xFilter(result, hFilter.getArrayPtr(), 
00643                                   hfs, boundary);
00644     if (vfs > 0) result = yFilter(result, vFilter.getArrayPtr(), 
00645                                   vfs, boundary);
00646     
00647     return result;
00648   }
00649 }//end namespace WeightFilter
00650 
00651 // ######################################################################
00652 // WeightsAll implementation
00653 // ######################################################################
00654 WeightsAll::WeightsAll() : WeightsDerived<WeightsAll>(), itsW(0.0) { };
00655 
00656 // ######################################################################
00657 WeightsAll::WeightsAll(const double& weight) : WeightsDerived<WeightsAll>(), 
00658                                                itsW(weight) { itsInit = true; }
00659 
00660 // ######################################################################
00661 Image<double> WeightsAll::compute(const Image<double>& in)
00662 {
00663   double s = sum(in);
00664   s *= itsW;
00665   Image<double> out(in.getDims(), NO_INIT);
00666   out.clear(s);
00667   return out;
00668 }
00669 
00670 // ######################################################################
00671 // WeightsUniform implementation
00672 // ######################################################################
00673 WeightsUniform::WeightsUniform() : WeightsDerived<WeightsUniform>(), itsW(0.0) { };
00674 
00675 // ######################################################################
00676 WeightsUniform::WeightsUniform(const double& weight) : WeightsDerived<WeightsUniform>(), itsW(weight) 
00677 { itsInit = true; }
00678 
00679 // ######################################################################
00680 Image<double> WeightsUniform::compute(const Image<double>& in)
00681 {
00682   Image<double> out = in * itsW;
00683   return out;
00684 }
00685 
00686 // ######################################################################
00687 // WeightsBinomial implementation
00688 // ######################################################################
00689 WeightsBinomial::WeightsBinomial() : WeightsDerived<WeightsBinomial>(),
00690                                      itsTaps(0), itsIter(0), subCenter(false), 
00691                                      itsCenter(0.0), itsWeight(0.0), 
00692                                      itsBp(NONE), itsSetup(false) { };
00693 
00694 // ######################################################################
00695 WeightsBinomial::WeightsBinomial(const double& std, const double& weight, 
00696                                  const bool doSubCenter, const BorderPolicy bp,
00697                                  const uint taps) :
00698   itsTaps(taps), itsIter(0), subCenter(doSubCenter), itsCenter(0.0), 
00699   itsWeight(weight), itsBp(bp), itsSetup(false)
00700 {
00701   //get required iterations
00702   itsIter = uint((std*std) / (double(taps - 1)/4.0));
00703   itsInit = true;
00704 }
00705 
00706 // ######################################################################
00707 Image<double> WeightsBinomial::compute(const Image<double>& in)
00708 {
00709   Image<double> out = in;
00710   if (!itsSetup) 
00711     {
00712       Image<double> impulse(in.getDims(), ZEROS);
00713       uint cx = (uint) (in.getWidth() / 2) - 1;
00714       uint cy = (uint) (in.getHeight() / 2) - 1;
00715       impulse.setVal(cx, cy, 1.0);
00716       impulse = filterBinomial(impulse,itsIter, itsTaps, itsBp);
00717       itsCenter  = 1.0 / impulse.getVal(cx,cy);
00718       if (!subCenter)
00719         itsCenter*= itsWeight;
00720       
00721       itsSetup = true;
00722     }
00723 
00724   //do the filtering
00725   out = filterBinomial(out, itsIter, itsTaps, itsBp);
00726 
00727   //subtract energy from self excitation, then scale
00728   if (subCenter)  
00729     {
00730       out *= itsCenter;
00731       out -= in;
00732       out *= itsWeight;
00733     }
00734   else
00735     out *= itsCenter;
00736   
00737   return out;
00738 }
00739 
00740 // ######################################################################
00741 // WeightsCS implementation
00742 // ######################################################################
00743 WeightsCS::WeightsCS() :  WeightsDerived<WeightsCS>(), itsW(0.0, 0.0, false, NONE, 0), 
00744                           itsInh(0.0) { };
00745 
00746 // ######################################################################
00747 WeightsCS::WeightsCS(const double& estd, const double& eweight, 
00748                      const double& inhibit, const bool doSubCenter, 
00749                      const BorderPolicy bp, const uint taps) :
00750   WeightsDerived<WeightsCS>(), itsW(estd, eweight, doSubCenter, bp, taps), itsInh(inhibit)
00751 { itsInit = true; }
00752 
00753 // ######################################################################
00754 Image<double> WeightsCS::compute(const Image<double>& in)
00755 {
00756   Image<double> e = itsW.compute(in);
00757   const double s = sum(in) * itsInh;
00758   e -= s;
00759   return e;
00760 }    
00761 
00762 // ######################################################################
00763 // WeightsDoG implementation
00764 // ######################################################################
00765 WeightsDoG::WeightsDoG() : WeightsDerived<WeightsDoG>(), itsE(0.0, 0.0, false, NONE, 0), 
00766                            itsI(0.0, 0.0, false, NONE, 0) { };
00767 
00768 // ######################################################################
00769 WeightsDoG::WeightsDoG(const double& estd, const double& istd, 
00770                        const double& ew, const double& iw, 
00771                        const bool subCenter, const BorderPolicy bp,
00772                        const uint taps) : WeightsDerived<WeightsDoG>(),
00773                                           itsE(estd, ew, subCenter, bp, taps), 
00774                                           itsI(istd, iw, subCenter, bp, taps)
00775 {  
00776   itsInit = true;
00777 }
00778 
00779 // ######################################################################
00780 Image<double> WeightsDoG::compute(const Image<double>& in)
00781 {
00782   Image<double> e = itsE.compute(in);
00783   const Image<double> i = itsI.compute(in);
00784   e -= i;
00785   return e;
00786 }    
00787 
00788 // ######################################################################
00789 // Weights1D implementation
00790 // ######################################################################
00791 Weights1D::Weights1D() : WeightsDerived<Weights1D>(), subCenter(false), itsCenter(0.0), 
00792                          itsStrat(CONV_BOUNDARY_CLEAN), itsX(), itsY(), 
00793                          itsSetup(false) { }
00794 
00795 // ######################################################################
00796 Weights1D::Weights1D(const bool doSubCenter, 
00797                      const ConvolutionBoundaryStrategy strat) :
00798   WeightsDerived<Weights1D>(),
00799   subCenter(doSubCenter), itsCenter(0.0), itsStrat(strat), 
00800   itsX(), itsY(), itsSetup(false) { }
00801 
00802 // ######################################################################
00803 void Weights1D::addWeight(const Image<double>& wxy)
00804 {
00805   itsX.push_back(wxy);
00806   itsY.push_back(wxy);
00807   itsInit = true;
00808 }
00809 
00810 // ######################################################################
00811 void Weights1D::addWeight(const Image<double>& wx, const Image<double>& wy)
00812 {
00813     itsX.push_back(wx);
00814     itsY.push_back(wy);  
00815     itsInit = true;
00816 }
00817 
00818 // ######################################################################
00819 void Weights1D::clear()
00820 {
00821   itsX.clear();
00822   itsY.clear();
00823   itsCenter = 0.0;
00824   itsSetup = false;
00825 }
00826 
00827 // ######################################################################
00828 Image<double> Weights1D::compute(const Image<double>& in)
00829 {
00830 
00831   if (~itsSetup && subCenter)
00832     {
00833       Image<double> impulse(in.getDims(), ZEROS);
00834       uint cx = (uint) (in.getWidth() / 2) - 1;
00835       uint cy = (uint) (in.getHeight() / 2) - 1;
00836       impulse.setVal(cx, cy, 1.0);
00837       //filter to get response at center
00838       for (uint jj = 0; jj < itsX.size(); ++jj)
00839         impulse = WeightFilter::sepFilter(impulse,itsX[jj],itsY[jj],itsStrat);
00840       itsCenter = impulse.getVal(cx,cy);
00841       itsSetup = true;
00842     }
00843   
00844   Image<double> out = in;  
00845   //apply the filter bank 
00846   for (uint jj = 0; jj < itsX.size(); ++jj)
00847     out = WeightFilter::sepFilter(out, itsX[jj], itsY[jj], itsStrat);
00848   
00849   //subtract energy from self excitation 
00850   if (subCenter)
00851     out = out - (in * itsCenter); 
00852   
00853   return out;      
00854 }
00855 
00856 // ######################################################################
00857 // Weights2D implementation
00858 // ######################################################################
00859 Weights2D::Weights2D(const ConvolutionBoundaryStrategy strat) 
00860   : WeightsDerived<Weights2D>(), itsStrat(strat), itsW()
00861 { 
00862 }
00863 
00864 // ######################################################################
00865 void Weights2D::addWeight(const Image<double>& w)
00866 {
00867   if (w.is1D())
00868     LFATAL("Filter needs to be 2D for this Weights type");
00869   else
00870     itsW.push_back(w);
00871   itsInit = true;
00872 }
00873 
00874 // ######################################################################
00875 void Weights2D::clear()
00876 {
00877   itsW.clear();
00878   itsInit = false;
00879 }
00880 
00881 // ######################################################################
00882 Image<double> Weights2D::compute(const Image<double>& in)
00883 {
00884   Image<double> out = in;
00885   //apply the filter bank itsIter iterations
00886   if (itsStrat == CONV_BOUNDARY_CLEAN)
00887     for (uint jj = 0; jj < itsW.size(); ++jj)
00888       out = WeightFilter::convolveHmax(out, itsW[jj]); 
00889   else
00890     for (uint jj = 0; jj < itsW.size(); ++jj)
00891       out = WeightFilter::optConvolve(out, itsW[jj]);
00892   
00893   return out;      
00894 }
00895 
00896 // ######################################################################
00897 // WeightsMask implementation
00898 // ######################################################################}
00899 WeightsMask::WeightsMask() : WeightsDerived<WeightsMask>()
00900 { 
00901 }
00902 
00903 // ######################################################################
00904 void WeightsMask::addWeight(const Image<double>& w)
00905 {
00906   itsW.push_back(w);
00907   itsInit = true;
00908 }
00909 
00910 // ######################################################################
00911 void WeightsMask::clear()
00912 {
00913   itsW.clear();
00914   itsInit = false;
00915 }
00916 
00917 // ######################################################################}
00918 Image<double> WeightsMask::compute(const Image<double>& in)
00919 {
00920   ASSERT((itsW.size() == in.size()) && in.size() > 0);
00921 
00922   Image<double> out(in.getDims(), ZEROS);
00923   std::vector<Image<double> >::const_iterator iter(itsW.begin()), end(itsW.end());
00924   Image<double>::iterator outiter(out.beginw());
00925   
00926   while (iter != end)
00927     {
00928       ASSERT(iter->size() == in.size());
00929       (*outiter++) = sum(in * (*iter++));
00930     }
00931 
00932 return Image<double>(in.getDims(),ZEROS); 
00933 }
00934 
00935 // ######################################################################
00936 // helper implementation
00937 // ######################################################################
00938 Image<double> filterBinomial(const Image<double>& in, const uint iter, 
00939                              const uint taps, const BorderPolicy bp)
00940 {
00941   Image<double> out = in;
00942   if (bp == NONE)
00943     switch(taps)
00944       {
00945       case 3:
00946         for (uint i = 0; i < iter; ++i)
00947           out = lowPass3(out);
00948         break;
00949       case 5:
00950         for (uint i = 0; i < iter; ++i)
00951           out = lowPass5(out);
00952         break;
00953       default:
00954         {
00955           Image<double> k = binomialKernel(taps);
00956           for (uint i = 0; i < iter; ++i)
00957             out = WeightFilter::sepFilter(out, k, k, CONV_BOUNDARY_CLEAN);
00958         }
00959       }
00960   else
00961     for (uint i = 0; i < iter; ++i)
00962       out = lowPassLpt(out, taps, bp);    
00963   
00964   return out;
00965 }
00966 
00967 // ######################################################################
00968 template <class W>
00969 void printImpulse(const uint w, const uint h, W& weights)
00970 {
00971   Image<double> in(w,h,ZEROS);
00972   int cx = in.getWidth() / 2 -1;
00973   int cy = in.getHeight() / 2 -1;
00974   in.setVal(cx,cy,1.0);
00975   in = weights.compute(in);
00976   printImage(in);
00977 }
00978 
00979 // ######################################################################
00980 void printImage(const Image<double>& in)
00981 {
00982   int cx = in.getWidth() / 2 - 1;
00983 
00984   Image<double>::const_iterator iter(in.begin() + cx);
00985   for (int i = 0; i < in.getHeight(); ++i)
00986     {
00987       LINFO("%3.5f", *iter);
00988       iter += in.getWidth();
00989     }
00990 }
00991 
00992 template 
00993 void printImpulse(const uint w, const uint h, WeightsUniform& weights);
00994 template 
00995 void printImpulse(const uint w, const uint h, WeightsBinomial& weights);
00996 template 
00997 void printImpulse(const uint w, const uint h, WeightsCS& weights);
00998 template 
00999 void printImpulse(const uint w, const uint h, WeightsDoG& weights);
01000 template 
01001 void printImpulse(const uint w, const uint h, Weights1D& weights);
01002 template 
01003 void printImpulse(const uint w, const uint h, Weights2D& weights);
01004 template 
01005 void printImpulse(const uint w, const uint h, WeightsMask& weights);
01006 // ######################################################################
01007 /* So things look consistent in everyone's emacs... */
01008 /* Local Variables: */
01009 /* indent-tabs-mode: nil */
01010 /* End: */
Generated on Sun May 8 08:41:01 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3