last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998-2005 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 00042 /** 00043 * \file cvrChannelC.h 00044 * Contains the data structure to represent complex valued channels 00045 * with float as type for the real and imaginary components. 00046 * \author Pablo Alvarado 00047 * \date 13.10.2007 00048 * 00049 * $Id: cvrChannelC.h,v 1.1 2007/10/14 02:44:14 alvarado Exp $ 00050 */ 00051 00052 #ifndef _CVR_CHANNEL_C_H_ 00053 #define _CVR_CHANNEL_C_H_ 00054 00055 #include "cvrMatrix.h" 00056 #include "cvrChannel.h" 00057 #include "cvrChannelC.h" 00058 #include "cvrComplex.h" 00059 #include "cvrTypes.h" 00060 00061 namespace cvr { 00062 class channel8; 00063 class image; 00064 00065 /** 00066 * Complex channel. 00067 * 00068 * This class is identical to a matrix of cvr::fcomplex except for the 00069 * method castFrom(channel8). 00070 * 00071 * The typical value range is between 0.0f and 1.0f for both, real and 00072 * imaginary components (see cvr::image for more information). 00073 * 00074 * @see cvr::image, cvr::channel8 00075 * 00076 * @ingroup gAggregate 00077 * @ingroup gImageProcessing 00078 */ 00079 class channelC : public matrix< fcomplex > { 00080 public: 00081 00082 /** 00083 * Default constructor creates an empty channel 00084 */ 00085 channelC(); 00086 00087 /** 00088 * Create a connected \c rows x \c cols channel and leave the data 00089 * uninitialized. 00090 * 00091 * @param rows number of rows of the channel 00092 * @param cols number of columns of the channel 00093 */ 00094 channelC(const int rows,const int cols); 00095 00096 /** 00097 * Create a connected \c size.y x \c size.x channel and initializes 00098 * all elements with \a iniValue 00099 * 00100 * @param size cvr::ipoint with the size of the channel 00101 * (size.x is the number of columns and 00102 * size.y the number of rows) 00103 */ 00104 channelC(const ipoint& size); 00105 00106 /** 00107 * Create a connected \c rows x \c cols channel 00108 * and initializes all elements with \a iniValue 00109 * 00110 * @param rows number of rows of the channel 00111 * @param cols number of columns of the channel 00112 * @param iniValue all elements will be initialized with this value 00113 */ 00114 channelC(const int rows,const int cols,const fcomplex& iniValue); 00115 00116 /** 00117 * Create a connected \c size.y x \c size.x channel and initializes 00118 * all elements with \a iniValue 00119 * 00120 * @param size cvr::ipoint with the size of the channel 00121 * (size.x is the number of columns and 00122 * size.y the number of rows) 00123 * @param iniValue all elements will be initialized with this value 00124 */ 00125 channelC(const ipoint& size,const fcomplex& iniValue); 00126 00127 /** 00128 * Create a connected \c rows x \c cols channel and initializes all 00129 * elements with the data ipointed by \a data. The first 00130 * \a cols-elements of the data will be copied on the first row, 00131 * the next ones on the second row and so on. 00132 * 00133 * @param rows number of rows of the channel 00134 * @param cols number of columns of the channel 00135 * @param data pointer to the memory block with the data to be initialized 00136 * with. 00137 */ 00138 channelC(const int rows,const int cols,const fcomplex data[]); 00139 00140 /** 00141 * Copy constructor. 00142 * 00143 * Create a window from another channelC. 00144 * 00145 * @param other the channel to be copied. 00146 * @param fromRow initial row of the other channel to be copied 00147 * @param fromCol initial column of the other channel to be copied 00148 * @param toRow last row to be copied of the other channel 00149 * @param toCol last column to be copied of the other channel 00150 * 00151 * Example: 00152 * \code 00153 * cvr::channelC m(4,6,0); // channel with 24 elements 00154 * // ... 00155 * // initialize channel with: 00156 * // 0 1 2 3 4 5 00157 * // 2 1 5 4 0 3 00158 * // 1 2 1 2 3 2 00159 * // 3 3 2 1 2 3 00160 * 00161 * cvr::channelC sm(m,1,3,0,2) // this line will lead to the 00162 * // following contents for sm: 00163 * // 1 2 3 00164 * // 1 5 4 00165 * // 2 1 2 00166 * \endcode 00167 * 00168 */ 00169 channelC(const channelC& other, 00170 const int fromRow, 00171 const int fromCol=0, 00172 const int toRow=MaxIndex, 00173 const int toCol=MaxIndex); 00174 00175 /** 00176 * Copy constructor. 00177 */ 00178 channelC(const channelC& other); 00179 00180 /** 00181 * Copy constructor. 00182 * 00183 * Create a window from another channel. 00184 * 00185 * @param other the channel to be copied. 00186 * @param from initial coordinates of the window. 00187 * @param to final coordinates of the window. 00188 */ 00189 channelC(const channelC& other, 00190 const ipoint& from, 00191 const ipoint& to); 00192 00193 /** 00194 * Returns the name of this type. 00195 */ 00196 virtual const std::string& name() const; 00197 00198 /** 00199 * Create a clone of this channel 00200 * @return a pointer to a copy of this matrix 00201 */ 00202 virtual channelC* clone() const; 00203 00204 /** 00205 * Create a new empty channel 00206 * @return a pointer to new channel 00207 */ 00208 virtual channelC* newInstance() const; 00209 00210 /** 00211 * Copy the \a other channel8 by casting each of its elements. 00212 * 00213 * The elements of the channel8 will be also multiplied by 1/255. 00214 * 00215 * @param other the channel8 to be casted 00216 * @return a reference to this channel 00217 * 00218 * Example: 00219 * \code 00220 * cvr::channel8 matA(10,10,255); // a channel8 00221 * cvr::channel matB; // a channel 00222 * 00223 * matB.castFrom(matA); // this will copy matA in matB!! 00224 * // and all elements will have 1.0f 00225 * \endcode 00226 */ 00227 channelC& castFrom(const channel8& other); 00228 00229 /** 00230 * Cast the image to an channelC. 00231 * It extracts the intensity channel of the image, defined as 00232 * (R+G+B)/3, where R, G, and B are the red, green and blue components 00233 * of the pixel. 00234 * 00235 * The elements of the resulting channel will be between 0.0f (black) and 00236 * 1.0f (white) for the real part and zero as imaginary part. 00237 * 00238 * @param other the image to be casted 00239 * @return a reference to this channel 00240 */ 00241 channelC& castFrom(const image& other); 00242 00243 /** 00244 * Copy the \a other matrix by casting each of its elements. 00245 * 00246 * @param other The matrix to be casted 00247 * @return a reference to this channel 00248 */ 00249 template<typename U> 00250 inline channelC& castFrom(const matrix<U>& other); 00251 00252 /** 00253 * Extract the real part of each pixel as a channel 00254 */ 00255 void getReal(channel& real) const; 00256 00257 /** 00258 * Extract the imaginary part of each pixel as a channel 00259 */ 00260 void getImag(channel& imag) const; 00261 00262 /** 00263 * Extract the squared magnitude of each pixel. 00264 * 00265 * This method is faster than getAbs() as it avoids taking the square root 00266 * of each pixel. 00267 */ 00268 void getNorm(channel& smag) const; 00269 00270 /** 00271 * Extract the magnitude of each pixel. 00272 * 00273 * This method is slower than getSqrMagnitude() as it has to apply the 00274 * square root to each pixel. 00275 */ 00276 void getAbs(channel& mag) const; 00277 00278 /** 00279 * Extract the argument of each pixel (its angle). 00280 * 00281 * This method is slow as it needs to apply the arctan to each pixel. 00282 * 00283 * For time critical applications, use the getArgumentFast, which makes use 00284 * of the cvr::arctanLUT, but is not as precise as this one. 00285 */ 00286 void getArg(channel& arg) const; 00287 00288 /** 00289 * Extract the argument of each pixel (its angle) in a fast way. 00290 * 00291 * This method requires that both the real and imaginary parts lie within 00292 * the interval [0,1]. 00293 * 00294 * This method makes use of the cvr::arctanLUT to accelerate the 00295 * computation of the angle. If you need very precise angular values, use 00296 * the getArg() method instead. 00297 */ 00298 void getArgFast(channel& arg) const; 00299 00300 /** 00301 * Set the real and imaginary parts from two different channels. 00302 * 00303 * Both channels must have the same size. If they are not, the method 00304 * returns \c false. 00305 */ 00306 bool set(const channel& real,const channel& imag); 00307 00308 /** 00309 * Get the real and imaginary parts as two different channels. 00310 */ 00311 void get(channel& real,channel& imag) const; 00312 00313 /** 00314 * Apply a gray valued transformation which maps the given interval to 00315 * [0.0,1.0] (default) or the explicitly given "destination" interval 00316 * 00317 * @param minVal the lower limit of the original data interval 00318 * @param maxVal the higher limit of the original data interval 00319 * @param minDest the lower limit of the mapped interval (default 0.0f) 00320 * @param maxDest the higher limit of the mapped interval (default 1.0f) 00321 * @return a reference to this object 00322 * 00323 * A linear mapping is applied, where now the slope and offset are complex 00324 * values computed by and analytical extension of the real counterpart. 00325 * 00326 * For example, if you want to map the interval [-1.0f,2.0f] to the "usual" 00327 * interval [0.0,1.0] just use one of following methods: 00328 * 00329 * \code 00330 * cvr::channel chnl; 00331 * // ... 00332 * chnl.mapLinear(-1.0f,2.0f,0.0,1.0); // map [-1,2] to [0,1] 00333 * // this is equivalent to (due to default "destination" interval) 00334 * chnl.mapLinear(-1.0f,2.0f); 00335 * \endcode 00336 * 00337 * Not that you can use this method to "invert" your gray values with 00338 * \code 00339 * chnl.mapLinear(0.0f,1.0f,1,0f,0.0f); // map [0,1] to [1,0] 00340 * // this is equivalent to (due to default "destination" interval) 00341 * chnl.mapLinear(1.0f,0.0f); 00342 * \endcode 00343 * 00344 */ 00345 channelC& mapLinear(const fcomplex& minVal, 00346 const fcomplex& maxVal, 00347 const fcomplex& minDest=0.0f, 00348 const fcomplex& maxDest=1.0f); 00349 00350 00351 /** 00352 * Apply a gray valued transformation which maps the given 00353 * intervall of the other channel into [0.0,1.0] (default) or the 00354 * explicitly given "destination" interval in this channel. 00355 * 00356 * @param other the other channel which values are to be mapped into 00357 * the new interval 00358 * @param minVal the lower limit of the original data interval 00359 * @param maxVal the higher limit of the original data interval 00360 * @param minDest the lower limit of the mapped interval (default 0.0f) 00361 * @param maxDest the higher limit of the mapped interval (default 1.0f) 00362 * @return a reference to this object 00363 * 00364 * For example, if you want to map the interval [-1.0f,2.0f] to 00365 * the "usual" interval [0.0,1.0] just use one of following methods: 00366 * 00367 * \code 00368 * cvr::channel chnl; 00369 * // ... 00370 * chnl.mapLinear(-1.0f,2.0f,0.0,1.0); // map [-1,2] to [0,1] 00371 * // this is equivalent to (due to default "destination" interval) 00372 * chnl.mapLinear(-1.0f,2.0f); 00373 * \endcode 00374 * 00375 * Not that you can use this method to "invert" your gray values with 00376 * \code 00377 * chnl.mapLinear(0.0f,1.0f,1,0f,0.0f); // map [0,1] to [1,0] 00378 * // this is equivalent to (due to default "destination" interval) 00379 * chnl.mapLinear(1.0f,0.0f); 00380 * \endcode 00381 * 00382 */ 00383 template<typename U> 00384 channelC& mapLinear(const matrix<U>& other, 00385 const U& minVal, 00386 const U& maxVal, 00387 const fcomplex& minDest=0.0f, 00388 const fcomplex& maxDest=1.0f); 00389 00390 }; 00391 00392 template<class U> 00393 channelC& channelC::castFrom(const matrix<U>& other) { 00394 matrix<value_type>::castFrom(other); 00395 return *this; 00396 } 00397 00398 /* 00399 * Apply a gray valued transformation which maps the given intervall to 00400 * [0.0,1.0] (default) or the explicitly given "destination" interval 00401 * @param minVal the lower limit of the original data interval 00402 * @param maxVal the higher limit of the original data interval 00403 * @param minDest the lower limit of the mapped interval (default 0.0f) 00404 * @param maxDest the higher limit of the mapped interval (default 1.0f) 00405 * @return a reference to this object 00406 */ 00407 template<class U> 00408 channelC& channelC::mapLinear(const matrix<U>& other, 00409 const U& minVal, const U& maxVal, 00410 const fcomplex& minDest, 00411 const fcomplex& maxDest) { 00412 00413 allocate(other.size()); 00414 00415 iterator it; 00416 typename vector<U>::const_iterator cit,eit; 00417 int y; 00418 00419 fcomplex tm,tb; 00420 00421 if (maxVal != minVal) { 00422 tm = (maxDest-minDest)/static_cast< fcomplex >(maxVal-minVal); 00423 } else { 00424 tm = 1.0f; 00425 } 00426 00427 tb = maxDest-maxVal*tm; 00428 00429 const fcomplex m=tm; 00430 const fcomplex b=tb; 00431 00432 // check possible speed improvements (unnecessary computations avoided) 00433 00434 if (b == 0.0f) { 00435 for (y=0,it=begin();y<other.rows();++y) { 00436 const vector<U>& vct=other.getRow(y); 00437 for (cit=vct.begin(),eit=vct.end();cit!=eit;++cit,++it) { 00438 (*it)=static_cast< fcomplex >((*cit)*m); 00439 } 00440 } 00441 } else if (m == 1.0f) { 00442 for (y=0,it=begin();y<other.rows();++y) { 00443 const vector<U>& vct=other.getRow(y); 00444 for (cit=vct.begin(),eit=vct.end();cit!=eit;++cit,++it) { 00445 (*it)=static_cast< fcomplex >((*cit)+b); 00446 } 00447 } 00448 } else { 00449 for (y=0,it=begin();y<other.rows();++y) { 00450 const vector<U>& vct=other.getRow(y); 00451 for (cit=vct.begin(),eit=vct.end();cit!=eit;++cit,++it) { 00452 (*it)=static_cast< fcomplex >((*cit)*m+b); 00453 } 00454 } 00455 } 00456 return (*this); 00457 } 00458 00459 00460 00461 } 00462 00463 #endif 00464