00001 /*!@file Image/Pixels.H Basic pixel types version 2.0 */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: T. Nathan Mundhenk <mundhenk@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/Pixels.H $ 00035 // $Id: Pixels.H 12598 2010-01-19 03:03:03Z dberg $ 00036 // 00037 00038 #ifndef PIXELS_H_DEFINED 00039 #define PIXELS_H_DEFINED 00040 00041 #include "Util/MathFunctions.H" 00042 #include "Image/PixelsTypes.H" 00043 #include <cmath> 00044 #include <string> // for string conversions 00045 00046 // ###################################################################### 00047 // ###################################################################### 00048 // FREE FUNCTION PIXEL MATH METHODS 00049 // ###################################################################### 00050 // ###################################################################### 00051 00052 namespace pix_helper 00053 { 00054 typedef double (unary_math_func)(double); 00055 00056 template <class P> 00057 inline P do_unary_func(P pixel, unary_math_func* func) 00058 { 00059 /* We use static_cast to make sure the compiler goes ahead and 00060 figures out how to cast this data type to a double at compile 00061 time. This should be trivial in almost all instances. */ 00062 00063 for (size_t i = 0; i < pixel.myDim; ++i) 00064 pixel.p[i] = 00065 clamped_convert<typename P::ScalarType> 00066 (func(static_cast<double>(pixel.p[i]))); 00067 00068 return pixel; 00069 } 00070 } 00071 00072 #define PIX_FREE_MATH_FUNCTIONS(PIX, TPARAMS) \ 00073 /* ############################################################ */ \ 00074 /* element-wise unary math functions */ \ 00075 template <TPARAMS> inline PIX \ 00076 abs(PIX A) { return pix_helper::do_unary_func(A, &::fabs); } \ 00077 \ 00078 template <TPARAMS> inline PIX \ 00079 sqrt(PIX A) { return pix_helper::do_unary_func(A, &::sqrt); } \ 00080 \ 00081 template <TPARAMS> inline PIX \ 00082 floor(PIX A) { return pix_helper::do_unary_func(A, &::floor); } \ 00083 \ 00084 template <TPARAMS> inline PIX \ 00085 ceil(PIX A) { return pix_helper::do_unary_func(A, &::ceil); } \ 00086 \ 00087 template <TPARAMS> inline PIX \ 00088 round(PIX A) { return pix_helper::do_unary_func(A, &::round); } \ 00089 \ 00090 template <TPARAMS> inline PIX \ 00091 log(const PIX A) { return pix_helper::do_unary_func(A, &::log); } \ 00092 \ 00093 template <TPARAMS> inline PIX \ 00094 log10(PIX A) { return pix_helper::do_unary_func(A, &::log10); } \ 00095 \ 00096 template <TPARAMS> inline PIX \ 00097 exp(PIX A) { return pix_helper::do_unary_func(A, &::exp); } \ 00098 \ 00099 template <TPARAMS> inline PIX \ 00100 erf(PIX A) { return pix_helper::do_unary_func(A, &::erf); } \ 00101 \ 00102 template <TPARAMS> inline PIX \ 00103 erfc(PIX A) { return pix_helper::do_unary_func(A, &::erfc); } \ 00104 \ 00105 template <TPARAMS> inline PIX \ 00106 sign(PIX A) { return pix_helper::do_unary_func(A, &::sign); } \ 00107 \ 00108 /* ############################################################ */ \ 00109 /* element-cumulative unary math functions */ \ 00110 template <TPARAMS> \ 00111 inline T max(PIX A) \ 00112 { \ 00113 T a = A.p[0]; \ 00114 for (size_t i = 1; i < A.myDim; i++) \ 00115 if (A.p[i] > a) a = A.p[i]; \ 00116 \ 00117 return a; \ 00118 } \ 00119 \ 00120 template <TPARAMS> \ 00121 inline T min(PIX A) \ 00122 { \ 00123 T a = A.p[0]; \ 00124 for (size_t i = 1; i < A.myDim; i++) \ 00125 if (A.p[i] < a) a = A.p[i]; \ 00126 \ 00127 return a; \ 00128 } \ 00129 \ 00130 template <TPARAMS> \ 00131 inline bool isFinite(PIX A) \ 00132 { \ 00133 for (size_t i = 0; i < A.myDim; i++) \ 00134 if (!isFinite(A.p[i])) return false; \ 00135 \ 00136 return true; \ 00137 } \ 00138 \ 00139 template <TPARAMS> \ 00140 inline T sum(PIX A) \ 00141 { \ 00142 T sum = 0; \ 00143 for (size_t i = 0; i < A.myDim; i++) \ 00144 sum = A.p[i] + sum; \ 00145 \ 00146 return sum; \ 00147 } \ 00148 \ 00149 template <TPARAMS> \ 00150 inline T mean(PIX A) \ 00151 { \ 00152 T sum = 0; \ 00153 for (size_t i = 0; i < A.myDim; i++) \ 00154 { \ 00155 sum = A.p[i] + sum; \ 00156 } \ 00157 \ 00158 return clamped_convert<T>(sum/double(A.myDim)); \ 00159 } \ 00160 \ 00161 /* ############################################################ */ \ 00162 /* basic trig functions */ \ 00163 template <TPARAMS> inline PIX \ 00164 sin(PIX A) { return pix_helper::do_unary_func(A, &::sin); } \ 00165 \ 00166 template <TPARAMS> inline PIX \ 00167 cos(PIX A) { return pix_helper::do_unary_func(A, &::cos); } \ 00168 \ 00169 template <TPARAMS> inline PIX \ 00170 tan(PIX A) { return pix_helper::do_unary_func(A, &::tan); } \ 00171 \ 00172 template <TPARAMS> inline PIX \ 00173 sec(PIX A) { return pix_helper::do_unary_func(A, &::sec); } \ 00174 \ 00175 template <TPARAMS> inline PIX \ 00176 cosec(PIX A) { return pix_helper::do_unary_func(A, &::cosec); } \ 00177 \ 00178 template <TPARAMS> inline PIX \ 00179 cotan(PIX A) { return pix_helper::do_unary_func(A, &::cotan); } \ 00180 \ 00181 /* ############################################################ */ \ 00182 /* inverse trig functions */ \ 00183 template <TPARAMS> inline PIX \ 00184 asin(PIX A) { return pix_helper::do_unary_func(A, &::asin); } \ 00185 \ 00186 template <TPARAMS> inline PIX \ 00187 acos(PIX A) { return pix_helper::do_unary_func(A, &::acos); } \ 00188 \ 00189 template <TPARAMS> inline PIX \ 00190 atan(PIX A) { return pix_helper::do_unary_func(A, &::atan); } \ 00191 \ 00192 template <TPARAMS> inline PIX \ 00193 asec(PIX A) { return pix_helper::do_unary_func(A, &::asec); } \ 00194 \ 00195 template <TPARAMS> inline PIX \ 00196 acosec(PIX A) { return pix_helper::do_unary_func(A, &::acosec); } \ 00197 \ 00198 template <TPARAMS> inline PIX \ 00199 acotan(PIX A) { return pix_helper::do_unary_func(A, &::acotan); } \ 00200 \ 00201 /* ############################################################ */ \ 00202 /* hyperbolic trig functions */ \ 00203 template <TPARAMS> inline PIX \ 00204 sinh(PIX A) { return pix_helper::do_unary_func(A, &::sinh); } \ 00205 \ 00206 template <TPARAMS> inline PIX \ 00207 cosh(PIX A) { return pix_helper::do_unary_func(A, &::cosh); } \ 00208 \ 00209 template <TPARAMS> inline PIX \ 00210 tanh(PIX A) { return pix_helper::do_unary_func(A, &::tanh); } \ 00211 \ 00212 template <TPARAMS> inline PIX \ 00213 sech(PIX A) { return pix_helper::do_unary_func(A, &::sech); } \ 00214 \ 00215 template <TPARAMS> inline PIX \ 00216 cosech(PIX A) { return pix_helper::do_unary_func(A, &::cosech); } \ 00217 \ 00218 template <TPARAMS> inline PIX \ 00219 cotanh(PIX A) { return pix_helper::do_unary_func(A, &::cotanh); } \ 00220 \ 00221 /* ############################################################ */ \ 00222 /* inverse hyperbolic trig functions */ \ 00223 template <TPARAMS> inline PIX \ 00224 asinh(PIX A) { return pix_helper::do_unary_func(A, &::asinh); } \ 00225 \ 00226 template <TPARAMS> inline PIX \ 00227 acosh(PIX A) { return pix_helper::do_unary_func(A, &::acosh); } \ 00228 \ 00229 template <TPARAMS> inline PIX \ 00230 atanh(PIX A) { return pix_helper::do_unary_func(A, &::atanh); } \ 00231 \ 00232 template <TPARAMS> inline PIX \ 00233 asech(PIX A) { return pix_helper::do_unary_func(A, &::asech); } \ 00234 \ 00235 template <TPARAMS> inline PIX \ 00236 acosech(PIX A) { return pix_helper::do_unary_func(A, &::acosech); } \ 00237 \ 00238 template <TPARAMS> inline PIX \ 00239 acotanh(PIX A) { return pix_helper::do_unary_func(A, &::acotanh); } \ 00240 \ 00241 /* ############################################################ */ \ 00242 /* other binary or ternary math functions */ \ 00243 template <TPARAMS> inline PIX \ 00244 maxmerge(PIX A, const PIX B) \ 00245 { \ 00246 for (size_t i = 0; i < A.myDim; i++) \ 00247 if (A.p[i] < B.p[i]) A.p[i] = B.p[i]; \ 00248 \ 00249 return A; \ 00250 } \ 00251 \ 00252 template <TPARAMS> inline PIX \ 00253 minmerge(PIX A, const PIX B) \ 00254 { \ 00255 for (size_t i = 0; i < A.myDim; i++) \ 00256 if (A.p[i] > B.p[i]) A.p[i] = B.p[i]; \ 00257 \ 00258 return A; \ 00259 } \ 00260 \ 00261 template <TPARAMS> inline PIX \ 00262 pow(PIX A, const T val) \ 00263 { \ 00264 for (size_t i = 0; i < A.myDim; i++) \ 00265 A.p[i] = clamped_convert<T>(pow(A.p[i], val)); \ 00266 \ 00267 return A; \ 00268 } \ 00269 \ 00270 template <TPARAMS> inline PIX \ 00271 pow(PIX A, const PIX B) \ 00272 { \ 00273 for (size_t i = 0; i < A.myDim; i++) \ 00274 A.p[i] = clamped_convert<T>(pow(A.p[i], B.p[i])); \ 00275 \ 00276 return A; \ 00277 } \ 00278 \ 00279 template <TPARAMS> inline PIX \ 00280 rand(PIX A,const int low, const int high) \ 00281 { \ 00282 for (size_t i = 0; i < A.myDim; i++) \ 00283 A.p[i] = clamped_convert<T>(1+(high*rand() \ 00284 /(RAND_MAX+low))); \ 00285 \ 00286 return A; \ 00287 } \ 00288 \ 00289 template <TPARAMS> inline PIX \ 00290 logN(PIX A, const T n) \ 00291 { \ 00292 for (size_t i = 0; i < A.myDim; i++) \ 00293 A.p[i] = logN(A.p[i], n); \ 00294 \ 00295 return A; \ 00296 } \ 00297 \ 00298 template <TPARAMS> inline PIX \ 00299 logsig(PIX A, const T a, const T b) \ 00300 { \ 00301 for (size_t i = 0; i < A.myDim; i++) \ 00302 A.p[i] = logsig(A.p[i], a, b); \ 00303 \ 00304 return A; \ 00305 } \ 00306 \ 00307 template <TPARAMS> inline PIX \ 00308 tansig(PIX A) \ 00309 { \ 00310 for (size_t i = 0; i < A.myDim; i++) \ 00311 A.p[i] = tansig(A.p[i]); \ 00312 \ 00313 return A; \ 00314 } \ 00315 \ 00316 template <TPARAMS> inline PIX \ 00317 saturate(PIX A, const T n) \ 00318 { \ 00319 for (size_t i = 0; i < A.myDim; i++) \ 00320 A.p[i] = saturate(A.p[i], n); \ 00321 \ 00322 return A; \ 00323 } \ 00324 \ 00325 template <TPARAMS> inline PIX \ 00326 poly(PIX A, const T* pn, const size_t n) \ 00327 { \ 00328 PIX B(0); \ 00329 for (size_t i = 0; i < A.myDim; ++i) \ 00330 for (size_t j = 0; j < n; ++j) \ 00331 B.p[i] += clamped_convert<T>(double(pn[j]) * pow(A.p[i],j)); \ 00332 \ 00333 return B; \ 00334 } \ 00335 \ 00336 template <TPARAMS> inline PIX \ 00337 gauss(PIX A, const PIX Mu, const PIX Std) \ 00338 { \ 00339 for (size_t i = 0; i < A.myDim; i++) \ 00340 A.p[i] = gauss(A.p[i], Mu.p[i], Std.p[i]); \ 00341 \ 00342 return A; \ 00343 } \ 00344 \ 00345 template <TPARAMS> inline PIX \ 00346 gauss(PIX A, const T Mu, const T Std) \ 00347 { \ 00348 for (size_t i = 0; i < A.myDim; i++) \ 00349 A.p[i] = gauss(A.p[i], Mu, Std); \ 00350 \ 00351 return A; \ 00352 } 00353 00354 00355 PIX_FREE_MATH_FUNCTIONS(PixRGB<T>, class T) 00356 PIX_FREE_MATH_FUNCTIONS(PixHSV<T>, class T) 00357 PIX_FREE_MATH_FUNCTIONS(PixJpegYUV<T>, class T) 00358 PIX_FREE_MATH_FUNCTIONS(PixVideoYUV<T>, class T) 00359 PIX_FREE_MATH_FUNCTIONS(PixYIQ<T>, class T) 00360 PIX_FREE_MATH_FUNCTIONS(PixH2SV1<T>, class T) 00361 PIX_FREE_MATH_FUNCTIONS(PixH2SV2<T>, class T) 00362 PIX_FREE_MATH_FUNCTIONS(PixH2SV3<T>, class T) 00363 00364 #define LIST_2(p1, p2) p1, p2 00365 PIX_FREE_MATH_FUNCTIONS(PixHyper<LIST_2(T, dim)>, LIST_2(class T, size_t dim)) 00366 #undef LIST_2 00367 00368 #undef PIX_FREE_MATH_FUNCTIONS 00369 00370 00371 //! PixRGB<byte> overload 00372 /*! Format is "<byte>,<byte>,<byte>" for R, G, B */ 00373 std::string convertToString(const PixRGB<byte>& val); 00374 //! PixRGB<byte> overload 00375 /*! Format is "<byte>,<byte>,<byte>" for R, G, B, or "#RRGGBB" with 00376 the RR, GG and BB values in hexadecimal. */ 00377 void convertFromString(const std::string& str, PixRGB<byte>& val); 00378 00379 //! PixHSV<byte> overload 00380 /*! Format is "<byte>,<byte>,<byte>" for H, S, V */ 00381 std::string convertToString(const PixHSV<byte>& val); 00382 //! PixHSV<byte> overload 00383 /*! Format is "<byte>,<byte>,<byte>" for H, S, V */ 00384 void convertFromString(const std::string& str, PixHSV<byte>& val); 00385 00386 //! PixDKL<byte> overload 00387 /*! Format is "<byte>,<byte>,<byte>" for D, K, L */ 00388 std::string convertToString(const PixDKL<byte>& val); 00389 //! PixDKL<byte> overload 00390 /*! Format is "<byte>,<byte>,<byte>" for D, K, L*/ 00391 void convertFromString(const std::string& str, PixDKL<byte>& val); 00392 00393 #endif