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 14762 2011-05-03 01:13:16Z siagian $ 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 //! Get the mean RGB of an Image 00188 template <class T> 00189 PixRGB<float> meanRGB(const Image<PixRGB<T> >& src); 00190 00191 //! Normalize values between nmin and nmax 00192 template <class T, class T2> 00193 inline void normalizeC(Image<PixRGB<T> >& src, const T2 nmin, const T2 nmax) 00194 { 00195 ASSERT(src.initialized()); 00196 T mi, ma; getMinMaxC(src, mi, ma); 00197 const float mif = float(mi); 00198 const float maf = float(ma); 00199 const float scale = maf - mif; 00200 if (scale > -1.0e-20 && scale < 1.0e-20) return; // no need to rescale... 00201 const float nscale = (float(nmax) - float(nmin)) / scale; 00202 00203 typename Image<PixRGB<T> >::iterator aptr = src.beginw(); 00204 typename Image<PixRGB<T> >::iterator stop = src.endw(); 00205 00206 while (aptr != stop) 00207 { 00208 aptr->setRed (nmin+(T2)(((float(aptr->red()))-mif)*nscale)); 00209 aptr->setGreen(nmin+(T2)(((float(aptr->green()))-mif)*nscale)); 00210 aptr->setBlue (nmin+(T2)(((float(aptr->blue()))-mif)*nscale)); 00211 ++aptr; 00212 } 00213 } 00214 00215 //! Compute luminance of a color image 00216 template <class T> 00217 Image<T> luminance(const Image<PixRGB<T> >& src); 00218 00219 //! Compute luminance of a greyscale image (no-op) 00220 /*! This no-op overload is provided so that luminance() can be applied 00221 to template images where it is not known whether the template 00222 argument is scalar or PixRGB. */ 00223 template <class T> 00224 Image<T> luminance(const Image<T>& src); 00225 00226 //! Compute luminance in NTSC coordinates 00227 /*! This version performs the same function as rgb2gray() in matlab */ 00228 template <class T> 00229 Image<T> luminanceNTSC(const Image<PixRGB<T> >& src); 00230 00231 //! Convert grayscale image to RGB 00232 template <class T> 00233 Image< PixRGB<T> > toRGB(const Image<T>& src); 00234 00235 //! Convert RGB image to RGB (no-op) 00236 /*! This no-op function is provided so that toRGB() can be applied to 00237 template images where it is not known whether the template argument 00238 is scalar or PixRGB. */ 00239 template <class T> 00240 Image< PixRGB<T> > toRGB(const Image< PixRGB<T> >& src); 00241 00242 //! Compute color information measure based in infoFFT 00243 template <class T> 00244 Image<float> infoMeasure(const Image<PixRGB<T> >& src, 00245 const float eps, const int size); 00246 00247 //! Get YIQ color components 00248 template <class T> 00249 void getYIQ(const Image<PixRGB<T> >& src, 00250 Image<T>& y, Image<T>& i, Image<T>& q); 00251 00252 //! Get YUV color components from an RGB image 00253 template <class T> 00254 void getJpegYUV(const Image<PixRGB<T> >& src, 00255 Image<T>& y, Image<T>& u, Image<T>& v); 00256 00257 //! Normalize my values by those in the lum image 00258 template <class T> 00259 Image<PixRGB<T> > luminanceNormalize(const Image<PixRGB<T> >& src, 00260 const T thresh); 00261 00262 //! Compute R/G and B/Y channels from a luminanceNormalized color image 00263 /*! This version does automatic promotion on the results, so that 00264 negative values can be represented even if the input is of type 00265 PixRGB<byte> */ 00266 template <class T> 00267 void getRGBY(const Image<PixRGB<T> >& src, 00268 Image<typename promote_trait<T, float>::TP>& rg, 00269 Image<typename promote_trait<T, float>::TP>& by, 00270 const typename promote_trait<T, float>::TP thresh); 00271 00272 //! Compute R/G and B/Y channels in a simpler way 00273 /*! Params are as in getRGBY. The computation for the RG and BY maps 00274 is: RG = (R-G)/max(R,G,B); BY = (B-min(R,G))/max(R,G,B).*/ 00275 template <class T> 00276 void getRGBYsimple(const Image<PixRGB<T> >& src, 00277 Image<typename promote_trait<T, float>::TP>& rg, 00278 Image<typename promote_trait<T, float>::TP>& by, 00279 const typename promote_trait<T, float>::TP thresh); 00280 00281 //! Compute R, G, B, Y channels from a luminanceNormalized color image 00282 /*! This version keeps the four channels separate so that correct 00283 results can be obtained without requiring promotion even if the 00284 input is of type PixRGB<byte> */ 00285 template <class T> 00286 void getRGBY(const Image<PixRGB<T> >& src, Image<T>& r, Image<T>& g, 00287 Image<T>& b, Image<T>& y, const T thresh); 00288 00289 //! Compute R/G and B/Y via computation of H2SV2 color space 00290 /*! In addition to returning R/G and B/Y this basically returns the 00291 full H2SV color space. the original RGB can be obtained later 00292 via conversion of rg,by, sat and val using a PixH2SV2 to RGB 00293 */ 00294 template <class T> 00295 void getRGBY(const Image<PixRGB<T> >& src, Image<T>& rg, Image<T>& by, 00296 Image<T>& sat, Image<T>& val, const ushort H2SVtype = 2); 00297 00298 //! Compute D, K, L color components from an RGB image 00299 /*! The DKL color space is motivated by the neurobiology of early 00300 vision in primates. D is roughly like luminance (with some neutral 00301 grey (RGB=[161 159 154]) at zero, white around 1.0, and black 00302 around -1.0), K roughly like Red-Green, and L roughly like 00303 Blue-Yellow. The images returned here have signed float values 00304 roughly in [-1,1] (but they sometimes are slightly larger that exactly 00305 that, so be sure to clamp if you ar egoing to convert). */ 00306 template <class T> 00307 void getDKL(const Image<PixRGB<T> >& src, 00308 Image<typename promote_trait<T, float>::TP>& dimg, 00309 Image<typename promote_trait<T, float>::TP>& kimg, 00310 Image<typename promote_trait<T, float>::TP>& limg); 00311 00312 //! Compute L, A, B color components from an RGB image 00313 /*! Derived from By Mark Ruzon from C code by Yossi Rubner, 23 September 1997 00314 * A Lab color space is a color-opponent space with dimension L for lightness and 00315 * a and b for the color-opponent dimensions, based on nonlinearly compressed CIE 00316 * XYZ color space coordinates. Lab color is designed to approximate human vision. 00317 * It aspires to perceptual uniformity, and its L component closely matches human 00318 * perception of lightness. It can thus be used to make accurate color balance corrections 00319 * by modifying output curves in the a and b components, or to adjust the lightness 00320 * contrast using the L component. In RGB or CMYK spaces, which model the output of 00321 * physical devices rather than human visual perception, these transformations can 00322 * only be done with the help of appropriate blend modes in the editing application. 00323 */ 00324 template <class T> 00325 void getLAB(const Image<PixRGB<T> >& src, 00326 Image<typename promote_trait<T, float>::TP>& limg, 00327 Image<typename promote_trait<T, float>::TP>& aimg, 00328 Image<typename promote_trait<T, float>::TP>& bimg); 00329 00330 //! normalize the LAB color space to lie in [0.0, 1.0] 00331 //! this is more complex than just calling inplaceNormalize 00332 //! NOTE: we assume that this is called right getLAB 00333 //! separate calls usually are done if user wants both 00334 //! normalized and unnormalized value of the LAB color space 00335 void normalizeLAB(Image<float>& limg, 00336 Image<float>& aimg, 00337 Image<float>& bimg); 00338 00339 //! just call getLAB and normalizeLAB 00340 template <class T> 00341 void getNormalizedLAB(const Image<PixRGB<T> >& src, 00342 Image<typename promote_trait<T, float>::TP>& limg, 00343 Image<typename promote_trait<T, float>::TP>& aimg, 00344 Image<typename promote_trait<T, float>::TP>& bimg); 00345 00346 //! contrast-modulate an RGB image with a mask 00347 Image< PixRGB<byte> > contrastModulate(const Image< PixRGB<byte> >& img, 00348 const Image<float>& mask, 00349 float baseContrast = 0.05, 00350 byte baseBright = 255); 00351 00352 //! Compute peak signal-to-noise ratio between two color images 00353 /*! For color images, pSNR computed from the average 00354 mean-squared-error from the red, green and blue channels */ 00355 template <class T> 00356 double pSNRcolor(const Image< PixRGB<T> >& img1, 00357 const Image< PixRGB<T> >& img2); 00358 00359 //! Compute weighted peak signal-to-noise ratio between two color images 00360 /*! This is like the other pSNRcolor() except that it uses the 00361 weighted version of distance() internally */ 00362 template <class T> 00363 double pSNRcolor(const Image< PixRGB<T> >& img1, 00364 const Image< PixRGB<T> >& img2, 00365 const Image<float>& weight); 00366 00367 //! Normalize each component of the RGB image separately 00368 /*! Normalize the red component with min.red() and max.red() etc.*/ 00369 template <class T> 00370 Image< PixRGB<T> > normalizeRGB(const Image< PixRGB<T> >& img, 00371 PixRGB<T> min, 00372 PixRGB<T> max); 00373 00374 //! Return the pixel-wise maximum of the r, g and b component 00375 template <class T> 00376 Image<T> maxRGB(const Image< PixRGB<T> >& img); 00377 00378 //! Stain a black and white image with a color 00379 /*! @param src the black and white image to be stained 00380 @param min This value will be converted to 0 (black) 00381 @param max This value will be converted to color 00382 @param color The color used for staining */ 00383 template <class T> 00384 Image< PixRGB<T> > colorStain (const Image<T>& src, 00385 const T& min, const T& max, 00386 const PixRGB<T>& color); 00387 00388 //! convert RGB color values into C.I.E. coordinates 00389 /*! @param rgbColor the color to convert from 00390 @param cr returns the R/I value 00391 @param cg returns the G/I value 00392 @param intens returns the intensity */ 00393 void RGBtoCIE(const PixRGB<byte>& rgbColor, 00394 float& cr, float& cg, float& intens); 00395 00396 //! distance between hue of image pixels and a given hue 00397 /*! @param img The color image to compare 00398 @param muR the R/I coordinate of the target hue in the C.I.E. color space 00399 @param muG the G/I coordinate in C.I.E. 00400 @param sigR the standard deviation of a 2D Gaussian in R/I direction 00401 @param sigG the standard deviation of a 2D Gaussian in G/I direction 00402 @param rho the correlation between the R/I and G/I directions 00403 @return a float image coding for how close the hue in img is 00404 to the target hue - 1 for right on the mark, 0 for very different */ 00405 Image<float> hueDistance(const Image< PixRGB<byte> >& img, 00406 float muR, float muG, 00407 float sigR, float sigG, float rho); 00408 00409 00410 // ###################################################################### 00411 /* So things look consistent in everyone's emacs... */ 00412 /* Local Variables: */ 00413 /* indent-tabs-mode: nil */ 00414 /* End: */ 00415 00416 #endif // !IMAGE_COLOROPS_H_DEFINED