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

ltiSplitImageToYCbCr.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 .......: ltiSplitImageToYCbCr.h
00027  * authors ....: Pablo Alvarado
00028  * organization: Electronics Department, ITCR
00029  * creation ...: 04.01.2007
00030  * revisions ..: $Id: ltiSplitImageToYCbCr.h,v 1.3 2007/01/05 19:19:56 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_SPLIT_IMAGE_TO_Y_Cb_Cr_H_
00034 #define _LTI_SPLIT_IMAGE_TO_Y_Cb_Cr_H_
00035 
00036 #include "ltiSplitImage.h"
00037 
00038 namespace lti {
00039   /**
00040    * Computes the YCbCr 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 YCbCr (ITU-RS601)
00057    * using the conversion equations given by the above mentioned reference:
00058    *
00059    * \f[
00060    * \begin{bmatrix}
00061    * Y \\
00062    * Cb \\
00063    * Cr
00064    * \end{bmatrix}
00065    * =
00066    * \begin{bmatrix}
00067    * 16  \\
00068    * 128 \\
00069    * 128
00070    * \end{bmatrix}
00071    * +
00072    * \frac{1}{255}
00073    * \begin{bmatrix}
00074    * 65.481  & 128.553 & 24.966  \\
00075    * -37.797 & -74.203 & 112     \\
00076    * 112     & -93.786 & -18.214 
00077    * \end{bmatrix}
00078    * \begin{bmatrix}
00079    * R \\
00080    * G \\
00081    * B
00082    * \end{bmatrix}
00083    * \f]
00084    *
00085    * Note that the Y values will have an excursion of 219 with an offset of 16,
00086    * while the Cb and Cr values will have an excursion of +/-112 with an offset
00087    * of 128.
00088    *
00089    * The Cb value corresponds to U, and Cr to V, in case you need to provide
00090    * them with "wrong" names.
00091    *
00092    * @ingroup gColor
00093    */
00094   class splitImageToYCbCr : public splitImage {
00095   public:
00096 
00097     /**
00098      * default constructor
00099      */
00100     splitImageToYCbCr();
00101 
00102     /**
00103      * copy constructor
00104      * @param other the object to be copied
00105      */
00106     splitImageToYCbCr(const splitImageToYCbCr& other);
00107 
00108     /**
00109      * destructor
00110      */
00111     virtual ~splitImageToYCbCr();
00112 
00113     /**
00114      * returns the name of this type ("splitImageToYCbCr")
00115      */
00116     virtual const char* getTypeName() const;
00117       
00118     /**
00119      * copy data of "other" functor.
00120      * @param other the functor to be copied
00121      * @return a reference to this functor object
00122      */
00123     splitImageToYCbCr& copy(const splitImageToYCbCr& other);
00124 
00125     /**
00126      * alias for copy member
00127      * @param other the functor to be copied
00128      * @return a reference to this functor object
00129      */
00130     splitImageToYCbCr& operator=(const splitImageToYCbCr& other);
00131 
00132     /**
00133      * returns a pointer to a clone of this functor.
00134      */
00135     virtual functor* clone() const;
00136 
00137 
00138     /**
00139      *  split pixel into float values (between 0 and 1)
00140      */
00141     inline virtual bool apply(const rgbPixel& pixel,
00142                               float& c1,
00143                               float& c2,
00144                               float& c3) const; 
00145 
00146     /**
00147      * Split pixel into 8-bit values (between 0 and 255)
00148      *
00149      * N.B.: when casting the transformation result to unsigned shorts
00150      * (8-bit channel) major rounding errors will occur.
00151      *
00152      * As a result, the merging operation might produce negative
00153      * values or values > 1, which are truncated subsequently.
00154      *
00155      * When accurate Y, U and V values are required, prefer float values
00156      */
00157     inline virtual bool apply(const rgbPixel& pixel,
00158                               ubyte& c1,
00159                               ubyte& c2,
00160                               ubyte& c3) const;  
00161 
00162     /**
00163      *  split pixel into float channels
00164      */   
00165     virtual bool apply(const image& img,
00166                        channel& c1,
00167                        channel& c2,
00168            channel& c3) const;
00169     
00170     /**
00171      * Split image into 8-bit channels.
00172      *
00173      * N.B.: when casting the transformation result to unsigned shorts
00174      * (8-bit channel) major rounding errors will occur.
00175      *
00176      * As a result, the merging operation might produce negative
00177      * values or values > 1, which are truncated subsequently.  When
00178      * accurate Y, U and V values are required, prefer float values.
00179      */
00180     virtual bool apply(const image& img,
00181                        channel8& c1,
00182                        channel8& c2,
00183            channel8& c3) const;
00184 
00185   };
00186 
00187 
00188   //
00189   // --------------------------------
00190   // implementation of inline methods
00191   // --------------------------------
00192   //
00193 
00194   // split pixel into float values (between 0 and 1)
00195   inline bool splitImageToYCbCr::apply(const rgbPixel& pixel,
00196                                        float& c1,
00197                                        float& c2,
00198                                        float& c3) const {
00199     
00200     const float red   = static_cast<float>( pixel.getRed() );
00201     const float green = static_cast<float>( pixel.getGreen() );
00202     const float blue  = static_cast<float>( pixel.getBlue() );
00203     
00204     c1 = (red   *( 0.2567882352941177f/255.0f) +
00205           green *( 0.5041294117647058f/255.0f) +
00206           blue  *( 0.0979058823529412f/255.0f) + 16.f/255.0f); // Y
00207     c2 = (red   *(-0.1482235294117647f/255.0f) +
00208           green *(-0.2909921568627451f/255.0f) +
00209           blue  *( 0.4392156862745098f/255.0f) + 128.f/255.0f); // U=Cb
00210     c3 = (red   *( 0.4392156862745098f/255.0f) +
00211           green *(-0.3677882352941176f/255.0f) +
00212           blue  *(-0.0714274509803921f/255.0f) + 128.f/255.0f); // V=Cr
00213     
00214     return true;
00215   }
00216 
00217   // split pixel into 8-bit values (between 0 and 255)
00218   // N.B.: when casting the transformation result to unsigned shorts
00219   // (8-bit channel) major rounding errors will occur.
00220   // As a result, the merging operation might
00221   // produce negative values or values > 1,  which are truncated subsequently.
00222   // When accurate Y, U and V values are required, prefer float values!
00223   inline bool splitImageToYCbCr::apply(const rgbPixel& pixel,
00224                                        ubyte& c1,
00225                                        ubyte& c2,
00226                                        ubyte& c3) const {
00227     const int r = pixel.getRed();
00228     const int g = pixel.getGreen();
00229     const int b = pixel.getBlue();
00230 
00231     // use fixed point arithmetic for faster code
00232 
00233     // The following coefficients are tuned to produce the smallest possible
00234     // error of RGB -> YCbCr -> RGB convertions.  Please DO NOT CHANGE! 
00235    
00236     // The error cannot be further reduced as the ubyte precision looses many
00237     // information when converting RGB->YCbCr.  With the given coefficients
00238     // 2660449 values of all 2^24 available were perfectly retrieved (18.8%),
00239     // an the mean deviation error is 0.845 (RGB color space L2 distance).
00240 
00241     // The values are the fixed point arithmetic with 16 bits decimals.
00242     // The offsets are 16 or 128 multiplied by 65536, but 32768 is added
00243     // to force correct rounding.
00244     c1 = static_cast<ubyte>((16829*r + 33039*g +  6416*b + 1081344)>>16);
00245     c2 = static_cast<ubyte>((-9714*r - 19070*g + 28784*b + 8421376)>>16);
00246     c3 = static_cast<ubyte>((28784*r - 24103*g -  4681*b + 8421376)>>16);
00247 
00248     return true;
00249   }
00250 
00251   // ---------------------------------------
00252   // end of implementation of inline methods
00253   // ---------------------------------------
00254 
00255 }
00256 
00257 #endif

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