00001
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
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
00218
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
00395 SrcImageIterator yd(img.first);
00396
00397 for(int y=0; y < imgSize.y; ++y, ++yd.y)
00398 {
00399
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
00463
00464
00465 typedef DestValueType argument_type;
00466
00467
00468
00469 typedef DestValueType result_type;
00470
00471
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
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
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
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
00597 ApplyLogFunctor logfunc(min, max);
00598 transformImage(img, dest,
00599 logfunc);
00600 break;
00601 }
00602 case 2:
00603 {
00604
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 int offsetX=ul.x;
00626 for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y, ++ul.y)
00627 {
00628 typename SrcImageIterator::row_iterator s(src_upperleft.rowIterator());
00629 typename SrcImageIterator::row_iterator send(s+ destSize.x);
00630 typename DestImageIterator::row_iterator d(dest_upperleft.rowIterator());
00631 ul.x=offsetX;
00632 for(; s != send; ++s, ++d, ++ul.x) {
00633 da.set(f(sa(s), ul), d);
00634 }
00635 }
00636 }
00637
00638 template <class SrcImageIterator, class SrcAccessor,
00639 class DestImageIterator, class DestAccessor, class Functor>
00640 void
00641 transformImageSpatial(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00642 vigra::pair<DestImageIterator, DestAccessor> dest,
00643 Functor const & f, vigra::Diff2D ul)
00644 {
00645 transformImageSpatial(src.first, src.second, src.third, dest.first, dest.second, f, ul);
00646 }
00647
00648
00649 }
00650
00651 #endif // VIGRA_EXT_UTILS_H