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

ltiMergeYPbPrToImage.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 .......: ltiMergeYPbPrToImage.h
00027  * authors ....: Pablo Alvarado
00028  * organization: Department of Electronics, ITCR
00029  * creation ...: 04.01.2007
00030  * revisions ..: $Id: ltiMergeYPbPrToImage.h,v 1.3 2007/01/10 02:25:58 alvarado Exp $
00031  */
00032 
00033 #ifndef _LTI_MERGE_Y_Pb_Pr_TO_IMAGE_H_
00034 #define _LTI_MERGE_Y_Pb_Pr_TO_IMAGE_H_
00035 
00036 #include "ltiMergeImage.h"
00037 
00038 namespace lti {
00039 
00040   /**
00041    * Creates RGB values from given YPbPr 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, YPbPr 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::splitImageToYPbPr is followed:
00059    *
00060    * \f[
00061    *   \begin{bmatrix}
00062    *     R \\
00063    *     G \\
00064    *     B
00065    *   \end{bmatrix}
00066    *   =
00067    *   M^{-1}
00068    *   \begin{bmatrix}
00069    *     Y \\
00070    *     Pb \\
00071    *     Pr
00072    *   \end{bmatrix}
00073    * \f]
00074    * where M is the matrix given in lti::splitImageToYPbPr.
00075    *
00076    * If you know you have a YPbPr space but it was given to you as
00077    * YUV, then the equivalences are U=Pb and V=Pr.
00078    *
00079    * A way of noticing if you have a YPbPr color space is determining the range
00080    * of the values of each channel.  Y should be in [0,1], while Pr and Pb
00081    * should be in [-0.5,0.5].
00082    *
00083    * @ingroup gColor
00084    */
00085   class mergeYPbPrToImage : public mergeImage {
00086   public:
00087 
00088     /**
00089      * Constructor
00090      */
00091     mergeYPbPrToImage(void);
00092 
00093     
00094     /**
00095      * Destructor
00096      */
00097     ~mergeYPbPrToImage();
00098 
00099     /**
00100      * Return the name of this type
00101      */
00102     virtual const char* getTypeName() const;
00103       
00104     /**
00105      * Copy data of "other" functor.
00106      *
00107      * @param other the functor to be copied
00108      * @return a reference to this functor object
00109      */
00110     mergeYPbPrToImage& copy(const mergeYPbPrToImage& other);
00111     
00112     /**
00113      * Alias for copy method.
00114      *
00115      * @param other the functor to be copied
00116      * @return a reference to this functor object
00117      */
00118     mergeYPbPrToImage& operator=(const mergeYPbPrToImage& other);
00119 
00120     /**
00121      * Returns a pointer to a clone of the functor.
00122      */
00123     virtual functor* clone() const;
00124 
00125     /**
00126      * Merge channels Y, Pb, Pr to an image.
00127      *
00128      * @param Y the Y channel, i.e. black&white
00129      * @param Pb the Pb channel, chromatic 
00130      * @param Pr the Pr channel, chromatic
00131      * @param img the image to be splitted
00132      */
00133     virtual bool apply(const matrix<float>& Y,
00134                        const matrix<float>& Pb,
00135                        const matrix<float>& Pr,
00136                        image& img) const;
00137 
00138     /**
00139      * Merge  8-bit-channels Y, Pb, Pr to an image.
00140      *
00141      * @param Y the Y channel, i.e. black&white
00142      * @param Pb the Pb channel, chromatic 
00143      * @param Pr the Pr channel, chromatic
00144      * @param img the image to be splitted
00145      */
00146     virtual bool apply(const channel8& Y,
00147                        const channel8& Pb,
00148                        const channel8& Pr,
00149                        image& img) const;
00150 
00151     /**
00152      * Merge the  values Y, Pb and Pr to a pixel.
00153      * @param Y the Y value, i.e. black&white
00154      * @param Pb the Pb value, chromatic 
00155      * @param Pr the Pr value, chromatic 
00156      * @param pixel the merged pixel
00157      */
00158     inline virtual bool apply(const float& Y,
00159            const float& Pb,
00160            const float& Pr,
00161            rgbPixel& pixel) const;
00162 
00163     /**
00164      * Merge the   8-bit-values Y, Pb and Pr to a pixel.
00165      *
00166      * @param Y the Y value, i.e. black&white
00167      * @param Pb the Pb  value, chromatic 
00168      * @param Pr the Pr value, chromatic 
00169      * @param pixel the merged pixel
00170      */ 
00171     inline virtual bool apply(const ubyte& Y,
00172                               const ubyte& Pb,
00173                               const ubyte& Pr,
00174                               rgbPixel& pixel) const;
00175 
00176     /*
00177      * Merge the   8-bit-values Y, Pb and Pr to a pixel.
00178      *
00179      * This is a static method to do the conversion.  It is required by
00180      * other functors which need a fast access to the conversion without
00181      * requiring an instance.
00182      *
00183      * \waring Be careful while using this method, since its static nature
00184      * makes you responsible for the previous initialization of the LUTs.  For
00185      * that matter, just make sure that any instance of mergeYPbPrToImage is
00186      * created before calling this method.
00187      *
00188      * @param Y the Y value, i.e. black&white
00189      * @param Pb the Pb  value, chromatic 
00190      * @param Pr the Pr value, chromatic 
00191      * @param pixel the merged pixel
00192      */ 
00193     static bool convert(const ubyte& Y,
00194                         const ubyte& Pb,
00195                         const ubyte& Pr,
00196                         rgbPixel& pixel);
00197     
00198   protected:
00199 
00200     /**
00201      * Initialize the Look-Up-Tables
00202      */
00203     virtual void initializeLUTs();
00204 
00205     /**
00206      * Look up tables to accelerate conversion YPbPr -> RGB
00207      */
00208     //@{
00209     /**
00210      * Partial Y results
00211      */
00212     static const int* lutY;
00213 
00214     /**
00215      * Partial results with Pr (equivalent to V) for the red channel
00216      * computation.
00217      */
00218     static const int* lutVr;
00219 
00220     /**
00221      * Partial results with Pb (equivalent to U) for the green channel
00222      * computation.
00223      */
00224     static const int* lutUg;
00225 
00226     /**
00227      * Partial results with Pr (equivalent to V) for the green channel
00228      * computation.
00229      */
00230     static const int* lutVg;
00231 
00232     /**
00233      * Partial results with Pb (equivalent to U) for the blue channel
00234      * computation.
00235      */
00236     static const int* lutUb;
00237     //@}
00238 
00239     /**
00240      * Clip function
00241      *
00242      * Equivalent to min(255,max(0,val)) but maybe faster
00243      */
00244     inline static ubyte clip(const int val);
00245 
00246   };
00247 
00248   //
00249   // -------------------------------------
00250   // Implementation of inline methods
00251   // -------------------------------------
00252   //
00253 
00254   inline ubyte mergeYPbPrToImage::clip(const int val) {
00255     if (val>255) {
00256       return 255;
00257     }
00258     if (val<0) {
00259       return 0;
00260     }
00261     return static_cast<ubyte>(val);
00262   }
00263 
00264   // create rgbPixel (ubyte)  from YUV float values
00265   inline bool mergeYPbPrToImage::apply(const float& c1,
00266                                        const float& c2,
00267                                        const float& c3,
00268                                        rgbPixel& pixel) const {
00269 
00270     // The following coefficients are tuned to produce 0% of error of
00271     // RGB -> YPbPr -> RGB convertions.  Please DO NOT CHANGE!
00272     const float Y = c1*255.f + 0.5f;
00273 
00274     pixel.set(clip(static_cast<int>(Y + c3*357.509895107622f)),
00275               clip(static_cast<int>(Y - c2* 87.7545979321608f 
00276                                       - c3*182.104719673362f)),
00277               clip(static_cast<int>(Y + c2*451.860016848823f)),
00278               0);
00279 
00280     return true;
00281   }
00282 
00283   // merge 8-bit-values to create an rgbPixel
00284   inline bool mergeYPbPrToImage::convert(const ubyte& c1,
00285                                          const ubyte& c2,
00286                                          const ubyte& c3,
00287                                          rgbPixel& pixel) {
00288 
00289     // The following coefficients are tuned to produce the smallest possible
00290     // error of RGB -> YPbPr -> RGB convertions.  Please DO NOT CHANGE! 
00291    
00292     // The error cannot be further reduced as the ubyte precision looses many
00293     // information when converting RGB->YPbPr.  With the given coefficients
00294     // 3999903 values of all 2^24 available were perfectly retrieved (31.3%),
00295     // an the mean deviation error is 0.761 (RGB color space L2 distance).
00296 
00297     // The 32768 is half the 16 bit precision and is added to force a correct
00298     // rounding.
00299     
00300     // The next lines are 100% equivalent to this, but using LUT, which
00301     // requires approximatelly 85% of the direct computation time.
00302     //
00303     //     const int Y =  static_cast<int>(c1)*65536 + 32768;
00304     //     const int U = (static_cast<int>(c2)-128);
00305     //     const int V = (static_cast<int>(c3)-128);
00306     
00307     //     pixel.set(clip((Y              +  91881 * V)>>16),
00308     //               clip((Y -  22553 * U -  46802 * V)>>16),
00309     //               clip((Y + 116130 * U             )>>16),
00310     //               0);
00311 
00312     const int Y = lutY[c1];
00313     pixel.set(clip( (Y             + lutVr[c3])>>16),
00314               clip( (Y + lutUg[c2] + lutVg[c3])>>16),
00315               clip( (Y + lutUb[c2]            )>>16),
00316               0);
00317 
00318     return true;
00319   }
00320 
00321   // merge 8-bit-values to create an rgbPixel
00322   inline bool mergeYPbPrToImage::apply(const ubyte& c1,
00323                                        const ubyte& c2,
00324                                        const ubyte& c3,
00325                                        rgbPixel& pixel) const {
00326     // alias for convert, so just call it
00327     return convert(c1,c2,c3,pixel);
00328   }
00329 }
00330 #endif

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