ImageSetOps.C

Go to the documentation of this file.
00001 /*!@file Image/ImageSetOps.C Free functions operating on sets of images */
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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/ImageSetOps.C $
00035 // $Id: ImageSetOps.C 14633 2011-03-23 22:55:54Z dberg $
00036 //
00037 
00038 #include "Image/ImageSetOps.H"
00039 
00040 #include "Image/DrawOps.H"
00041 #include "Image/FilterOps.H"
00042 #include "Image/Image.H"
00043 #include "Image/ImageSet.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/Range.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Util/Assert.H"
00048 #include "rutz/compat_cmath.h"
00049 
00050 // ######################################################################
00051 // ######################################################################
00052 // ##### ImageSet processing functions
00053 // ######################################################################
00054 // ######################################################################
00055 
00056 // ######################################################################
00057 template <class T>
00058 bool isHomogeneous(const ImageSet<T>& x)
00059 {
00060   if (x.size() == 0) return true;
00061 
00062   const Dims d = x[0].getDims();
00063 
00064   for (uint i = 1; i < x.size(); ++i)
00065     if (d != x[i].getDims())
00066       return false;
00067 
00068   return true;
00069 }
00070 
00071 // ######################################################################
00072 template <class T>
00073 bool isDyadic(const ImageSet<T>& pyr)
00074 {
00075   if (pyr.size() == 0) return false;
00076 
00077   for (uint i = 1; i < pyr.size(); ++i)
00078     {
00079       const Dims prevdims = pyr[i-1].getDims();
00080       const Dims curdims = pyr[i].getDims();
00081 
00082       // make sure we don't go below 1
00083       const int pw2 = std::max(prevdims.w()/2,1);
00084       const int ph2 = std::max(prevdims.h()/2,1);
00085 
00086       if (curdims.w() != pw2) return false;
00087       if (curdims.h() != ph2) return false;
00088     }
00089 
00090   return true;
00091 }
00092 
00093 // ######################################################################
00094 template <class T>
00095 Image<T> sum(const ImageSet<T>& x)
00096 {
00097   ASSERT(isHomogeneous(x));
00098 
00099   Image<T> result(x[0].getDims(), ZEROS);
00100 
00101   for (uint a = 0; a < x.size(); ++a)
00102     {
00103       result += x[a];
00104     }
00105 
00106   return result;
00107 }
00108 
00109 // ######################################################################
00110 template <class T>
00111 Image<T> mean(const ImageSet<T>& x)
00112 {
00113   Image<T> result = sum(x);
00114   result /= x.size();
00115   return result;
00116 }
00117 
00118 // ######################################################################
00119 template <class T>
00120 Range<T> rangeOf(const ImageSet<T>& x)
00121 {
00122   Range<T> result;
00123 
00124   for (uint i = 0; i < x.size(); ++i)
00125     {
00126       result.merge(rangeOf(x[i]));
00127     }
00128 
00129   return result;
00130 }
00131 
00132 // ######################################################################
00133 template <class T>
00134 ImageSet<T> takeSlice(const ImageSet<T>* sets, uint nsets, uint level)
00135 {
00136   ImageSet<T> result(nsets);
00137 
00138   for (uint i = 0; i < nsets; ++i)
00139     {
00140       result[i] = sets[i][level];
00141     }
00142 
00143   return result;
00144 }
00145 
00146 // ######################################################################
00147 template <class T>
00148 Image<T> makeImageArray(const ImageSet<T>& x,
00149                         int Nx, int grid_width, T grid_color,
00150                         int destX, int destY)
00151 {
00152   if (Nx < 0)
00153     {
00154       Nx = int(ceil(sqrt(x.size())));
00155     }
00156 
00157   Image<T> result;
00158 
00159   // One way or the other, all images must be reshaped to the same size
00160   // for concatArray(). So, if the user didn't request any specific
00161   // shaping (by setting destX or destY to -1), then we specify to
00162   // reshape each image to the size of the largest level.
00163   if (destX <= 0 || destY <= 0)
00164     {
00165       destX = x[0].getWidth();
00166       destY = x[0].getHeight();
00167     }
00168 
00169   if (isDyadic(x) && destX == x[0].getWidth() && destY == x[0].getHeight())
00170     {
00171       // With a dyadic pyramid, we get more appropriate upscaling by just
00172       // duplicating pixels.
00173       ImageSet<T> y = x;
00174       for (unsigned int i = 1; i < y.size(); ++i)
00175         y[i] = zoomXY(y[i], 1<<i, 1<<i);
00176 
00177       result = concatArray(&y[0], y.size(), Nx);
00178     }
00179   else
00180     {
00181       result = concatArray(&x[0], x.size(), Nx, destX, destY);
00182     }
00183 
00184   if (grid_width > 0)
00185     drawGrid(result, destX, destY, grid_width, grid_width, grid_color);
00186 
00187   return result;
00188 }
00189 
00190 // ######################################################################
00191 template <class T>
00192 ImageSet<T> reduce(const ImageSet<T>& x, int octaves)
00193 {
00194   ImageSet<T> result(x);
00195 
00196   for (int n = 0; n < octaves; ++n)
00197     {
00198       for (uint i = 0; i < x.size(); ++i)
00199         {
00200           result[i] = lowPass3(result[i]);
00201           result[i] = decXY(result[i]);
00202         }
00203     }
00204 
00205   return result;
00206 }
00207 
00208 // ######################################################################
00209 template <class T>
00210 ImageSet<T> rescale(const ImageSet<T>& x, const Dims& dims)
00211 {
00212   ImageSet<T> result(x.size());
00213 
00214   for (uint i = 0; i < x.size(); ++i)
00215     {
00216       result[i] = rescale(x[i], dims);
00217     }
00218 
00219   return result;
00220 }
00221 
00222 // ######################################################################
00223 ImageSet<float> orientedFilterSet(const Image<float>& lowPassedInput,
00224                                   float period,
00225                                   const float* angles, const uint numAngles)
00226 {
00227   ImageSet<float> result(numAngles);
00228 
00229   LINFO("oriented laplacian period is %f", period);
00230 
00231   const float k = (2.0f * M_PI) / period;
00232 
00233   for (uint i = 0; i < numAngles; ++i)
00234     result[i] = orientedFilter(lowPassedInput, k, angles[i]);
00235 
00236   return result;
00237 }
00238 
00239 // ######################################################################
00240 void splitPosNeg(const ImageSet<float>& x, ImageSet<float>& pos, ImageSet<float>& neg)
00241 {
00242   pos = ImageSet<float>(x.size());
00243   neg = ImageSet<float>(x.size());
00244   for (uint i = 0; i < x.size(); ++i)
00245     splitPosNeg(x[i], pos[i], neg[i]);
00246 }
00247 
00248 // ######################################################################
00249 // ######################################################################
00250 // ##### ImageSet mathematical operators
00251 // ######################################################################
00252 // ######################################################################
00253 
00254 // ######################################################################
00255 template <class T>
00256 ImageSet<T>& operator-=(ImageSet<T>& x, const Image<T>& y)
00257 {
00258   ASSERT(isHomogeneous(x));
00259 
00260   for (uint i = 0; i < x.size(); ++i)
00261     x[i] -= y;
00262 
00263   return x;
00264 }
00265 
00266 // ######################################################################
00267 template <class T>
00268 ImageSet<T>& operator+=(ImageSet<T>& x, const Image<T>& y)
00269 {
00270   ASSERT(isHomogeneous(x));
00271 
00272   for (uint i = 0; i < x.size(); ++i)
00273     x[i] += y;
00274 
00275   return x;
00276 }
00277 
00278 // ######################################################################
00279 template <class T>
00280 ImageSet<T>& operator*=(ImageSet<T>& x, const Image<T>& y)
00281 {
00282   ASSERT(isHomogeneous(x));
00283 
00284   for (uint i = 0; i < x.size(); ++i)
00285     x[i] *= y;
00286 
00287   return x;
00288 }
00289 
00290 // ######################################################################
00291 template <class T>
00292 ImageSet<T>& operator/=(ImageSet<T>& x, const Image<T>& y)
00293 {
00294   ASSERT(isHomogeneous(x));
00295 
00296   for (uint i = 0; i < x.size(); ++i)
00297     x[i] /= y;
00298 
00299   return x;
00300 }
00301 
00302 // ######################################################################
00303 template <class T>
00304 ImageSet<T>& operator-=(ImageSet<T>& x, const T& v)
00305 {
00306   for (uint i = 0; i < x.size(); ++i)
00307     x[i] -= v;
00308 
00309   return x;
00310 }
00311 
00312 // ######################################################################
00313 template <class T>
00314 ImageSet<T>& operator+=(ImageSet<T>& x, const T& v)
00315 {
00316   for (uint i = 0; i < x.size(); ++i)
00317     x[i] += v;
00318 
00319   return x;
00320 }
00321 
00322 // ######################################################################
00323 template <class T>
00324 ImageSet<T>& operator*=(ImageSet<T>& x, const T& v)
00325 {
00326   for (uint i = 0; i < x.size(); ++i)
00327     x[i] *= v;
00328 
00329   return x;
00330 }
00331 
00332 // ######################################################################
00333 template <class T>
00334 ImageSet<T>& operator/=(ImageSet<T>& x, const T& v)
00335 {
00336   for (uint i = 0; i < x.size(); ++i)
00337     x[i] /= v;
00338 
00339   return x;
00340 }
00341 
00342 // ######################################################################
00343 template <class T>
00344 ImageSet<T> operator-(ImageSet<T>& x, const T& v)
00345 {
00346   ImageSet<T> res = x;
00347   return (res -= v);
00348 }
00349 
00350 // ######################################################################
00351 template <class T>
00352 ImageSet<T> operator+(ImageSet<T>& x, const T& v)
00353 {
00354   ImageSet<T> res = x;
00355   return (res += v);
00356 }
00357 
00358 // ######################################################################
00359 template <class T>
00360 ImageSet<T> operator*(ImageSet<T>& x, const T& v)
00361 {
00362   ImageSet<T> res = x;
00363   return (res *= v);
00364 }
00365 
00366 // ######################################################################
00367 template <class T>
00368 ImageSet<T> operator/(ImageSet<T>& x, const T& v)
00369 {
00370   ImageSet<T> res = x;
00371   return (res /= v);
00372 }
00373 
00374 // ######################################################################
00375 template <class T>
00376 ImageSet<T>& operator-=(ImageSet<T>& x, const ImageSet<T>& y)
00377 {
00378   ASSERT(x.size() == y.size());
00379 
00380   for (uint i = 0; i < x.size(); ++i)
00381     x[i] -= y[i];
00382 
00383   return x;
00384 }
00385 
00386 // ######################################################################
00387 template <class T>
00388 ImageSet<T>& operator+=(ImageSet<T>& x, const ImageSet<T>& y)
00389 {
00390   ASSERT(x.size() == y.size());
00391 
00392   for (uint i = 0; i < x.size(); ++i)
00393     x[i] += y[i];
00394 
00395   return x;
00396 }
00397 
00398 // ######################################################################
00399 template <class T>
00400 ImageSet<T>& operator*=(ImageSet<T>& x, const ImageSet<T>& y)
00401 {
00402   ASSERT(x.size() == y.size());
00403 
00404   for (uint i = 0; i < x.size(); ++i)
00405     x[i] *= y[i];
00406 
00407   return x;
00408 }
00409 
00410 // ######################################################################
00411 template <class T>
00412 ImageSet<T>& operator/=(ImageSet<T>& x, const ImageSet<T>& y)
00413 {
00414   ASSERT(x.size() == y.size());
00415 
00416   for (uint i = 0; i < x.size(); ++i)
00417     x[i] /= y[i];
00418 
00419   return x;
00420 }
00421 
00422 // ######################################################################
00423 template <class T>
00424 ImageSet<T> clampedDiff(const ImageSet<T>& b, const ImageSet<T>& c)
00425 {
00426   ASSERT(b.size() == c.size());
00427 
00428   ImageSet<T> res(b.size());
00429   for (uint i = 0; i < b.size(); ++i)
00430     res[i] = clampedDiff(b[i],c[i]);
00431 
00432   return res;
00433 }
00434 
00435 // ######################################################################
00436 // ######################################################################
00437 // ##### In-place ImageSet modification functions
00438 // ######################################################################
00439 // ######################################################################
00440 
00441 // ######################################################################
00442 template <class T> inline
00443 void doRectify(ImageSet<T>& x)
00444 {
00445   for (uint i = 0; i < x.size(); ++i)
00446     inplaceRectify(x[i]);
00447 }
00448 
00449 // ######################################################################
00450 template <class T> inline
00451 void doLowThresh(ImageSet<T>& x, const T threshold, const T newval)
00452 {
00453   for (uint i = 0; i < x.size(); ++i)
00454     inplaceLowThresh(x[i], threshold, newval);
00455 }
00456 
00457 // ######################################################################
00458 template <class T> inline
00459 void doLowThreshAbs(ImageSet<T>& x, const T threshold, const T newval)
00460 {
00461   for (uint i = 0; i < x.size(); ++i)
00462     inplaceLowThreshAbs(x[i], threshold, newval);
00463 }
00464 
00465 // ######################################################################
00466 template <class T> inline
00467 void doSqrt(ImageSet<T>& x)
00468 {
00469   for (uint i = 0; i < x.size(); ++i)
00470     x[i] = sqrt(x[i]);
00471 }
00472 
00473 // ######################################################################
00474 template <class T> inline
00475 void doSquared(ImageSet<T>& x)
00476 {
00477   for (uint i = 0; i < x.size(); ++i)
00478     x[i] = squared(x[i]);
00479 }
00480 
00481 // ######################################################################
00482 void doMeanNormalize(ImageSet<float>& x)
00483 {
00484   x -= mean(x);
00485 }
00486 
00487 // ######################################################################
00488 void doOneNormalize(ImageSet<float>& x)
00489 {
00490   const Range<float> r = rangeOf(x);
00491 
00492   for (uint i = 0; i < x.size(); ++i)
00493     {
00494       x[i] /= r.max();
00495     }
00496 }
00497 
00498 // ######################################################################
00499 void doEnergyNorm(ImageSet<float>& x)
00500 {
00501   for (uint i = 0; i < x.size(); ++i)
00502     {
00503       x[i] = energyNorm(x[i]);
00504     }
00505 }
00506 
00507 // ######################################################################
00508 void doApplyBiases(ImageSet<float>& x, const float* biases)
00509 {
00510   for (uint i = 0; i < x.size(); ++i)
00511     {
00512       x[i] *= biases[i];
00513     }
00514 }
00515 
00516 // ######################################################################
00517 void doAddWeighted(ImageSet<float>& x, const ImageSet<float>& y, float multiple)
00518 {
00519   ASSERT(x.size() == y.size());
00520   for (uint a = 0; a < x.size(); ++a)
00521     x[a] += y[a] * multiple;
00522 }
00523 
00524 // ######################################################################
00525 void doClear(ImageSet<float>& x, float v)
00526 {
00527   for (uint a = 0; a < x.size(); ++a)
00528     {
00529       x[a].clear(v);
00530     }
00531 }
00532 
00533 
00534 // Include the explicit instantiations
00535 #include "inst/Image/ImageSetOps.I"
00536 
00537 template bool isDyadic(const ImageSet<int>& pyr);
00538 template ImageSet<double>& operator/=(ImageSet<double>& x, const double& v);
00539 
00540 // ######################################################################
00541 /* So things look consistent in everyone's emacs... */
00542 /* Local Variables: */
00543 /* indent-tabs-mode: nil */
00544 /* End: */
Generated on Sun May 8 08:05:12 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3