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

ltiSplitImageToYPbPr.h

00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
00003  * Department of Electronics, ITCR, Costa Rica
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 .......: ltiSplitImageToYPbPr.h
00027  * authors ....: Pablo Alvarado
00028  * organization: Electronics Department, ITCR
00029  * creation ...: 04.01.2007
00030  * revisions ..: $Id: ltiSplitImageToYPbPr.h,v 1.3 2007/01/05 22:53:33 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_SPLIT_IMAGE_TO_Y_Pb_Pr_H_
00034 #define _LTI_SPLIT_IMAGE_TO_Y_Pb_Pr_H_
00035 
00036 #include "ltiSplitImage.h"
00037 
00038 namespace lti {
00039   /**
00040    * Computes the YPbPr values from a given RGB color representation
00041    * (rgbPixel).
00042    *
00043    * In the literature, technical and scientific, there is often confusion
00044    * among the color spaces YUV, YCbCr and YPbPr.  Poynton in
00045    * http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html explains that
00046    * YUV is usually never correctly meant, because the color space normally
00047    * used for component digital video is the YCbCr (ITU-RS601 or CCIR-601).
00048    * Other devices use the YPbPr, but the "real" YUV is rarely employed.
00049    *
00050    * The LTI-Lib provides all three spaces:
00051    *
00052    * - YCbCr: lti::splitImageToYCbCr used by IEEE 1394 FireWire cameras
00053    * - YPbPr: lti::splitImageToYPbPr used by some WebCams
00054    * - YUV:   lti::splitImageToYUV   did they really meant to use this?
00055    *
00056    * This functor splits an RGB images into the color space YPbPr
00057    * using the conversion equations given by the above mentioned reference:
00058    *
00059    * \f[
00060    * \begin{bmatrix}
00061    * Y \\
00062    * Pb \\
00063    * Pr
00064    * \end{bmatrix}
00065    * =
00066    * \begin{bmatrix}
00067    *  0.299    &  0.587    &  0.114   \\
00068    * -0.168736 & -0.331264 &  0.5     \\
00069    *  0.5      & -0.418688 & -0.081312 
00070    * \end{bmatrix}
00071    * \begin{bmatrix}
00072    * R \\
00073    * G \\
00074    * B
00075    * \end{bmatrix}
00076    * \f]
00077    *
00078    * In the formula above, RGB have been assumed to be in the intervall [0,1].
00079    * With it, the Y values will have also be in [0,1], while Pb and Pr will lie
00080    * between [-0.5 and 0.5].  For the ubyte types an offset of 128 is added to
00081    * the Pb and Pr values, which are previously scaled by 255.
00082    *
00083    * @ingroup gColor
00084    */
00085   class splitImageToYPbPr : public splitImage {
00086   public:
00087 
00088     /**
00089      * default constructor
00090      */
00091     splitImageToYPbPr();
00092 
00093     /**
00094      * copy constructor
00095      * @param other the object to be copied
00096      */
00097     splitImageToYPbPr(const splitImageToYPbPr& other);
00098 
00099     /**
00100      * destructor
00101      */
00102     virtual ~splitImageToYPbPr();
00103 
00104     /**
00105      * returns the name of this type ("splitImageToYPbPr")
00106      */
00107     virtual const char* getTypeName() const;
00108       
00109     /**
00110      * copy data of "other" functor.
00111      * @param other the functor to be copied
00112      * @return a reference to this functor object
00113      */
00114     splitImageToYPbPr& copy(const splitImageToYPbPr& other);
00115 
00116     /**
00117      * alias for copy member
00118      * @param other the functor to be copied
00119      * @return a reference to this functor object
00120      */
00121     splitImageToYPbPr& operator=(const splitImageToYPbPr& other);
00122 
00123     /**
00124      * returns a pointer to a clone of this functor.
00125      */
00126     virtual functor* clone() const;
00127 
00128 
00129     /**
00130      *  split pixel into float values (between 0 and 1)
00131      */
00132     inline virtual bool apply(const rgbPixel& pixel,
00133                               float& c1,
00134                               float& c2,
00135                               float& c3) const; 
00136 
00137     /**
00138      * Split pixel into 8-bit values (between 0 and 255)
00139      *
00140      * N.B.: when casting the transformation result to unsigned shorts
00141      * (8-bit channel) major rounding errors will occur.
00142      *
00143      * As a result, the merging operation might produce negative
00144      * values or values > 1, which are truncated subsequently.
00145      *
00146      * When accurate Y, U and V values are required, prefer float values
00147      */
00148     inline virtual bool apply(const rgbPixel& pixel,
00149                               ubyte& c1,
00150                               ubyte& c2,
00151                               ubyte& c3) const;  
00152 
00153     /**
00154      *  split pixel into float channels
00155      */   
00156     virtual bool apply(const image& img,
00157                        channel& c1,
00158                        channel& c2,
00159            channel& c3) const;
00160     
00161     /**
00162      * Split image into 8-bit channels.
00163      *
00164      * N.B.: when casting the transformation result to unsigned shorts
00165      * (8-bit channel) major rounding errors will occur.
00166      *
00167      * As a result, the merging operation might produce negative
00168      * values or values > 1, which are truncated subsequently.  When
00169      * accurate Y, U and V values are required, prefer float values.
00170      */
00171     virtual bool apply(const image& img,
00172                        channel8& c1,
00173                        channel8& c2,
00174            channel8& c3) const;
00175 
00176   };
00177 
00178 
00179   //
00180   // --------------------------------
00181   // implementation of inline methods
00182   // --------------------------------
00183   //
00184 
00185   // split pixel into float values (between 0 and 1)
00186   inline bool splitImageToYPbPr::apply(const rgbPixel& pixel,
00187                                        float& c1,
00188                                        float& c2,
00189                                        float& c3) const {
00190     
00191     const float red   = static_cast<float>( pixel.getRed() );
00192     const float green = static_cast<float>( pixel.getGreen() );
00193     const float blue  = static_cast<float>( pixel.getBlue() );
00194     
00195     c1 =  red   *  0.299f/255.0f  +
00196           green *  0.587f/255.0f  +
00197           blue  *  0.114f/255.0f; // Y
00198     c2 =  red   *(-0.168736f/255.0f) +
00199           green *(-0.331264f/255.0f) +
00200           blue  *  0.5f/255.0f; // U=Pb
00201     c3 =  red   *  0.5f/255.0f  +
00202           green *(-0.418688f/255.0f) +
00203           blue  *(-0.081312f/255.0f); // V=Pr
00204     
00205     return true;
00206   }
00207 
00208   // split pixel into 8-bit values (between 0 and 255)
00209   // N.B.: when casting the transformation result to unsigned shorts
00210   // (8-bit channel) major rounding errors will occur.
00211   // As a result, the merging operation might
00212   // produce negative values or values > 1,  which are truncated subsequently.
00213   // When accurate Y, U and V values are required, prefer float values!
00214   inline bool splitImageToYPbPr::apply(const rgbPixel& pixel,
00215                                        ubyte& c1,
00216                                        ubyte& c2,
00217                                        ubyte& c3) const {
00218     const int r = pixel.getRed();
00219     const int g = pixel.getGreen();
00220     const int b = pixel.getBlue();
00221 
00222     // use fixed point arithmetic for faster code
00223 
00224     // The following coefficients are tuned to produce the smallest possible
00225     // error of RGB -> YPbPr -> RGB convertions.  Please DO NOT CHANGE! 
00226    
00227     // The error cannot be further reduced as the ubyte precision looses many
00228     // information when converting RGB->YPbPr.  With the given coefficients
00229     // 3999903 values of all 2^24 available were perfectly retrieved (31.3%),
00230     // an the mean deviation error is 0.761 (RGB color space L2 distance).
00231 
00232     // The values are the fixed point arithmetic with 16 bits decimals.
00233     // The offset 128 is multiplied by 65536, but 32768 is added also
00234     // to force correct rounding.
00235     c1 = static_cast<ubyte>(( 19595*r + 38470*g +  7471*b + 32768)>>16);
00236     c2 = static_cast<ubyte>((-11058*r - 21710*g + 32768*b + 8421376)>>16);
00237     c3 = static_cast<ubyte>(( 32768*r - 27439*g -  5329*b + 8421376)>>16);
00238 
00239     return true;
00240   }
00241 
00242   // ---------------------------------------
00243   // end of implementation of inline methods
00244   // ---------------------------------------
00245 
00246 }
00247 
00248 #endif

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