
00001 /*!@file Image/ColorOps.H Color 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/ColorOps.H $ 00036 // $Id: ColorOps.H 11147 2009-04-28 05:23:29Z itti $ 00037 // 00038 00039 // The fromXXX() code here is somewhat inspired from the 00040 // grab_gray_image.c example code provided with the libdc1394 00041 // distribution by Gord Peters, and from the Coriander source code. 00042 00043 #ifndef IMAGE_COLOROPS_H_DEFINED 00044 #define IMAGE_COLOROPS_H_DEFINED 00045 00046 #include "Image/Image.H" 00047 #include "Util/Assert.H" 00048 #include "Util/Promotions.H" 00049 00050 class Dims; 00051 template <class T> class Image; 00052 template <class T> class PixRGB; 00053 class ColorMap; 00054 00055 //! Set the red, green and blue components from 3 monochromatic images 00056 template <class T> 00057 Image<PixRGB<T> > makeRGB(const Image<T>& red, 00058 const Image<T>& green, 00059 const Image<T>& blue); 00060 00061 //! Colorize a greyscale byte image using a colormap 00062 /*! Note that this will throw a fatal error if the colormap does not 00063 have exactly 256 entries. */ 00064 Image< PixRGB<byte> > colorize(const Image<byte>& img, const ColorMap& cmap); 00065 00066 //! Add color speckle noise to array; faster version, draws 'num' dots 00067 void inplaceColorSpeckleNoise(Image< PixRGB<byte> >& dest, const int num); 00068 00069 //! Get the red, green and blue components as 3 monochromatic images 00070 template <class T> 00071 void getComponents(const Image<PixRGB<T> >& src, 00072 Image<T>& red, Image<T>& green, Image<T>& blue); 00073 00074 //! Split out a single pixel component image from a multispectral pixel input image 00075 template <class PixT> 00076 inline Image<typename PixT::ScalarType> 00077 getPixelComponentImage(const Image<PixT>& in, const size_t i) 00078 { 00079 typedef typename PixT::ScalarType T; 00080 00081 Image<T> result(in.getDims(), NO_INIT); 00082 00083 typename Image<PixT>::const_iterator sptr = in.begin(); 00084 typename Image<T>::iterator dptr = result.beginw(); 00085 typename Image<T>::iterator stop = result.endw(); 00086 00087 ASSERT(i < PixT::myDim); 00088 00089 while (dptr != stop) 00090 { 00091 *dptr = sptr->p[i]; 00092 ++dptr; ++sptr; 00093 } 00094 00095 return result; 00096 } 00097 00098 /*! This method will normalize an image based upon the maximum value 00099 provided to it. This is either max or the absolute value of min. 00100 It then creates an image where all negative values are assigned a red 00101 pixel value while all postive numbers are assigned a green pixel value 00102 @param max The maximum pixel value 00103 @param min The minimum pixel value 00104 @param image The image of values (positive and negative) to be processed 00105 */ 00106 Image<PixRGB<float> > normalizeRGPolar(const Image<float>& src, 00107 const float max, 00108 const float min); 00109 /*! This method will normalize an image based upon the maximum value 00110 provided to it. This is either max or the absolute value of min. 00111 It then creates an image where all negative values are assigned a red 00112 pixel value while all postive numbers are assigned a green pixel value. 00113 This version will autmatically determine min and max and then normalize 00114 between 0 and 255 for red and green 00115 @param image The image of values (positive and negative) to be processed 00116 */ 00117 Image<PixRGB<float> > normalizeRGPolarAuto(const Image<float>& src); 00118 //! Normalize a grey scale image, with some idea for scale 00119 /*! nromalize a grey scale image, but to give an idea of the actual scale, 00120 we leave one channel as the orignal value and set the other the new 00121 value. This way, the intensity is still normalized over once channel 00122 so that you can make out the image features, but the hue change lets 00123 you know that the real intensity was very high. 00124 00125 Note: the output baseColor and normColor should be 1,2 or 3. They should 00126 also not be equal. These are which channel is set as the base and 00127 normalized channel representations. 00128 00129 Also Note: The base color will be clamped to between 0 and clamp so 00130 that it can still be displayed 00131 00132 @param src The orignal grey scale image 00133 @param min The low bound on the normalization, for instance 0 00134 @param max The high bound on the normalization, for instance 255 00135 @param clamp clamp the baseColor to no more than this value 00136 @param baseColor, 1,2,3 ; R,G,B : which channel to not normalize out 00137 @param normColor, 1,2,3 ; R,G,B : which channel to normalize out 00138 */ 00139 Image<PixRGB<float> > normalizeWithScale(const Image<float>& src, 00140 const float min, 00141 const float max, 00142 const float clamp, 00143 const char baseColor, 00144 const char normColor); 00145 00146 //! Normalize a grey scale image, with some idea for scale 00147 /*! Here we normalize the image using translation between RGB and HSV 00148 what we do is set the intensity as the basic normalized value 00149 of the original gray scale image. However, we use hue as the 00150 absolute scale. Saturation is constant at 100 (full). 00151 */ 00152 Image<PixRGB<float> > normalizeScaleRainbow(const Image<float>& src, 00153 const float min, 00154 const float max); 00155 //! Create a color image by staining a monochrome image. 00156 /*! Each pixel in the result is given by the stain color multiplied by 00157 the corresponding pixel in the monochrome source image. This is 00158 entirely equivalent to, but more efficient than, creating a color 00159 image from the monochrome image, then multiplying the color image 00160 by the stain color.*/ 00161 template <class T> 00162 Image<PixRGB<T> > stain(const Image<T>& src, PixRGB<float> color); 00163 00164 //! Create a color image from src by tinting positive and negative values 00165 /*! For each pixel x in the input image, we compute ratio=x/maxval; 00166 then if the ratio is positive, the output value is ratio*pos_stain 00167 + (1-ratio)*background, and if the ratio is negative, then the 00168 output value is (-ratio)*neg_stain + (1-(-ratio))*background. */ 00169 Image<PixRGB<float> > stainPosNeg(const Image<float>& src, 00170 const float maxval, 00171 const PixRGB<float>& background, 00172 const PixRGB<float>& pos_stain, 00173 const PixRGB<float>& neg_stain); 00174 00175 //! Overlay an image over another, however, stain the top image 00176 /*! This method works almost exactly like overlay except that the 00177 bottom image is stained (colored) red green or blue depending on 00178 whether char channel is set to r,g, or b */ 00179 Image<PixRGB<float> > overlayStain(const Image<float>& top, 00180 const Image<float>& bottom, 00181 const float trans, const char channel); 00182 00183 //! Get min and max of the components 00184 template <class T> 00185 void getMinMaxC(const Image<PixRGB<T> >& src, T& mi, T& ma); 00186 00187 //! Normalize values between nmin and nmax 00188 template <class T, class T2> 00189 inline void normalizeC(Image<PixRGB<T> >& src, const T2 nmin, const T2 nmax) 00190 { 00191 ASSERT(src.initialized()); 00192 T mi, ma; getMinMaxC(src, mi, ma); 00193 const float mif = float(mi); 00194 const float maf = float(ma); 00195 const float scale = maf - mif; 00196 if (scale > -1.0e-20 && scale < 1.0e-20) return; // no need to rescale... 00197 const float nscale = (float(nmax) - float(nmin)) / scale; 00198 00199 typename Image<PixRGB<T> >::iterator aptr = src.beginw(); 00200 typename Image<PixRGB<T> >::iterator stop = src.endw(); 00201 00202 while (aptr != stop) 00203 { 00204 aptr->setRed (nmin+(T2)(((float(aptr->red()))-mif)*nscale)); 00205 aptr->setGreen(nmin+(T2)(((float(aptr->green()))-mif)*nscale)); 00206 aptr->setBlue (nmin+(T2)(((float(aptr->blue()))-mif)*nscale)); 00207 ++aptr; 00208 } 00209 } 00210 00211 //! Compute luminance of a color image 00212 template <class T> 00213 Image<T> luminance(const Image<PixRGB<T> >& src); 00214 00215 //! Compute luminance of a greyscale image (no-op) 00216 /*! This no-op overload is provided so that luminance() can be applied 00217 to template images where it is not known whether the template 00218 argument is scalar or PixRGB. */ 00219 template <class T> 00220 Image<T> luminance(const Image<T>& src); 00221 00222 //! Compute luminance in NTSC coordinates 00223 /*! This version performs the same function as rgb2gray() in matlab */ 00224 template <class T> 00225 Image<T> luminanceNTSC(const Image<PixRGB<T> >& src); 00226 00227 //! Convert grayscale image to RGB 00228 template <class T> 00229 Image< PixRGB<T> > toRGB(const Image<T>& src); 00230 00231 //! Convert RGB image to RGB (no-op) 00232 /*! This no-op function is provided so that toRGB() can be applied to 00233 template images where it is not known whether the template argument 00234 is scalar or PixRGB. */ 00235 template <class T> 00236 Image< PixRGB<T> > toRGB(const Image< PixRGB<T> >& src); 00237 00238 //! Compute color information measure based in infoFFT 00239 template <class T> 00240 Image<float> infoMeasure(const Image<PixRGB<T> >& src, 00241 const float eps, const int size); 00242 00243 //! Get YIQ color components 00244 template <class T> 00245 void getYIQ(const Image<PixRGB<T> >& src, 00246 Image<T>& y, Image<T>& i, Image<T>& q); 00247 00248 //! Get YUV color components from an RGB image 00249 template <class T> 00250 void getJpegYUV(const Image<PixRGB<T> >& src, 00251 Image<T>& y, Image<T>& u, Image<T>& v); 00252 00253 //! Normalize my values by those in the lum image 00254 template <class T> 00255 Image<PixRGB<T> > luminanceNormalize(const Image<PixRGB<T> >& src, 00256 const T thresh); 00257 00258 //! Compute R/G and B/Y channels from a luminanceNormalized color image 00259 /*! This version does automatic promotion on the results, so that 00260 negative values can be represented even if the input is of type 00261 PixRGB<byte> */ 00262 template <class T> 00263 void getRGBY(const Image<PixRGB<T> >& src, 00264 Image<typename promote_trait<T, float>::TP>& rg, 00265 Image<typename promote_trait<T, float>::TP>& by, 00266 const typename promote_trait<T, float>::TP thresh); 00267 00268 //! Compute R/G and B/Y channels in a simpler way 00269 /*! Params are as in getRGBY. The computation for the RG and BY maps 00270 is: RG = (R-G)/max(R,G,B); BY = (B-min(R,G))/max(R,G,B).*/ 00271 template <class T> 00272 void getRGBYsimple(const Image<PixRGB<T> >& src, 00273 Image<typename promote_trait<T, float>::TP>& rg, 00274 Image<typename promote_trait<T, float>::TP>& by, 00275 const typename promote_trait<T, float>::TP thresh); 00276 00277 //! Compute R, G, B, Y channels from a luminanceNormalized color image 00278 /*! This version keeps the four channels separate so that correct 00279 results can be obtained without requiring promotion even if the 00280 input is of type PixRGB<byte> */ 00281 template <class T> 00282 void getRGBY(const Image<PixRGB<T> >& src, Image<T>& r, Image<T>& g, 00283 Image<T>& b, Image<T>& y, const T thresh); 00284 00285 //! Compute R/G and B/Y via computation of H2SV2 color space 00286 /*! In addition to returning R/G and B/Y this basically returns the 00287 full H2SV color space. the original RGB can be obtained later 00288 via conversion of rg,by, sat and val using a PixH2SV2 to RGB 00289 */ 00290 template <class T> 00291 void getRGBY(const Image<PixRGB<T> >& src, Image<T>& rg, Image<T>& by, 00292 Image<T>& sat, Image<T>& val, const ushort H2SVtype = 2); 00293 00294 //! Compute D, K, L color components from an RGB image 00295 /*! The DKL color space is motivated by the neurobiology of early 00296 vision in primates. D is roughly like luminance (with some neutral 00297 grey (RGB=[161 159 154]) at zero, white around 1.0, and black 00298 around -1.0), K roughly like Red-Green, and L roughly like 00299 Blue-Yellow. The images returned here have signed float values 00300 roughly in [-1,1] (but they sometimes are slightly larger that exactly 00301 that, so be sure to clamp if you ar egoing to convert). */ 00302 template <class T> 00303 void getDKL(const Image<PixRGB<T> >& src, 00304 Image<typename promote_trait<T, float>::TP>& dimg, 00305 Image<typename promote_trait<T, float>::TP>& kimg, 00306 Image<typename promote_trait<T, float>::TP>& limg); 00307 00308 //! contrast-modulate an RGB image with a mask 00309 Image< PixRGB<byte> > contrastModulate(const Image< PixRGB<byte> >& img, 00310 const Image<float>& mask, 00311 float baseContrast = 0.05, 00312 byte baseBright = 255); 00313 00314 //! Compute peak signal-to-noise ratio between two color images 00315 /*! For color images, pSNR computed from the average 00316 mean-squared-error from the red, green and blue channels */ 00317 template <class T> 00318 double pSNRcolor(const Image< PixRGB<T> >& img1, 00319 const Image< PixRGB<T> >& img2); 00320 00321 //! Compute weighted peak signal-to-noise ratio between two color images 00322 /*! This is like the other pSNRcolor() except that it uses the 00323 weighted version of distance() internally */ 00324 template <class T> 00325 double pSNRcolor(const Image< PixRGB<T> >& img1, 00326 const Image< PixRGB<T> >& img2, 00327 const Image<float>& weight); 00328 00329 //! Normalize each component of the RGB image separately 00330 /*! Normalize the red component with min.red() and max.red() etc.*/ 00331 template <class T> 00332 Image< PixRGB<T> > normalizeRGB(const Image< PixRGB<T> >& img, 00333 PixRGB<T> min, 00334 PixRGB<T> max); 00335 00336 //! Return the pixel-wise maximum of the r, g and b component 00337 template <class T> 00338 Image<T> maxRGB(const Image< PixRGB<T> >& img); 00339 00340 //! Stain a black and white image with a color 00341 /*! @param src the black and white image to be stained 00342 @param min This value will be converted to 0 (black) 00343 @param max This value will be converted to color 00344 @param color The color used for staining */ 00345 template <class T> 00346 Image< PixRGB<T> > colorStain (const Image<T>& src, 00347 const T& min, const T& max, 00348 const PixRGB<T>& color); 00349 00350 //! convert RGB color values into C.I.E. coordinates 00351 /*! @param rgbColor the color to convert from 00352 @param cr returns the R/I value 00353 @param cg returns the G/I value 00354 @param intens returns the intensity */ 00355 void RGBtoCIE(const PixRGB<byte>& rgbColor, 00356 float& cr, float& cg, float& intens); 00357 00358 //! distance between hue of image pixels and a given hue 00359 /*! @param img The color image to compare 00360 @param muR the R/I coordinate of the target hue in the C.I.E. color space 00361 @param muG the G/I coordinate in C.I.E. 00362 @param sigR the standard deviation of a 2D Gaussian in R/I direction 00363 @param sigG the standard deviation of a 2D Gaussian in G/I direction 00364 @param rho the correlation between the R/I and G/I directions 00365 @return a float image coding for how close the hue in img is 00366 to the target hue - 1 for right on the mark, 0 for very different */ 00367 Image<float> hueDistance(const Image< PixRGB<byte> >& img, 00368 float muR, float muG, 00369 float sigR, float sigG, float rho); 00370 00371 00372 // ###################################################################### 00373 /* So things look consistent in everyone's emacs... */ 00374 /* Local Variables: */ 00375 /* indent-tabs-mode: nil */ 00376 /* End: */ 00377 00378 #endif // !IMAGE_COLOROPS_H_DEFINED
1.4.4