latest version v1.9 - last update 10 Apr 2010 |
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