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