LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiSplitImageToYUV.h

00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  * 
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public 
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.  
00021  */ 
00022 
00023  
00024 /*--------------------------------------------------------------------
00025  * project ....: LTI-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiSplitImageToYUV.h
00027  * authors ....: Volker Schmirgel, Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 17.12.2002
00030  * revisions ..: $Id: ltiSplitImageToYUV.h,v 1.7 2007/01/05 22:53:33 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_SPLIT_IMAGE_TO_Y_U_V_H_
00034 #define _LTI_SPLIT_IMAGE_TO_Y_U_V_H_
00035 
00036 #include "ltiSplitImage.h"
00037 
00038 namespace lti {
00039   /**
00040    * Computes the YUV values from a given RGB color representation (rgbPixel).
00041    *
00042    * In the literature, technical and scientific, there is a confusion between
00043    * the color spaces YUV, YCrCb and YPbPr.  Poynton in
00044    * http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html explains that
00045    * YUV is usually never correctly meant, because the color space normally
00046    * used for component digital video is the YCrCb (ITU-RS601 or CCIR-601).
00047    * Other devices use the YPbPr, but the "real" YUV is usually not employed.
00048    *
00049    * The LTI-Lib provides all three spaces:
00050    *
00051    * - YCrCb: lti::splitImageToYCbCr used by IEEE 1394 FireWire cameras
00052    * - YPbPr: lti::splitImageToYPbPr used by some WebCams
00053    * - YUV:   lti::splitImageToYUV   did they really meant to use this?
00054    *
00055    * This functor splits an RGB images into the color space YUV as described
00056    * in the Poynton reference given above.
00057    *
00058    * \f[
00059    * \begin{bmatrix}
00060    * Y \\
00061    * U \\
00062    * V
00063    * \end{bmatrix}
00064    * =
00065    * \begin{bmatrix}
00066    *  0.299       &  0.587       &  0.114       \\
00067    * -0.147141189 & -0.288869157 &  0.436010346 \\
00068    *  0.614975383 & -0.514965121 & -0.100010262 
00069    * \end{bmatrix}
00070    * \begin{bmatrix}
00071    * R \\
00072    * G \\
00073    * B
00074    * \end{bmatrix}
00075    * \f]
00076    *
00077    * Here, RGB are values in the intervall [0,1].  Within this range, the
00078    * excursion for Y is also from 0.0 to 1.0, the excursion of U is from -0.436
00079    * to 0.436 and V varies from -0.615 to 0.615.  These ranges are respected in
00080    * the implentation for \c float types (lti::channel). 
00081    *
00082    * If you use \c ubyte (lti::channel8), then the values for U and V are
00083    * linearly mapped from 0 to 1, which results in the mapping
00084    *
00085    * \code
00086    * Y =  0.299*R + 0.587*G + 0.114*B 
00087    * U = -0.169*R - 0.331*G + 0.500*B + 128.0 
00088    * V =  0.500*R - 0.419*G - 0.081*B + 128.0 
00089    * \endcode
00090    *
00091    * The former mapping is equivalent to the color space YPbPr scaled in such a
00092    * way that "black" is mapped to Y=0 and "white" to Y=255, and the Pb and Pr
00093    * channels, which acquire values from -0.5 to 0.5, are linearly mapped to
00094    * the inteval [0,255] as well.  In other words, for \c ubyte operations it
00095    * is equivalent to use this functor or lti::splitImageToYPbPr (which is
00096    * maybe better named as the value ratios are at least kept there).
00097    *
00098    * @ingroup gColor
00099    */
00100   class splitImageToYUV : public splitImage {
00101   public:
00102 
00103     /**
00104      * default constructor
00105      */
00106     splitImageToYUV();
00107 
00108     /**
00109      * copy constructor
00110      * @param other the object to be copied
00111      */
00112     splitImageToYUV(const splitImageToYUV& other);
00113 
00114     /**
00115      * destructor
00116      */
00117     virtual ~splitImageToYUV();
00118 
00119     /**
00120      * returns the name of this type ("splitImageToYUV")
00121      */
00122     virtual const char* getTypeName() const;
00123       
00124     /**
00125      * copy data of "other" functor.
00126      * @param other the functor to be copied
00127      * @return a reference to this functor object
00128      */
00129     splitImageToYUV& copy(const splitImageToYUV& other);
00130 
00131     /**
00132      * alias for copy member
00133      * @param other the functor to be copied
00134      * @return a reference to this functor object
00135      */
00136     splitImageToYUV& operator=(const splitImageToYUV& other);
00137 
00138     /**
00139      * returns a pointer to a clone of this functor.
00140      */
00141     virtual functor* clone() const;
00142 
00143 
00144     /**
00145      *  split pixel into float values (between 0 and 1)
00146      */
00147     inline virtual bool apply(const rgbPixel& pixel,
00148                               float& c1,
00149                               float& c2,
00150                               float& c3) const; 
00151 
00152     /**
00153      * Split pixel into 8-bit values (between 0 and 255)
00154      *
00155      * N.B.: when casting the transformation result to unsigned shorts
00156      * (8-bit channel) major rounding errors will occur.
00157      *
00158      * As a result, the merging operation might produce negative
00159      * values or values > 1, which are truncated subsequently.
00160      *
00161      * When accurate Y, U and V values are required, prefer float values
00162      */
00163     inline virtual bool apply(const rgbPixel& pixel,
00164                               ubyte& c1,
00165                               ubyte& c2,
00166                               ubyte& c3) const;  
00167 
00168     /**
00169      *  split pixel into float channels
00170      */   
00171     virtual bool apply(const image& img,
00172                        channel& c1,
00173                        channel& c2,
00174            channel& c3) const;
00175     
00176     /**
00177      * Split image into 8-bit channels.
00178      *
00179      * N.B.: when casting the transformation result to unsigned shorts
00180      * (8-bit channel) major rounding errors will occur.
00181      *
00182      * As a result, the merging operation might produce negative
00183      * values or values > 1, which are truncated subsequently.  When
00184      * accurate Y, U and V values are required, prefer float values.
00185      */
00186     virtual bool apply(const image& img,
00187                        channel8& c1,
00188                        channel8& c2,
00189            channel8& c3) const;
00190 
00191   };
00192 
00193 
00194   //
00195   // --------------------------------
00196   // implementation of inline methods
00197   // --------------------------------
00198   //
00199 
00200   // split pixel into float values (between 0 and 1)
00201   inline bool splitImageToYUV::apply(const rgbPixel& pixel,
00202                                      float& c1,
00203                                      float& c2,
00204                                      float& c3) const {
00205     
00206     const float red   = static_cast<float>( pixel.getRed() );
00207     const float green = static_cast<float>( pixel.getGreen() );
00208     const float blue  = static_cast<float>( pixel.getBlue() );
00209     
00210     c1 =  red   *  0.299f/255.0f  +
00211           green *  0.587f/255.0f  +
00212           blue  *  0.114f/255.0f;        // Y
00213     c2 =  red   *(-0.147141189f/255.0f) +
00214           green *(-0.288869157f/255.0f) +
00215           blue  *  0.436010346f/255.0f;  // U
00216     c3 =  red   *  0.614975383f/255.0f  +
00217           green *(-0.514965121f/255.0f) +
00218           blue  *(-0.100010262f/255.0f); // V
00219 
00220     return true;
00221   }
00222 
00223   // split pixel into 8-bit values (between 0 and 255)
00224   // N.B.: when casting the transformation result to unsigned shorts
00225   // (8-bit channel) major rounding errors will occur.
00226   // As a result, the merging operation might
00227   // produce negative values or values > 1,  which are truncated subsequently.
00228   // When accurate Y, U and V values are required, prefer float values!
00229   inline bool splitImageToYUV::apply(const rgbPixel& pixel,
00230                                      ubyte& c1,
00231                                      ubyte& c2,
00232                                      ubyte& c3) const {
00233 
00234     const int r = pixel.getRed();
00235     const int g = pixel.getGreen();
00236     const int b = pixel.getBlue();
00237 
00238     // use fixed point arithmetic for faster code
00239 
00240     // The following coefficients are tuned to produce the smallest possible
00241     // error of RGB -> YPbPr -> RGB convertions.  Please DO NOT CHANGE! 
00242    
00243     // The error cannot be further reduced as the ubyte precision looses many
00244     // information when converting RGB->YPbPr.  With the given coefficients
00245     // 3999903 values of all 2^24 available were perfectly retrieved (31.3%),
00246     // an the mean deviation error is 0.761 (RGB color space L2 distance).
00247 
00248     // The values are the fixed point arithmetic with 16 bits decimals.
00249     // The offset 128 is multiplied by 65536, but 32768 is added also
00250     // to force correct rounding.
00251     c1 = static_cast<ubyte>(( 19595*r + 38470*g +  7471*b +   32768)>>16);
00252     c2 = static_cast<ubyte>((-11058*r - 21710*g + 32768*b + 8421376)>>16);
00253     c3 = static_cast<ubyte>(( 32768*r - 27439*g -  5329*b + 8421376)>>16);
00254 
00255     return true;
00256   }
00257 
00258   // ---------------------------------------
00259   // end of implementation of inline methods
00260   // ---------------------------------------
00261 
00262 }
00263 
00264 #endif

Generated on Sat Apr 10 15:26:14 2010 for LTI-Lib by Doxygen 1.6.1