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

ltiMergeYCbCrToImage.h

00001 /*
00002  * Copyright (C) 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 .......: ltiMergeYCbCrToImage.h
00027  * authors ....: Pablo Alvarado
00028  * organization: Department of Electronics, ITCR
00029  * creation ...: 04.01.2007
00030  * revisions ..: $Id: ltiMergeYCbCrToImage.h,v 1.3 2007/01/05 19:19:56 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_MERGE_Y_Cb_Cr_TO_IMAGE_H_
00034 #define _LTI_MERGE_Y_Cb_Cr_TO_IMAGE_H_
00035 
00036 #include "ltiMergeImage.h"
00037 
00038 namespace lti {
00039 
00040   /**
00041    * Creates RGB values from given YCbCr values by merging float or ubyte
00042    * values to an rgbPixel, merging channels(floats) or channel8s(ubytes) to an
00043    * Image
00044    *
00045    * In the literature, technical and scientific, there is often confusion
00046    * among the color spaces YUV, YCbCr and YPbPr.  Poynton in
00047    * http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html explains that
00048    * YUV is usually never correctly meant, because the color space normally
00049    * used for component digital video is the YCbCr (ITU-RS601 or CCIR-601).
00050    * Other devices use the YPbPr, but the "real" YUV is rarely employed.
00051    *
00052    * The LTI-Lib provides all three spaces:
00053    *
00054    * - YCbCr: lti::mergeYCbCrToImage used by IEEE 1394 FireWire cameras
00055    * - YPbPr: lti::mergeYPbPrToImage used by some WebCams
00056    * - YUV:   lti::mergeYUVToImage   did they really meant to use this?
00057    *
00058    * Here, the inverse transformation of lti::splitImageToYCbCr is followed:
00059    *
00060    * \f[
00061    *   \begin{bmatrix}
00062    *     R \\
00063    *     G \\
00064    *     B
00065    *   \end{bmatrix}
00066    *   =
00067    *   M^{-1}
00068    *   \left(
00069    *     \begin{bmatrix}
00070    *       Y \\
00071    *       Cb \\
00072    *       Cr
00073    *     \end{bmatrix}
00074    *     -
00075    *     \begin{bmatrix}
00076    *       16 \\
00077    *       128 \\
00078    *       128
00079    *     \end{bmatrix}
00080    *   \right)
00081    * \f]
00082    * where M is the matrix given in lti::splitImageToYCbCr.
00083    *
00084    * If you know you have a YCbCr space but it was given to you as
00085    * YUV, then the equivalences are U=Cb and V=Cr.
00086    *
00087    * A way of noticing if you have a YCbCr color space is determining the range
00088    * of the values of each channel.  Y should be in [16,235], while Cr and Cb
00089    * should be in [16,240].  If you channel Y has values in [0,255] then you
00090    * should use mergeYPbPrToImage instead.
00091    *
00092    * @ingroup gColor
00093    */
00094   class mergeYCbCrToImage : public mergeImage {
00095   public:
00096 
00097     /**
00098      * Constructor
00099      */
00100     mergeYCbCrToImage(void);
00101 
00102     
00103     /**
00104      * Destructor
00105      */
00106     ~mergeYCbCrToImage();
00107 
00108     /**
00109      * Return the name of this type
00110      */
00111     virtual const char* getTypeName() const;
00112       
00113     /**
00114      * Copy data of "other" functor.
00115      *
00116      * @param other the functor to be copied
00117      * @return a reference to this functor object
00118      */
00119     mergeYCbCrToImage& copy(const mergeYCbCrToImage& other);
00120     
00121     /**
00122      * Alias for copy method.
00123      *
00124      * @param other the functor to be copied
00125      * @return a reference to this functor object
00126      */
00127     mergeYCbCrToImage& operator=(const mergeYCbCrToImage& other);
00128 
00129     /**
00130      * Returns a pointer to a clone of the functor.
00131      */
00132     virtual functor* clone() const;
00133 
00134     /**
00135      * Merge channels Y, Cr, Cb to an image.
00136      *
00137      * @param Y the Y channel, i.e. black&white
00138      * @param Cb the Cb channel, chromatic 
00139      * @param Cr the Cr channel, chromatic
00140      * @param img the image to be splitted
00141      */
00142     virtual bool apply(const matrix<float>& Y,
00143                        const matrix<float>& Cb,
00144                        const matrix<float>& Cr,
00145                        image& img) const;
00146 
00147     /**
00148      * Merge  8-bit-channels Y, U, V to an image.
00149      *
00150      * @param Y the Y channel, i.e. black&white
00151      * @param Cb the Cb channel, chromatic 
00152      * @param Cr the Cr channel, chromatic
00153      * @param img the image to be splitted
00154      */
00155     virtual bool apply(const channel8& Y,
00156                        const channel8& Cb,
00157                        const channel8& Cr,
00158                        image& img) const;
00159 
00160     /**
00161      * Merge the  values Y, Cr and Cb to a pixel.
00162      * @param Y the Y value, i.e. black&white
00163      * @param Cb the Cb value, chromatic 
00164      * @param Cr the Cr value, chromatic 
00165      * @param pixel the merged pixel
00166      */
00167     inline virtual bool apply(const float& Y,
00168            const float& Cb,
00169            const float& Cr,
00170            rgbPixel& pixel) const;
00171 
00172     /**
00173      * Merge the   8-bit-values Y, U and V to a pixel.
00174      *
00175      * @param Y the Y value, i.e. black&white
00176      * @param Cb the Cb  value, chromatic 
00177      * @param Cr the Cr value, chromatic 
00178      * @param pixel the merged pixel
00179      */ 
00180     inline virtual bool apply(const ubyte& Y,
00181                               const ubyte& Cb,
00182                               const ubyte& Cr,
00183                               rgbPixel& pixel) const;
00184   protected:
00185 
00186     /**
00187      * Initialize the Look-Up-Tables
00188      */
00189     virtual void initializeLUTs();
00190 
00191     /**
00192      * Look up tables to accelerate conversion YUV -> RGB
00193      */
00194     //@{
00195     /**
00196      * Partial Y results
00197      */
00198     static const int* lutY;
00199 
00200     /**
00201      * Partial results with Cr (equivalent to V) for the red channel
00202      * computation.
00203      */
00204     static const int* lutVr;
00205 
00206     /**
00207      * Partial results with Cb (equivalent to U) for the green channel
00208      * computation.
00209      */
00210     static const int* lutUg;
00211 
00212     /**
00213      * Partial results with Cr (equivalent to V) for the green channel
00214      * computation.
00215      */
00216     static const int* lutVg;
00217 
00218     /**
00219      * Partial results with Cb (equivalent to U) for the blue channel
00220      * computation.
00221      */
00222     static const int* lutUb;
00223     //@}
00224 
00225     /**
00226      * Clip function
00227      *
00228      * Equivalent to min(255,max(0,val)) but maybe faster
00229      */
00230     inline ubyte clip(const int val) const;
00231 
00232   };
00233 
00234   //
00235   // -------------------------------------
00236   // Implementation of inline methods
00237   // -------------------------------------
00238   //
00239 
00240   inline ubyte mergeYCbCrToImage::clip(const int val) const {
00241     if (val>255) {
00242       return 255;
00243     }
00244     if (val<0) {
00245       return 0;
00246     }
00247     return static_cast<ubyte>(val);
00248   }
00249 
00250   // create rgbPixel (ubyte)  from YUV float values
00251   inline bool mergeYCbCrToImage::apply(const float& c1,
00252                                        const float& c2,
00253                                        const float& c3,
00254                                        rgbPixel& pixel) const {
00255 
00256     // The values here are chosen to exactly invert the method followed in
00257     // splitImageToYCrBr
00258     static const float offuv = 128.f/255.f;
00259     static const float offY  = 16.f/255.f;
00260 
00261     // The following coefficients are tuned to produce 0% of error of
00262     // RGB -> YCbCr -> RGB convertions.  Please DO NOT CHANGE!
00263 
00264     const float Y = (c1-offY)*296.917808219178f + 0.5f;
00265     const float U = c2-offuv;
00266     const float V = c3-offuv;
00267 
00268     pixel.set(clip(static_cast<int>(Y + V*406.986856270605f)),
00269               clip(static_cast<int>(Y - U*99.8994476850698f 
00270                                       - V*207.306914501362f)),
00271               clip(static_cast<int>(Y + U*514.394323086897f)),
00272               0);
00273 
00274     return true;
00275   }
00276 
00277   // merge 8-bit-values to create an rgbPixel
00278   inline bool mergeYCbCrToImage::apply(const ubyte& c1,
00279                                        const ubyte& c2,
00280                                        const ubyte& c3,
00281                                        rgbPixel& pixel) const {
00282 
00283     // The following coefficients are tuned to produce the smallest possible
00284     // error of RGB -> YCbCr -> RGB convertions.  Please DO NOT CHANGE! 
00285    
00286     // The error cannot be further reduced as the ubyte precision looses many
00287     // information when converting RGB->YCbCr.  With the given coefficients
00288     // 2660449 values of all 2^24 available were perfectly retrieved (18.8%),
00289     // an the mean deviation error is 0.845 (RGB color space L2 distance).
00290 
00291     // the 32768 is half the 16 bit precision and is added to force a correct
00292     // rounding
00293     
00294     // The next lines are 100% equivalent to this, but using LUT, which
00295     // requires approximatelly 85% of the direct computation time.
00296     //
00297     //     const int Y = (static_cast<int>(c1)- 16)*76309 + 32768;
00298     //     const int U = (static_cast<int>(c2)-128);
00299     //     const int V = (static_cast<int>(c3)-128);
00300     
00301     //     pixel.set(clip((Y              + 104597 * V)>>16),
00302     //               clip((Y -  25675 * U -  53279 * V)>>16),
00303     //               clip((Y + 132201 * U             )>>16),
00304     //               0);
00305 
00306     const int Y = lutY[c1];
00307     pixel.set(clip( (Y             + lutVr[c3])>>16),
00308               clip( (Y + lutUg[c2] + lutVg[c3])>>16),
00309               clip( (Y + lutUb[c2]            )>>16),
00310               0);
00311 
00312     return true;
00313   }
00314 }
00315 #endif

Generated on Sat Apr 10 15:25:51 2010 for LTI-Lib by Doxygen 1.6.1