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