
00001 /*!@file Image/MathOps.H Mathematical operations on Image 00002 */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: Rob Peters <rjpeters@klab.caltech.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/MathOps.H $ 00036 // $Id: MathOps.H 10794 2009-02-08 06:21:09Z itti $ 00037 // 00038 00039 #ifndef IMAGE_MATHOPS_H_DEFINED 00040 #define IMAGE_MATHOPS_H_DEFINED 00041 00042 #include "Image/Image.H" 00043 #include "Util/Promotions.H" 00044 #include <vector> 00045 00046 class Dims; 00047 template <class T> class Point2D; 00048 class Rectangle; 00049 template <class T> class Image; 00050 template <class T> class Range; 00051 00052 //! fill with a generating function: x = func() for each x in image 00053 /*! returns a copy of the functor object after having been called */ 00054 template <class T, class F> 00055 inline F fill(Image<T>& x, F func); 00056 00057 //! apply a function in-place: x = func(x) for each x in image 00058 /*! returns a copy of the functor object after having been called */ 00059 template <class T, class F> 00060 inline F apply(Image<T>& x, F func); 00061 00062 //! apply a function out-of-place: y = func(x) for x in input, y in output 00063 template <class T2, class T, class F> 00064 inline Image<T2> transform(const Image<T>& x, F func); 00065 00066 //! Returns the sum of all input pixels. 00067 template <class T> 00068 double sum(const Image<T>& a); 00069 00070 //! Get the average of all input pixels. 00071 template <class T> 00072 double mean(const Image<T>& a); 00073 00074 //! compute standard deviation of pixel values over image 00075 template <class T> 00076 double stdev(const Image<T>& a); 00077 00078 //! Get the min/max range of the input pixels. 00079 /*! This provides similar functionality to Image<T>::getMinMax(). */ 00080 template <class T> 00081 Range<T> rangeOf(const Image<T>& img); 00082 00083 //! Linearly remap pixels from the source to dest dynamic ranges. 00084 /*! This is similar to, but more general than, Image<T>::normalize(). In 00085 effect, Image<T>::normalize() always assumes that the source range is 00086 the image's own min/max range. In contrast, remapRange() allows one to 00087 find the global min/max across a range of images, and then use that as 00088 the source range while normalizing each the images using that range. */ 00089 template <class T> 00090 Image<T> remapRange(const Image<T>& img, 00091 const Range<T>& from, const Range<T>& to); 00092 00093 //! Square each element of the input image. 00094 template <class T> 00095 Image<T> squared(const Image<T>& a); 00096 00097 //! Raise each element of the input image to the given power. 00098 template <class T> 00099 Image<typename promote_trait<T,float>::TP> 00100 toPower(const Image<T>& a, double pow); 00101 00102 //! Raise pixels in given region of an input image to the given power. Pass a vector of 2D points that define the region of the image that you want to enhance. 00103 template <class T> 00104 Image<typename promote_trait<T,float>::TP> 00105 toPowerRegion(const Image<T>& a, double pow, std::vector<Point2D<int> > region); 00106 00107 00108 //! Take absolute value of every pixel. 00109 template <class T> 00110 Image<T> abs(const Image<T>& a); 00111 00112 //! Compute exp(pixel / (2 * sigma^2)) for every pixel. 00113 template <class T> 00114 Image<typename promote_trait<T,float>::TP> 00115 hmaxActivation(const Image<T>& a, const float sigma); 00116 /* 00117 //! Returns abs(b - c). 00118 //template <class T> 00119 //Image<T> absDiff(const Image<T>& b, const Image<T>& c); 00120 */ 00121 //! Returns abs(b - c) for each color channel 00122 template <class T_or_RGB> 00123 Image<T_or_RGB> absDiff(const Image<T_or_RGB>& b, 00124 const Image<T_or_RGB>& c); 00125 00126 //! Returns (b - c), clamping to zero all negative values. 00127 //template <class T> 00128 //Image<T> clampedDiff(const Image<T>& b, const Image<T>& c); 00129 00130 //! Returns (b - c) for each color channel, clamping to zero all neg. values 00131 template <class T_or_RGB> 00132 Image<T_or_RGB> clampedDiff(const Image<T_or_RGB>& b, 00133 const Image<T_or_RGB>& c); 00134 00135 //! Returns (val - a). 00136 template <class T> 00137 Image<T> binaryReverse(const Image<T>& a, const T val); 00138 00139 //! Returns (b + c) / 2, clean & prevents overflows. 00140 template <class T> 00141 Image<T> average(const Image<T>& b, const Image<T>& c); 00142 00143 //! Returns (a*w + b) / 2, the weighted average between images 00144 template <class T> 00145 Image<T> averageWeighted(Image<T>& a, const Image<T>& b, T *aWeight); 00146 00147 //! Returns max(a, b), element by element. 00148 template <class T_or_RGB> 00149 Image<T_or_RGB> takeMax(const Image<T_or_RGB>& a, 00150 const Image<T_or_RGB>& b); 00151 00152 //! Returns min(a, b), element by element. 00153 template <class T> 00154 Image<T> takeMin(const Image<T>& a, const Image<T>& b); 00155 00156 //! Compute energy for quadrature pair (sqrt(img1^2 + img2^2)). 00157 template <class T_or_RGB> 00158 Image<T_or_RGB> quadEnergy(const Image<T_or_RGB>& img1, 00159 const Image<T_or_RGB>& img2); 00160 00161 //! RMS error between arr1 and arr2. 00162 template <class T> 00163 double RMSerr(const Image<T>& arr1, const Image<T>& arr2); 00164 00165 //! Create transparency overlay of two images 00166 /*! by laying top over bottom with transparency of top set to 00167 trans. A new image will be returned (use 0 to 100 for percent 00168 transparency). NOTE: top and bottom must be the same size! 00169 this function only works for grey scale images */ 00170 template <class T> 00171 Image<T> overlay(const Image<T>& top, const Image<T>& bottom, 00172 const float trans); 00173 00174 //! sum pixels along the X and Y axes (sumX, sumY) and in total (return value) 00175 /*!@param img is a w x h size image 00176 @param sumX will return a vector of length w with the sum over the rows of img 00177 @param sumY will return a vector of length h with the sum over the columns*/ 00178 template <class T> 00179 float sumXY(const Image<T>& img, std::vector<float>& sumX, 00180 std::vector<float>& sumY); 00181 00182 //! Returns Euclidean distance between two images 00183 /*! Returns sqrt(sum_over_pixels((img1[i] - img2[i])^2)) */ 00184 template <class T> 00185 double distance(const Image<T> &img1, const Image<T> &img2); 00186 00187 //! Returns weighted Euclidean distance between two images 00188 /*! Returns sqrt(sum_over_pixels(weight[i] * (img1[i] - img2[i])^2)) */ 00189 template <class T> 00190 double distance(const Image<T> &img1, const Image<T> &img2, 00191 const Image<float> &weight); 00192 00193 //! Returns the correlation coefficient r^2 of the two images. 00194 double corrcoef(const Image<float>& img1, const Image<float>& img2); 00195 00196 //! Returns the cross-correlation coefficient r between two patches 00197 /*! Note that the computations done here differ from what is done in 00198 corrcoeff, in that a signed correlation coefficient is returned 00199 (between -1 and 1), and we add a convention that if both patches 00200 have zero variance then the correlation is 1. If only one patch has 00201 zero variance then the correlation is zero. Current implementation 00202 requires that the patch fits within both image bounds, and assumes a 00203 small patch size so that it will not attempt to use a faster 00204 FFT-based implementation which can save time with larger patches. 00205 @param img1 first image 00206 @param topleft1 coordinates of top-left corner of patch in img1 00207 @param patchdims dimensions of patch 00208 @param img2 second image 00209 @param topleft2 coordinates of top-left corner of patch in img2 00210 @param eps epsilon used to determine whether patch variance is zero */ 00211 template <class T> 00212 double corrpatch(const Image<T>& img1, const Point2D<int>& topleft1, 00213 const Dims& patchdims, const Image<T>& img2, 00214 const Point2D<int>& topleft2, const double eps = 1.0e-20); 00215 00216 //! return correlation matrix and means for input samples 00217 /*! This class will take a set of images and produce the eigen / correlation 00218 matrices. The input provided consists of a set of images: 00219 00220 (1) An image for each feature dimension 00221 (2) Multiple sets of (1) for each frame sample 00222 00223 That is, you provide a cardinal set of images that contains multiple 00224 image frames as well as feature maps for each frame. 00225 00226 This class returns an image that is the eigen matrix given the samples 00227 you have provided. It also returns the mean values per dimension. The 00228 usefulness of this is that one can compute and fit a gaussian to 00229 the data. This can be used for instance in likelyhood estimation. 00230 00231 The return eigen matrix is either a basic covariance matrix with 00232 un-normalized values useful for likelyhood estimation OR you can 00233 opt to have it normalize the matrix by the product of the standard 00234 deviations. This gives a pearson r correlation coefficent. 00235 00236 note on input: The set is a nest vector of images. It should be of the form 00237 in c++ notation 00238 00239 baseImages[frames][features] 00240 00241 Thus, the first nesting should index each frame while the second should 00242 index each feature image. 00243 00244 We compute covariance using an augmented method from Hayes 5th Ed. 1991 00245 00246 @param baseImages The set of all input images 00247 @param baseCorr a return image that is the eigen matrix 00248 @param baseMean a return image that is the set of means 00249 @param baseSTD a return image that is the set of independant standard dev. 00250 @param baseSS a return image that contains the sum of squares 00251 @param baseN a return uint that is the total sample size 00252 @param returnR Should we return the normalized R or the eigen matrix 00253 */ 00254 00255 template <class T> 00256 void corrEigenMatrix(const std::vector<std::vector<Image<T> > > &baseImages, 00257 Image<T> &baseCorr, Image<T> &baseMean, 00258 Image<T> &baseSTD, Image<T> &baseSS, 00259 uint &baseN, bool returnR = false); 00260 00261 //! Given an eigen matrix and mean matrix, compute a likelyhood image 00262 /*! In this function we take in an image and the statistics of an 00263 exemplar image set. We then use this to find a likelyhood image 00264 which is how much each pixel in the input image is like the exempler 00265 based on probability. High return values mean that a pixel has a high 00266 probability of belonging to the exemplar class. 00267 00268 Basically, we compute P(x|C) for each pixel assuming baseImages as the 00269 samples and baseCorr as the eigen matrix that describes the distribution 00270 of the original sample. This computes P from the multi-variate gaussian. 00271 The results can be taken and fed into getNormalized bayes image with 00272 the results from a second class to give a true bayes P for each pixel 00273 belonging to one class or the other. 00274 00275 Note: the non-normalized likelhood image is usefull for certain things 00276 but should not be used in deriving the direct bayed probability 00277 00278 @param baseImage the image set you wish to find the likelyhood over 00279 @param baseCorr The eigen matrix correlation from the training set 00280 @param baseMean The set of mean values from the training set 00281 @param returnLogLikelyhood Keep numbers sane and return log not e^ 00282 @param likelyhoodImage this is the returned likelyhood image 00283 @param nonNormalizedLImage this is a non-normalized likelyhood image 00284 00285 */ 00286 template <class T> 00287 void getLikelyhoodImage(const std::vector<Image<T> > &baseImages, 00288 const Image<T> &baseCorr, const Image<T> &baseMean, 00289 const bool returnLogLikelyhood, 00290 Image<T> &likelyhoodImage, 00291 Image<T> &nonNormalizedLImage); 00292 00293 //! Take in two likelyhood images and compute bayes p between them 00294 /*! The idea here is to compute the true bayesian probability of 00295 membership in one image or another given the likelyhood computed in 00296 getLikelyhoodImage. Here we compute the p(C|x) for two classes. 00297 00298 The idea here is to compute the likelyhood that a pixel belongs to one 00299 class v. another in an input image. You must input two likelyhood images 00300 of the form P(x|C) (as computed in getLikelyhoodImage). Also, you may 00301 input the prior probability P(C) if P(C1) is not P(C2). Otherwise, 00302 it is assumed P(C1) = P(C2). 00303 00304 The return image has the P for each pixel being in class 1 v. class 2 00305 to get the result the other way, compute 1 - P (pretty easy). 00306 00307 To compute this, we perform P(C|x) = g(a) where: 00308 00309 a = ln((P(x|C1)*P(C1))/(P(x|C2)*P(C2))) 00310 00311 g(a) = 1/(1 + exp(-a)) 00312 00313 This is known as logistic discrimination (Bishop 1995) 00314 00315 @param classImage1 the likelyhood image of class 1 00316 @param classImage2 the likelyhood image of class 2 00317 @usingLogLikelyhood set to true if using log rather than e^ likelyhood 00318 @param classPrior1 the prior of class 1 (sample numbers) 00319 @param classPrior2 the prior of class 2 (sample numbers) 00320 @param bias This is a simple bias if desired, P(x)' = P(x)*bias 00321 */ 00322 template <class T> 00323 Image<T> getNormalizedBayesImage(const Image<T> classImage1, 00324 const Image<T> classImage2, 00325 const bool usingLogLikelyhood, 00326 const T beta, 00327 const T classPrior1 = 1.0, 00328 const T classPrior2 = 1.0, 00329 const T bias = 1.0); 00330 00331 //! Take in an image of correlation and standard deviation, give r 00332 /*! You can use this function to give r from an already existing eigen matrix 00333 for instance, one computed from corrEigenMatrix. Thus, you can post hoc 00334 compute r if you opted not to when using corrEigenMatrix. This function 00335 just basically normalizes the eigen matrix by the standard deviation 00336 to give a true pearson r correlation matrix 00337 00338 @param eigenMatrix The input eigen correlation matrix 00339 @param STDMatrix The input independant standard deviations 00340 */ 00341 template <class T> 00342 Image<T> getPearsonRMatrix(const Image<T> &eigenMatrix, 00343 const Image<T> &STDMatrix); 00344 00345 //! Augment the bayes image with some beliefs 00346 /*! The belief images should be from 0 to 1 where 0 signifies 00347 complete belief in the reliability of class1 results while 0 00348 signifies absolutly no reliability. This basicially takes the product 00349 of the two as the final augmented belief. 00350 00351 Using the median point, beliefs can be contracted to single values 00352 for instance, if the input bayes image ranges from 0 to 2, if the median 00353 is specified as 1, then values below 1 will tend to 1 as beleifs decrease 00354 while values above 1, will tend to 1 as beliefs decrease. 00355 00356 @param bayesImage An image from getNormalizedBayesImage 00357 @param beliefImage1 the belief for class image 1 00358 @param beliefImage2 the belief for class image 2 00359 @param medianPoint a middle point values are squashed to 00360 @param beliefImage The augemented belief image 00361 @param beliefValue a record of the beleif products 00362 */ 00363 00364 template <class T> 00365 void getAugmentedBeliefBayesImage(const Image<T> &bayesImage, 00366 const Image<T> &beliefImage1, 00367 const Image<T> &beliefImage2, 00368 const T medianPoint, 00369 Image<T> &beliefImage, 00370 Image<T> &beliefValue); 00371 00372 00373 00374 //! Returns peak signal-to-noise ratio 00375 /*! pSNR is computed as 10.log_10(255^2/sigma^2) where 00376 sigma^2=/N.sum(x1_i - x2_i)^2 and is a measure of distortion between 00377 two images */ 00378 template <class T> 00379 double pSNR(const Image<T> &img1, const Image<T> &img2); 00380 00381 //! Returns weighted peak signal-to-noise ratio 00382 /*! This is like the other pSNR() except that it uses the weighted 00383 version of distance() internally */ 00384 template <class T> 00385 double pSNR(const Image<T> &img1, const Image<T> &img2, 00386 const Image<float>& weight); 00387 00388 //! Take square root of all elements 00389 template <class T> 00390 Image<typename promote_trait<T,float>::TP> sqrt(const Image<T>& img); 00391 00392 //! Take inverse of all elements > eps in abs, 0 otherwise 00393 template <class T> 00394 Image<typename promote_trait<T,float>::TP> inverse(const Image<T>& img, 00395 const T eps); 00396 00397 //! Take exponential of all pixels 00398 template <class T> 00399 Image<typename promote_trait<T,float>::TP> exp(const Image<T>& img); 00400 00401 //! Take negative exponential of all pixels, that is exp(-x) 00402 template <class T> 00403 Image<typename promote_trait<T,float>::TP> negexp(const Image<T>& img); 00404 00405 //! Take natural logarithm of all pixels 00406 template <class T> 00407 Image<typename promote_trait<T,float>::TP> log(const Image<T>& img); 00408 00409 //! Take base-10 logarithm of all pixels 00410 template <class T> 00411 Image<typename promote_trait<T,float>::TP> log10(const Image<T>& img); 00412 00413 //! determine the first and last non-zero values and the centroid 00414 /*!@param vect a vector of numbers 00415 @param centroid returns the centroid of vect 00416 @param first returns the position of the first non-zero value in vect 00417 @param last returns the position of the last non-zero value in vect 00418 @return true if we actually found all these values, false if vect 00419 only contains zeros*/ 00420 template <class T> 00421 bool getCentroidFirstLast(std::vector<T> vect, float& centroid, 00422 int& first, int& last); 00423 00424 //! determine the centroid of all the points in the image 00425 /*! The centroid is rounded to integer pixel positions. 00426 When there are no values > 0 in the img, (-1,-1) is returned 00427 @param boundingBox the bounding box of the object(s) contained in 00428 the image is returned 00429 @param cenX returns the float value of the centroid along the x axis 00430 @param cenY returns the float value of the centroid along the y axis 00431 @return the centroid rounded to integer coordinates*/ 00432 template <class T> 00433 Point2D<int> centroid(const Image<T>& img, Rectangle& boundingBox, 00434 float& cenX, float& cenY); 00435 00436 //! determine the center of mass of all the points in the image 00437 /*! The centroid is rounded to integer pixel positions. 00438 When there are no values > 0 in the img, (-1,-1) is returned */ 00439 template <class T> 00440 Point2D<int> centroid(const Image<T>& img); 00441 00442 //! Apply a squashing function to the pixel values 00443 /*! The squashing function is a 4th-order polynomial with sigmoidal 00444 shape. Denoting by x a pixel value in the original image and by 00445 y=f(x) the transformed pixel value that will be put in the result 00446 image, the contraints on the polynomial are: 1) f(oldmin)=newmin, 2) 00447 f(oldmax)=newmax, 3) f(oldmid)=newmid, 4) f'(oldmin)=0, and 5) 00448 f'(oldmax)=0. So, typically, the polynomial will have horizontal 00449 slope at both ends of the input range, and will remap the old 00450 min/max to the new min/max while also remapping a user-chosen 00451 mid-point oldmid to newmid. Playing with this mid-point allows the 00452 user to give more emphasis to higher or lower values while 00453 remapping. This is the full form, but two simplified forms are also 00454 available that will compute some of the arguments here from the 00455 input image. Because the main use of this function is when oldmin is 00456 the true minimum value of the input image, and oldmax its true 00457 maximum, here we will not waste time checking for input values 00458 outside this range, and their remapped values are unclear as the 00459 polynomial is unconstrained outside the input range. Internal 00460 remapping is done using floats, and results are converted back (with 00461 possible clamping) to the same type as the original image, so that 00462 this function may be efficiently used to do contrast adjustments in 00463 Image<byte> data. */ 00464 template<class T> 00465 Image<T> squash(const Image<T>& src, 00466 const T oldmin, const T newmin, 00467 const T oldmid, const T newmid, 00468 const T oldmax, const T newmax); 00469 00470 //! Apply a squashing function to the pixel values 00471 /*! In this specialization of the general form of squash(), the old 00472 min/max are computed using getMinMax(). */ 00473 template<class T> 00474 Image<T> squash(const Image<T>& src, const T newmin, 00475 const T oldmid, const T newmid, const T newmax); 00476 00477 //! Apply a squashing function to the pixel values 00478 /*! In this specialization of the general form of squash(), the old 00479 min/max are computed using getMinMax(), and the new min/max will be 00480 kept equal to the old ones, so that there is no overall change in 00481 range (unless your mid-point is outside that range). */ 00482 template<class T> 00483 Image<T> squash(const Image<T>& src, const T oldmid, const T newmid); 00484 00485 //! Mix between two images based on comparing mask values to a threshold 00486 /*! On every pixel, if mask >= thresh, the returned value is taken 00487 from higher, otherwise it is taken from lower. All three of lower, 00488 highr and mask must have same dims. */ 00489 template <class T, class T_or_RGB> 00490 Image<T_or_RGB> thresholdedMix(const Image<T>& mask, const T& thresh, 00491 const Image<T_or_RGB>& lower, 00492 const Image<T_or_RGB>& higher); 00493 00494 //! take the logistic sigmoid 1/(1+e^x(...)) over the image 00495 /*! This is a standard logistic sigmoid with offset o and slope b 00496 @param ima the input image 00497 @param o Offset for this sigmoid 00498 @param b Slope for this sigmoid 00499 */ 00500 Image<float> logSig(const Image<float>& ima, float o, float b); 00501 00502 //! randomly scramble image pixels 00503 template <class T_or_RGB> 00504 Image<T_or_RGB> scramble(const Image<T_or_RGB>& ima); 00505 00506 //! take in an image and return it's statistically most relevent points 00507 /*! 00508 Input an image to find a monte carlo like map. This will in essence cut 00509 out about half the pixels in a simple quick fashion by applying the formula: 00510 select if -> pow(pixelValue,bias) > minVal+(maxVal*rand()/RAND_MAX+1.0) 00511 The bias is used to scew the distribution using an exponent 00512 if no bias is given, this method will work more efficently by skipping 00513 the exponent computation over each pixel. 00514 @param ima This is the input probability map 00515 @param coords this is a pointer to a vector which will hold selected coords 00516 @param bais this scews the probability map by pow(pixVal,bias) 00517 00518 */ 00519 int32 findMonteMap(Image<float>& ima, 00520 std::vector<Point2D<int> >* coords, 00521 int decimation, float bias); 00522 00523 //! Take in a vector and decimate it according how many points you want back 00524 /*! 00525 In essence this will decimate a list of coordinates attempting to create a 00526 list of the size in outPoints. Thus, if you have list of 23890 points and 00527 want a list of 300 points, this will take every nth point and create a 00528 list of about this size. 00529 @param coords This is the list of input coordinates 00530 @param cmap This is the final list of coordinates after decimation 00531 @param inPoints this is the input list size 00532 @param outPoints this is how many points you would like out 00533 */ 00534 00535 int32 makeSparceMap(std::vector<Point2D<int> >* coords, std::vector<Point2D<int>*>* cmap, 00536 std::vector<Point2D<int> >* Oldcoords, 00537 std::vector<bool>* keep, int inPoints, int outPoints); 00538 00539 00540 //! a += b * coeff 00541 template <class T> 00542 void inplaceAddWeighted(Image<T>& a, 00543 const Image<T>& b, const float coeff); 00544 00545 //! a = a*a 00546 template <class T> 00547 void inplaceSquare(Image<T>& a); 00548 00549 //! Replace all occurences of a value 'from' by another value 'to' 00550 void inplaceReplaceVal(Image<byte>& dest, 00551 const byte& from, const byte& to); 00552 00553 //! Progressive attenuation of borders by "size" pixels 00554 template <class T_or_RGB> 00555 void inplaceAttenuateBorders(Image<T_or_RGB>& a, int size); 00556 00557 //! Set borders of "size" pixels to given value 00558 /*! Default value is T's default, which should be T's representation 00559 of zero. */ 00560 template <class T_or_RGB> 00561 void inplaceSetBorders(Image<T_or_RGB>& a, const int size, 00562 const T_or_RGB value = T_or_RGB()); 00563 00564 //! Add speckle noise to array; thresh = 1 for 100% noise 00565 void inplaceSpeckleNoise(Image<byte>& dest, 00566 const float thresh, const int size, 00567 const byte noise_color, 00568 bool random_color=false); 00569 00570 //! Get a sample which is the max value within a circular aperture 00571 /*! This only works for monochromatic images. 00572 @param center coordinates of the center of the aperture 00573 @param radius radius of the aperture, in pixels */ 00574 float getLocalMax(const Image<float>& src, 00575 const Point2D<int>& center, const int radius); 00576 00577 //! Get min and max values 00578 template <class T> 00579 void getMinMax(const Image<T>& src, T& mini, T& maxi); 00580 00581 //! Get min and max values inside and outside a mask 00582 /*! Only pixels with non-zero mask value are considered. */ 00583 template <class T> 00584 void getMaskedMinMax(const Image<T>& src, const Image<byte>& mask, 00585 T& min_in, T& max_in, T& min_out, T& max_out); 00586 00587 //! Get min, max and average values 00588 template <class T> 00589 void getMinMaxAvg(const Image<T>& src, T& mini, T& maxi, T& avg); 00590 00591 //! Get min, max, avg within a binary mask 00592 /*! Only the pixels where mask is non-zero are considered. */ 00593 template <class T> 00594 void getMaskedMinMaxAvg(const Image<T>& src, const Image<byte> &mask, 00595 T& mi, T& ma, T& avg); 00596 00597 //! Get min, max, sum and area values from a continuously-masked image 00598 /*! The sum is the weighted sum of src by mask. Area is the sum of all 00599 non-zero mask values. */ 00600 template <class T> 00601 void getMaskedMinMaxSumArea(const Image<T>& src, const Image<float> &mask, 00602 T& mi, T& ma, 00603 typename promote_trait<T,float>::TP &sum, 00604 typename promote_trait<T,float>::TP &area); 00605 00606 //! Get min, max, average std deviation and some other stats 00607 template <class T> 00608 void getMinMaxAvgEtc(const Image<T>& src, T& xmini, T& xmaxi, T& xavg, T& xstd, 00609 ushort& minPosX, ushort& minPosY, 00610 ushort& maxPosX, ushort& maxPosY, 00611 uint& pixCount); 00612 00613 //! Check wether all pixels have finite values 00614 /*! This relies on isFinite() being defined for your pixel type 00615 T. In Types.H we define it for the canonical types, and you can 00616 use these canonical definitions to define it for more complex 00617 types (see, for example, the definition in Pixels.H). */ 00618 template <class T> 00619 bool isFinite(const Image<T>& src); 00620 00621 //! find point of max activity and also what that max activity is 00622 template <class T> 00623 void findMax(const Image<T>& src, Point2D<int>& p, T& maxval); 00624 00625 //! find point of min activity and also what that min activity is 00626 template <class T> 00627 void findMin(const Image<T>& src, Point2D<int>& p, T& minval); 00628 00629 //! Saturate values < cmin to cmin and > cmax to cmax 00630 template <class T> 00631 void inplaceClamp(Image<T>& dst, const T cmin, const T cmax); 00632 00633 //! Normalize values between nmin and nmax 00634 template <class T> 00635 void inplaceNormalize(Image<T>& dst, const T nmin, const T nmax); 00636 00637 //! Normalize values between nmin and nmax, also return oldmin and oldmax 00638 template <class T> 00639 void inplaceNormalize(Image<T>& dst, const T nmin, const T nmax, 00640 T& oldmin, T& oldmax); 00641 00642 //! Return true if point p is a local maximum 00643 /*! We just check that the value at p is >= the values of its 4 neighbors */ 00644 template <class T> 00645 bool isLocalMax(const Image<T>& src, const Point2D<int>& p); 00646 00647 //! Saturate values < 0 00648 template <class T> 00649 void inplaceRectify(Image<T>& dst); 00650 00651 //! Put all values >= 0 into pos and the negated of all vals <= 0 into neg 00652 template <class T> 00653 void splitPosNeg(const Image<T>& src, 00654 Image<T>& pos, Image<T>& neg); 00655 00656 //! Cut values < thresh and replace them by val 00657 template <class T> 00658 void inplaceLowThresh(Image<T>& dst, 00659 const T thresh, const T val = T()); 00660 00661 //! Cut values whose abs is < thresh and replace them by val 00662 template <class T> 00663 void inplaceLowThreshAbs(Image<T>& dst, 00664 const T thresh, const T val = T()); 00665 00666 //! Pass image through sigmoid: f(x) = x^g / (s + x^h) 00667 template <class T> 00668 void inplaceSigmoid(Image<T>& dst, 00669 const float g, const float h, const float s); 00670 00671 //! Tells how many pixels are zero 00672 template <class T> 00673 int emptyArea(const Image<T>& src); 00674 00675 //! Counts how many pixels are > thresh (in absolute value if absol true) 00676 template <class T> 00677 int countThresh(const Image<T>& src, 00678 const T thresh, const bool absol = true); 00679 00680 //! Return a row vector containing the within-column mean of each input column 00681 Image<float> meanRow(const Image<float>& inp); 00682 00683 //! Return a row vector containing the within-column standard deviation of each input column 00684 Image<float> stdevRow(const Image<float>& inp); 00685 00686 //! Return the result of adding vector v to each row of matrix M 00687 Image<float> addRow(const Image<float>& M, const Image<float>& v); 00688 00689 //! Return the result of subtracting vector v from each row of matrix M 00690 Image<float> subtractRow(const Image<float>& M, const Image<float>& v); 00691 00692 //! Return the result of multiplying each row of matrix M by vector v 00693 Image<float> multiplyRow(const Image<float>& M, const Image<float>& v); 00694 00695 //! Return the result of dividing each row of matrix M by vector v 00696 Image<float> divideRow(const Image<float>& M, const Image<float>& v); 00697 00698 // ###################################################################### 00699 // ###################################################################### 00700 // ##### Inline function definitions 00701 // ###################################################################### 00702 // ###################################################################### 00703 00704 // ###################################################################### 00705 template <class T, class F> 00706 inline F fill(Image<T>& x, F func) 00707 { 00708 // optimization; see comment in Image<T>::clear() 00709 if (x.isShared()) 00710 x = Image<T>(x.getDims(), NO_INIT); 00711 00712 for (typename Image<T>::iterator itr = x.beginw(), stop = x.endw(); 00713 itr != stop; ++itr) 00714 *itr = T(func()); 00715 00716 return func; 00717 } 00718 00719 // ###################################################################### 00720 template <class T, class F> 00721 inline F apply(Image<T>& x, F func) 00722 { 00723 for (typename Image<T>::iterator itr = x.beginw(), stop = x.endw(); 00724 itr != stop; ++itr) 00725 *itr = T(func(*itr)); 00726 00727 return func; 00728 } 00729 00730 // ###################################################################### 00731 template <class T2, class T, class F> inline 00732 Image<T2> transform(const Image<T>& x, F func) 00733 { 00734 Image<T2> result(x.getDims(), NO_INIT); 00735 00736 typename Image<T>::const_iterator sptr = x.begin(); 00737 typename Image<T2>::iterator dptr = result.beginw(); 00738 typename Image<T2>::iterator stop = result.endw(); 00739 00740 while (dptr != stop) 00741 *dptr++ = func(*sptr++); 00742 00743 return result; 00744 } 00745 00746 // ###################################################################### 00747 /* So things look consistent in everyone's emacs... */ 00748 /* Local Variables: */ 00749 /* indent-tabs-mode: nil */ 00750 /* End: */ 00751 00752 #endif // !IMAGE_MATHOPS_H_DEFINED
1.4.4