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     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 } // namespace
00650 
00651 #endif // VIGRA_EXT_UTILS_H

Generated on 5 Dec 2014 for Hugintrunk by  doxygen 1.4.7