Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/utils.h
Go to the documentation of this file.00001 // -*- c-basic-offset: 4 -*- 00026 #ifndef VIGRA_EXT_UTILS_H 00027 #define VIGRA_EXT_UTILS_H 00028 00029 #include <hugin_math/hugin_math.h> 00030 #include <vigra/rgbvalue.hxx> 00031 #include <vigra/transformimage.hxx> 00032 #include <cmath> 00033 00034 namespace vigra { 00035 00036 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2> 00037 struct PromoteTraits<RGBValue<T1, R, G, B>, T2 > 00038 { 00039 typedef RGBValue<typename PromoteTraits<T1, T2>::Promote> Promote; 00040 }; 00041 00042 } 00043 00044 namespace vigra_ext { 00045 00048 #define LUT_TRAITS(T1,S) \ 00049 template<> \ 00050 struct LUTTraits<T1> \ 00051 { \ 00052 static T1 max() \ 00053 { \ 00054 return S; \ 00055 } \ 00056 }; \ 00057 template<> \ 00058 struct LUTTraits<vigra::RGBValue<T1> > \ 00059 { \ 00060 static T1 max() \ 00061 { \ 00062 return S; \ 00063 } \ 00064 }; 00065 00066 template <class T1> 00067 struct LUTTraits; 00068 00069 LUT_TRAITS(unsigned char, UCHAR_MAX); 00070 LUT_TRAITS(signed char, SCHAR_MAX); 00071 LUT_TRAITS(unsigned short, USHRT_MAX); 00072 LUT_TRAITS(signed short, SHRT_MAX); 00073 LUT_TRAITS(unsigned int, UINT_MAX); 00074 LUT_TRAITS(signed int, INT_MAX); 00075 LUT_TRAITS(float, 1.0); 00076 LUT_TRAITS(double, 1.0); 00077 00078 #undef LUT_TRAITS 00079 00080 inline double getMaxValForPixelType(const std::string & v) 00081 { 00082 if (v == "UINT8") { 00083 return 255; 00084 } else if (v == "INT8") { 00085 return 127; 00086 } else if (v == "UINT16") { 00087 return 65535; 00088 } else if (v == "INT16") { 00089 return 32767; 00090 } else if (v == "UINT32") { 00091 return 4294967295u; 00092 } else if (v == "INT32") { 00093 return 2147483647; 00094 } 00095 return 1.0; 00096 } 00097 00098 template <class VALUE> 00099 struct PointPairT 00100 { 00101 PointPairT() 00102 { 00103 } 00104 00105 PointPairT(short img1, VALUE val1, const hugin_utils::FDiff2D & p1, float r1, 00106 short img2, VALUE val2, const hugin_utils::FDiff2D & p2, float r2) 00107 : imgNr1(img1), i1(val1), p1(p1), r1(r1), imgNr2(img2), i2(val2), p2(p2), r2(r2) 00108 { 00109 } 00110 00111 short imgNr1; 00112 VALUE i1; 00113 hugin_utils::FDiff2D p1; 00114 float r1; 00115 short imgNr2; 00116 VALUE i2; 00117 hugin_utils::FDiff2D p2; 00118 float r2; 00119 }; 00120 00121 typedef PointPairT<float> PointPair; 00122 typedef PointPairT<vigra::RGBValue<float> > PointPairRGB; 00123 00124 00125 00126 // get the value_type of vector pixels and also single channel pixels. 00127 #define VT_TRAITS_VEC(T1) \ 00128 template<> \ 00129 struct ValueTypeTraits<vigra::RGBValue<T1, 0u, 1u, 2u> > \ 00130 { \ 00131 typedef vigra::RGBValue<T1, 0u, 1u, 2u>::value_type value_type; \ 00132 }; 00133 00134 #define VT_TRAITS(T1) \ 00135 template<> \ 00136 struct ValueTypeTraits<T1> \ 00137 { \ 00138 typedef T1 value_type; \ 00139 }; 00140 00141 template <class T1> 00142 struct ValueTypeTraits 00143 { 00144 typedef typename T1::value_type value_type; 00145 }; 00146 00147 #if 0 00148 VT_TRAITS_VEC(vigra::UInt8); 00149 VT_TRAITS_VEC(vigra::Int16); 00150 VT_TRAITS_VEC(vigra::UInt16); 00151 VT_TRAITS_VEC(vigra::Int32); 00152 VT_TRAITS_VEC(vigra::UInt32); 00153 VT_TRAITS_VEC(float); 00154 VT_TRAITS_VEC(double); 00155 #endif 00156 00157 VT_TRAITS(vigra::UInt8); 00158 VT_TRAITS(vigra::Int16); 00159 VT_TRAITS(vigra::UInt16); 00160 VT_TRAITS(vigra::Int32); 00161 VT_TRAITS(vigra::UInt32); 00162 VT_TRAITS(float); 00163 VT_TRAITS(double); 00164 00165 #undef VT_TRAITS 00166 #undef VT_TRAITS_VEC 00167 00168 00169 using VIGRA_CSTD::pow; 00170 using VIGRA_CSTD::log; 00171 00172 inline float pow(float a, double b) 00173 { 00174 return std::pow(a,(float) b); 00175 } 00176 00178 template <class T, unsigned int R, unsigned int G, unsigned int B> 00179 inline 00180 vigra::RGBValue<T, R, G, B> pow(vigra::RGBValue<T, R, G, B> const & v, double e) { 00181 return vigra::RGBValue<T, R, G, B>(pow(v.red(),e), pow(v.green(),e), pow(v.blue(),e)); 00182 } 00183 00185 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2> 00186 inline 00187 vigra::RGBValue<V1, R, G, B> & 00188 operator+=(vigra::RGBValue<V1, R, G, B> & l, V2 const & r) 00189 { 00190 l.red() += r; 00191 l.green() += r; 00192 l.blue() += r; 00193 return l; 00194 } 00195 00197 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00198 inline 00199 vigra::RGBValue<T, RIDX, GIDX, BIDX> 00200 log(vigra::RGBValue<T, RIDX, GIDX, BIDX> const & v) 00201 { 00202 return vigra::RGBValue<T, RIDX, GIDX, BIDX>(std::log(v.red()), std::log(v.green()), std::log(v.blue())); 00203 } 00204 00206 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00207 inline 00208 vigra::RGBValue<T, RIDX, GIDX, BIDX> 00209 log10(vigra::RGBValue<T, RIDX, GIDX, BIDX> const & v) 00210 { 00211 return vigra::RGBValue<T, RIDX, GIDX, BIDX>(std::log10(v.red()), std::log10(v.green()), std::log10(v.blue())); 00212 } 00213 00215 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2> 00216 inline 00217 // WARNING: This is a hack.. 00218 //vigra::RGBValue<V1> 00219 typename vigra::PromoteTraits<vigra::RGBValue<V1, R, G, B>, V2 >::Promote 00220 operator+(vigra::RGBValue<V1, R, G, B> const & r1, V2 const & r2) 00221 { 00222 typename vigra::PromoteTraits<vigra::RGBValue<V1, R, G, B>, V2 >::Promote res(r1); 00223 00224 res += r2; 00225 00226 return res; 00227 } 00228 00231 template <class V, int SIZE, class D1, class D2> 00232 inline 00233 vigra::TinyVector<V, SIZE> 00234 pow(vigra::TinyVector<V, SIZE> const & v, double e) 00235 { 00236 vigra::TinyVector<V, SIZE> res; 00237 for (int i=0; i<SIZE; i++) 00238 res[i] = std::pow(v[i], e); 00239 return res; 00240 } 00241 00244 template <class V, int SIZE, class D1, class D2> 00245 inline 00246 vigra::TinyVector<V, SIZE> 00247 log(vigra::TinyVector<V, SIZE> const & v, double e) 00248 { 00249 vigra::TinyVector<V, SIZE> res; 00250 for (int i=0; i<SIZE; i++) 00251 res[i] = std::log(v[i], e); 00252 return res; 00253 } 00254 00256 template <class V> 00257 inline 00258 V 00259 getMaxComponent(vigra::RGBValue<V> const & v) 00260 { 00261 return std::max(std::max(v.red(), v.green()), v.blue()); 00262 } 00263 00265 template <class V> 00266 inline 00267 V 00268 getMaxComponent(V v) 00269 { 00270 return v; 00271 } 00272 00274 template <class V> 00275 inline 00276 V 00277 getMinComponent(vigra::RGBValue<V> const & v) 00278 { 00279 return std::max(std::max(v.red(), v.green()), v.blue()); 00280 } 00281 00283 template <class V> 00284 inline 00285 V 00286 getMinComponent(V v) 00287 { 00288 return v; 00289 } 00290 00291 00293 struct OverlapSizeCounter 00294 { 00295 OverlapSizeCounter() 00296 : size(0) 00297 { } 00298 00299 template<typename PIXEL> 00300 void operator()(PIXEL const & img1, PIXEL const & img2) 00301 { 00302 if (img1 > 0 && img2 > 0) { 00303 size++; 00304 } 00305 } 00306 00307 unsigned int getSize() 00308 { 00309 return size; 00310 } 00311 00312 unsigned int size; 00313 }; 00314 00315 00323 template <class F1, class F2> 00324 struct NestFunctor 00325 { 00326 F1 f1; 00327 F2 f2; 00328 NestFunctor(const F1 & fu1, const F2 & fu2) 00329 : f1(fu1), f2(fu2) 00330 { } 00331 00334 typedef typename F1::result_type result_type; 00335 00336 template <class T1> 00337 result_type operator()(T1 const & v) const 00338 { 00339 return f1(f2(v)); 00340 } 00341 00343 template <class T1, class T2> 00344 result_type operator()(T1 const & v1, T2 const & v2) const 00345 { 00346 return f1(f2(v1,v2)); 00347 } 00348 00350 template <class T1, class T2, class T3> 00351 result_type operator()(T1 const & v1, T2 const & v2, T3 const & v3) const 00352 { 00353 return f1(f2(v1,v2,v3)); 00354 } 00355 }; 00356 00357 00359 struct MaskPixelCounter 00360 { 00361 MaskPixelCounter() 00362 : count(0) 00363 { } 00364 00365 template<typename PIXEL> 00366 void operator()(PIXEL const & img1) 00367 { 00368 if (img1 > 0) { 00369 count++; 00370 } 00371 } 00372 00373 int getCount() 00374 { 00375 return count; 00376 } 00377 00378 int count; 00379 }; 00380 00387 template <class SrcImageIterator, class SrcAccessor> 00388 void circularCrop(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img, 00389 hugin_utils::FDiff2D middle, double radius) 00390 { 00391 vigra::Diff2D imgSize = img.second - img.first; 00392 double r2 = radius*radius; 00393 00394 // create dest y iterator 00395 SrcImageIterator yd(img.first); 00396 // loop over the image and transform 00397 for(int y=0; y < imgSize.y; ++y, ++yd.y) 00398 { 00399 // create x iterators 00400 SrcImageIterator xd(yd); 00401 for(int x=0; x < imgSize.x; ++x, ++xd.x) 00402 { 00403 double dx = x-middle.x; 00404 double dy = y-middle.y; 00405 if (dx*dx+dy*dy > r2) { 00406 *xd = 0; 00407 } 00408 } 00409 } 00410 } 00411 00413 template <class T> 00414 struct PassThroughFunctor 00415 { 00416 typedef T result_type; 00417 00418 T operator()(const T & a) const 00419 { 00420 return a; 00421 } 00422 00423 template <class T2> 00424 T2 operator()(const T2 & a, const hugin_utils::FDiff2D & p) const 00425 { 00426 return a; 00427 } 00428 00429 template <class T2, class A> 00430 A 00431 hdrWeight(T2 v, A a) const 00432 { 00433 return a; 00434 } 00435 00436 }; 00437 00438 00442 template <class T> 00443 typename vigra::NumericTraits<T>::RealPromote 00444 normalizeValue(T v, vigra::VigraTrueType) 00445 { 00446 return vigra::NumericTraits<T>::toRealPromote(v) / vigra::NumericTraits<T>::max(); 00447 } 00448 00449 template <class T> 00450 typename vigra::NumericTraits<T>::RealPromote 00451 normalizeValue(T v, vigra::VigraFalseType) 00452 { 00453 return v; 00454 } 00455 00456 00457 00458 template <class DestValueType> 00459 struct LinearTransform 00460 { 00461 public: 00462 /* the functors argument type (actually, since 00463 <tt>operator()</tt> is a template, much more types are possible) 00464 */ 00465 typedef DestValueType argument_type; 00466 00467 /* the functors result type 00468 */ 00469 typedef DestValueType result_type; 00470 00471 /* init scale and offset 00472 */ 00473 LinearTransform(float scale, float offset) 00474 : scale_(scale), offset_(offset) 00475 {} 00476 template <class SrcValueType> 00477 result_type operator()(SrcValueType const & s) const 00478 { 00479 return vigra::NumericTraits<result_type>::fromRealPromote(scale_ * (vigra::NumericTraits<SrcValueType>::toRealPromote(s) + offset_)); 00480 } 00481 private: 00482 00483 float scale_; 00484 float offset_; 00485 }; 00486 00487 00488 struct ApplyLogFunctor 00489 { 00490 float minv; 00491 float maxv; 00492 float scale; 00493 00494 ApplyLogFunctor(float min_, float max_) 00495 { 00496 // protect against zeros in image data 00497 if (min_ == 0.0f) { 00498 min_ = 1e-5; 00499 } 00500 minv = std::log10(min_); 00501 maxv = std::log10(max_); 00502 scale = (maxv - minv)/255; 00503 } 00504 00505 template <class T> 00506 unsigned char operator()(T v) const 00507 { 00508 typedef vigra::NumericTraits<vigra::UInt8> DestTraits; 00509 return DestTraits::fromRealPromote((std::log10(float(v))-minv)/scale); 00510 } 00511 00512 template <class T, unsigned int R, unsigned int G, unsigned int B> 00513 vigra::RGBValue<vigra::UInt8,0,1,2> operator()(const vigra::RGBValue<T,R,G,B> & v) const 00514 { 00515 typedef vigra::NumericTraits< vigra::RGBValue<vigra::UInt8,0,1,2> > DestTraits; 00516 typedef vigra::NumericTraits< vigra::RGBValue<T,R,G,B> > SrcTraits; 00517 return DestTraits::fromRealPromote((log10(SrcTraits::toRealPromote(v)) + (-minv))/scale); 00518 } 00519 }; 00520 00521 00522 template <class TIn, class TOut=vigra::UInt8> 00523 struct ApplyGammaFunctor 00524 { 00525 float minv; 00526 float maxv; 00527 float gamma; 00528 float scale; 00529 00530 ApplyGammaFunctor(TIn min_, TIn max_, float gamma_) 00531 { 00532 minv = min_; 00533 maxv = max_; 00534 gamma = gamma_; 00535 scale = float(maxv) - minv; 00536 } 00537 00538 TOut operator()(TIn v) const 00539 { 00540 typedef vigra::NumericTraits<TOut> DestTraits; 00541 return DestTraits::fromRealPromote(pow((float(v)-minv)/scale, gamma)*255); 00542 } 00543 00544 vigra::RGBValue<TOut> operator()(const vigra::RGBValue<TIn> & v) const 00545 { 00546 typedef vigra::NumericTraits< vigra::RGBValue<TOut> > DestTraits; 00547 typedef vigra::NumericTraits< vigra::RGBValue<TIn> > SrcTraits; 00548 return DestTraits::fromRealPromote(pow((SrcTraits::toRealPromote(v)+(-minv))/scale, gamma)*255); 00549 } 00550 }; 00551 00552 // gamma correction with lookup table 00553 template <> 00554 struct ApplyGammaFunctor<vigra::UInt16, vigra::UInt8> 00555 { 00556 vigra::UInt8 lut[65536]; 00557 00558 ApplyGammaFunctor(vigra::UInt16 min, vigra::UInt16 max, float gamma) 00559 { 00560 float scale = float(max) - min; 00561 for (int i=0; i<65536; i++) { 00562 lut[i] = hugin_utils::roundi(pow((float(i)-min)/scale, gamma)*255); 00563 } 00564 } 00565 00566 vigra::UInt8 operator()(vigra::UInt16 v) const 00567 { 00568 return lut[v]; 00569 } 00570 00571 vigra::RGBValue<vigra::UInt8> operator()(const vigra::RGBValue<vigra::UInt16> & v) const 00572 { 00573 return vigra::RGBValue<vigra::UInt8>(lut[v[0]], lut[v[1]], lut[v[2]]); 00574 } 00575 }; 00576 00577 template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor, class T> 00578 void applyMapping(vigra::triple<SrcIterator, SrcIterator, SrcAccessor> img, 00579 vigra::pair<DestIterator, DestAccessor> dest, T min, T max, int mapping ) 00580 { 00581 00582 switch (mapping) 00583 { 00584 case 0: 00585 { 00586 // linear 00587 float offset_ = -float(min); 00588 float scale_ = 255/float(max)-float(min); 00589 vigra::transformImage(img, dest, 00590 LinearTransform<typename DestAccessor::value_type>( scale_, offset_) 00591 ); 00592 break; 00593 } 00594 case 1: 00595 { 00596 // log 00597 ApplyLogFunctor logfunc(min, max); 00598 transformImage(img, dest, 00599 logfunc); 00600 break; 00601 } 00602 case 2: 00603 { 00604 // gamma 00605 ApplyGammaFunctor<T> logfunc(min, max, 1/2.2f); 00606 transformImage(img, dest, 00607 logfunc); 00608 break; 00609 } 00610 default: 00611 vigra_fail("Unknown image mapping mode"); 00612 } 00613 } 00614 00615 template <class SrcImageIterator, class SrcAccessor, 00616 class DestImageIterator, class DestAccessor, class Functor> 00617 void 00618 transformImageSpatial(SrcImageIterator src_upperleft, 00619 SrcImageIterator src_lowerright, SrcAccessor sa, 00620 DestImageIterator dest_upperleft, DestAccessor da, 00621 Functor const & f, vigra::Diff2D ul) 00622 { 00623 vigra::Diff2D destSize = src_lowerright - src_upperleft; 00624 00625 for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y, ++ul.y) 00626 { 00627 typename SrcImageIterator::row_iterator s(src_upperleft.rowIterator()); 00628 typename SrcImageIterator::row_iterator send(s+ destSize.x); 00629 typename DestImageIterator::row_iterator d(dest_upperleft.rowIterator()); 00630 for(; s != send; ++s, ++d, ++ul.x) { 00631 da.set(f(sa(s), ul), d); 00632 } 00633 } 00634 } 00635 00636 template <class SrcImageIterator, class SrcAccessor, 00637 class DestImageIterator, class DestAccessor, class Functor> 00638 void 00639 transformImageSpatial(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, 00640 vigra::pair<DestImageIterator, DestAccessor> dest, 00641 Functor const & f, vigra::Diff2D ul) 00642 { 00643 transformImageSpatial(src.first, src.second, src.third, dest.first, dest.second, f, ul); 00644 } 00645 00646 00647 } // namespace 00648 00649 #endif // VIGRA_EXT_UTILS_H
1.3.9.1