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 <vigra/codec.hxx>
00033 #include <cmath>
00034 
00035 namespace vigra {
00036 
00037 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
00038 struct PromoteTraits<RGBValue<T1, R, G, B>, T2 >
00039 {
00040     typedef RGBValue<typename PromoteTraits<T1, T2>::Promote> Promote;
00041 };
00042 
00043 }
00044 
00045 namespace vigra_ext {
00046 
00049 #define LUT_TRAITS(T1, Smin, Smax) \
00050 template<> \
00051 struct LUTTraits<T1> \
00052 { \
00053     static T1 max() \
00054 { \
00055     return Smax; \
00056 } \
00057     static T1 min() \
00058 { \
00059     return Smin; \
00060 } \
00061 }; \
00062 template<> \
00063 struct LUTTraits<vigra::RGBValue<T1> > \
00064 { \
00065     static T1 max() \
00066 { \
00067     return Smax; \
00068 } \
00069     static T1 min() \
00070 { \
00071     return Smin; \
00072 } \
00073 };
00074 
00075     template <class T1>
00076     struct LUTTraits;
00077 
00078     LUT_TRAITS(unsigned char, 0, UCHAR_MAX);
00079     LUT_TRAITS(signed char, SCHAR_MIN, SCHAR_MAX);
00080     LUT_TRAITS(unsigned short, 0, USHRT_MAX);
00081     LUT_TRAITS(signed short, SHRT_MIN, SHRT_MAX);
00082     LUT_TRAITS(unsigned int, 0, UINT_MAX);
00083     LUT_TRAITS(signed int, INT_MIN, INT_MAX);
00084     LUT_TRAITS(float, 0.0f, 1.0f);
00085     LUT_TRAITS(double, 0.0, 1.0);
00086 
00087 #undef LUT_TRAITS
00088 
00089 inline double getMaxValForPixelType(const std::string & v)
00090 {
00091     if (v == "UINT8") {
00092         return 255;
00093     } else if (v == "INT8") {
00094         return 127;
00095     } else if (v == "UINT16") {
00096         return 65535;
00097     } else if (v == "INT16") {
00098         return 32767;
00099     } else if (v == "UINT32") {
00100         return 4294967295u;
00101     } else if (v == "INT32") {
00102         return 2147483647;
00103     }
00104     return 1.0;
00105 }
00106 
00107 template <class VALUE>
00108 struct PointPairT
00109 {
00110     PointPairT()
00111     {
00112     }
00113 
00114     PointPairT(short img1, VALUE val1, const hugin_utils::FDiff2D & p1, float r1,
00115               short img2, VALUE val2, const hugin_utils::FDiff2D & p2, float r2)
00116     : imgNr1(img1), i1(val1), p1(p1), r1(r1), imgNr2(img2), i2(val2), p2(p2), r2(r2)
00117     {
00118     }
00119 
00120     short imgNr1;
00121     VALUE i1;
00122     hugin_utils::FDiff2D p1;
00123     float r1;
00124     short imgNr2;
00125     VALUE i2;
00126     hugin_utils::FDiff2D p2;
00127     float r2;
00128 };
00129 
00130 typedef PointPairT<float> PointPair;
00131 typedef PointPairT<vigra::RGBValue<float> > PointPairRGB;
00132 
00133 
00134 
00135 // get the value_type of vector pixels and also single channel pixels.
00136 #define VT_TRAITS_VEC(T1) \
00137 template<> \
00138 struct ValueTypeTraits<vigra::RGBValue<T1, 0u, 1u, 2u> > \
00139 { \
00140     typedef vigra::RGBValue<T1, 0u, 1u, 2u>::value_type value_type; \
00141 };
00142 
00143 #define VT_TRAITS(T1) \
00144 template<> \
00145 struct ValueTypeTraits<T1> \
00146 { \
00147     typedef T1 value_type; \
00148 };
00149 
00150 template <class T1>
00151 struct ValueTypeTraits
00152 {
00153     typedef typename T1::value_type value_type;
00154 };
00155 
00156 #if 0
00157 VT_TRAITS_VEC(vigra::UInt8);
00158 VT_TRAITS_VEC(vigra::Int16);
00159 VT_TRAITS_VEC(vigra::UInt16);
00160 VT_TRAITS_VEC(vigra::Int32);
00161 VT_TRAITS_VEC(vigra::UInt32);
00162 VT_TRAITS_VEC(float);
00163 VT_TRAITS_VEC(double);
00164 #endif
00165 
00166 VT_TRAITS(vigra::UInt8);
00167 VT_TRAITS(vigra::Int16);
00168 VT_TRAITS(vigra::UInt16);
00169 VT_TRAITS(vigra::Int32);
00170 VT_TRAITS(vigra::UInt32);
00171 VT_TRAITS(float);
00172 VT_TRAITS(double);
00173 
00174 #undef VT_TRAITS
00175 #undef VT_TRAITS_VEC
00176 
00177 
00178 using VIGRA_CSTD::pow;
00179 using VIGRA_CSTD::log;
00180 
00181 inline float pow(float a, double b)
00182 {
00183     return std::pow(a,(float) b);
00184 }
00185 
00187 template <class T, unsigned int R, unsigned int G, unsigned int B>
00188 inline
00189 vigra::RGBValue<T, R, G, B> pow(vigra::RGBValue<T, R, G, B> const & v, double e) {
00190     return vigra::RGBValue<T, R, G, B>(pow(v.red(),e), pow(v.green(),e),  pow(v.blue(),e));
00191 }
00192 
00194 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
00195 inline
00196 vigra::RGBValue<V1, R, G, B> &
00197 operator+=(vigra::RGBValue<V1, R, G, B> & l, V2 const & r)
00198 {
00199     l.red() += r;
00200     l.green() += r;
00201     l.blue() += r;
00202     return l;
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 log(vigra::RGBValue<T, RIDX, GIDX, BIDX> const & v)
00210 {
00211     return vigra::RGBValue<T, RIDX, GIDX, BIDX>(std::log(v.red()), std::log(v.green()), std::log(v.blue()));
00212 }
00213 
00215 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
00216 inline
00217 vigra::RGBValue<T, RIDX, GIDX, BIDX>
00218 log10(vigra::RGBValue<T, RIDX, GIDX, BIDX> const & v)
00219 {
00220     return vigra::RGBValue<T, RIDX, GIDX, BIDX>(std::log10(v.red()), std::log10(v.green()), std::log10(v.blue()));
00221 }
00222 
00224 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
00225 inline
00226 // WARNING: This is a hack.. 
00227 //vigra::RGBValue<V1>
00228 typename vigra::PromoteTraits<vigra::RGBValue<V1, R, G, B>, V2 >::Promote
00229 operator+(vigra::RGBValue<V1, R, G, B> const & r1, V2 const & r2)
00230 {
00231     typename vigra::PromoteTraits<vigra::RGBValue<V1, R, G, B>, V2 >::Promote res(r1);
00232 
00233     res += r2;
00234 
00235     return res;
00236 }
00237 
00240 template <class V, int SIZE, class D1, class D2>
00241 inline
00242 vigra::TinyVector<V, SIZE>
00243 pow(vigra::TinyVector<V, SIZE> const & v, double e)
00244 {
00245     vigra::TinyVector<V, SIZE> res;
00246     for (int i=0; i<SIZE; i++)
00247         res[i] = std::pow(v[i], e);
00248     return res;
00249 } 
00250 
00253 template <class V, int SIZE, class D1, class D2>
00254 inline
00255 vigra::TinyVector<V, SIZE>
00256 log(vigra::TinyVector<V, SIZE> const & v, double e)
00257 {
00258     vigra::TinyVector<V, SIZE> res;
00259     for (int i=0; i<SIZE; i++)
00260         res[i] = std::log(v[i], e);
00261     return res;
00262 } 
00263 
00265 template <class V>
00266 inline
00267 V
00268 getMaxComponent(vigra::RGBValue<V> const & v)
00269 {
00270     return std::max(std::max(v.red(), v.green()), v.blue());
00271 }
00272 
00274 template <class V>
00275 inline
00276 V
00277 getMaxComponent(V v)
00278 {
00279     return v;
00280 }
00281 
00283 template <class V>
00284 inline
00285 V
00286 getMinComponent(vigra::RGBValue<V> const & v)
00287 {
00288     return std::min(std::min(v.red(), v.green()), v.blue());
00289 }
00290 
00292 template <class V>
00293 inline
00294 V
00295 getMinComponent(V v)
00296 {
00297     return v;
00298 }
00299 
00300 template <class VALUETYPE>
00301 class FindComponentsMinMax
00302 {
00303 public:
00305     typedef VALUETYPE argument_type;
00307     typedef VALUETYPE result_type;
00309     typedef VALUETYPE value_type;
00310 
00312     FindComponentsMinMax() : min(vigra::NumericTraits<value_type>::max()), max(vigra::NumericTraits<value_type>::min()), count(0)
00313     {}
00314 
00316     void reset()
00317     {
00318         count = 0;
00319     }
00320 
00322     void operator()(argument_type const & v)
00323     {
00324         if (count)
00325         {
00326             if (v < min) min = v;
00327             if (max < v) max = v;
00328         }
00329         else
00330         {
00331             min = v;
00332             max = v;
00333         }
00334         ++count;
00335     }
00336 
00338     void operator()(vigra::RGBValue<VALUETYPE> const & v)
00339     {
00340         const VALUETYPE vMax = vigra_ext::getMaxComponent(v);
00341         const VALUETYPE vMin = vigra_ext::getMinComponent(v);
00342         if (count)
00343         {
00344             if (vMin < min)
00345             {
00346                 min = vMin;
00347             };
00348             if (vMax > max)
00349             {
00350                 max = vMax;
00351             };
00352         }
00353         else
00354         {
00355             min = vMin;
00356             max = vMax;
00357         }
00358         ++count;
00359     }
00360 
00362     VALUETYPE min;
00364     VALUETYPE max;
00366     unsigned int count;
00367 };
00368 
00369 template<class ImgIter, class ImgAccessor, class AlphaIter, class AlphaAccessor>
00370 void applyExposureClipMask(vigra::triple<ImgIter, ImgIter, ImgAccessor> image, vigra::triple<AlphaIter, AlphaIter, AlphaAccessor> mask, double lowerLimit, double upperLimit)
00371 {
00372     typedef typename ImgAccessor::value_type ImageValueType;
00373     vigra_precondition((image.second - image.first) == (mask.second - mask.first), "applyExposureMask: image and mask have different sizes");
00374     const vigra::Diff2D imgSize = image.second - image.first;
00375     const double LowerLimit = lowerLimit * LUTTraits<ImageValueType>::max();
00376     const double UpperLimit = upperLimit * LUTTraits<ImageValueType>::max();
00377 
00378     // create dest y iterator
00379     ImgIter yd(image.first);
00380     AlphaIter ymd(mask.first);
00381     // loop over the image and transform
00382     for (int y = 0; y < imgSize.y; ++y, ++yd.y, ++ymd.y)
00383     {
00384         // create x iterators
00385         ImgIter xd(yd);
00386         AlphaIter xmd(ymd);
00387         for (int x = 0; x < imgSize.x; ++x, ++xd.x, ++xmd.x)
00388         {
00389             const double minVal = vigra_ext::getMinComponent(*xd);
00390             const double maxVal = vigra_ext::getMaxComponent(*xd);
00391             if (minVal < LowerLimit || maxVal > UpperLimit)
00392             {
00393                 *xmd = 0;
00394             };
00395         }
00396     }
00397 }
00398 
00400 struct OverlapSizeCounter
00401 {
00402     OverlapSizeCounter()
00403         : size(0)
00404     { }
00405 
00406     template<typename PIXEL>
00407     void operator()(PIXEL const & img1, PIXEL const & img2)
00408     {
00409         if (img1 > 0 && img2 > 0) {
00410             size++;
00411         }
00412     }
00413 
00414     unsigned int getSize()
00415     {
00416         return size;
00417     }
00418 
00419     unsigned int size;
00420 };
00421 
00422 
00430 template <class F1, class F2>
00431 struct NestFunctor
00432 {
00433     F1 f1;
00434     F2 f2;
00435     NestFunctor(const F1 & fu1, const F2 & fu2)
00436     : f1(fu1), f2(fu2)
00437     { }
00438 
00441     typedef typename F1::result_type result_type;
00442 
00443     template <class T1>
00444     result_type operator()(T1 const & v) const
00445     {
00446         return f1(f2(v));
00447     }
00448 
00450     template <class T1, class T2>
00451     result_type operator()(T1 const & v1, T2 const & v2) const
00452     {
00453         return f1(f2(v1,v2));
00454     }
00455 
00457     template <class T1, class T2, class T3>
00458     result_type operator()(T1 const & v1, T2 const & v2, T3 const & v3) const
00459     {
00460         return f1(f2(v1,v2,v3));
00461     }
00462 };
00463 
00464 
00466 struct MaskPixelCounter
00467 {
00468     MaskPixelCounter()
00469         : count(0)
00470     { }
00471 
00472     template<typename PIXEL>
00473     void operator()(PIXEL const & img1)
00474     {
00475         if (img1 > 0) {
00476             count++;
00477         }
00478     }
00479 
00480     int getCount()
00481     {
00482         return count;
00483     }
00484 
00485     int count;
00486 };
00487 
00494 template <class SrcImageIterator, class SrcAccessor>
00495 void circularCrop(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img,
00496                   hugin_utils::FDiff2D middle, double radius)
00497 {
00498     vigra::Diff2D imgSize = img.second - img.first;
00499     double r2 = radius*radius;
00500 
00501     // create dest y iterator
00502     SrcImageIterator yd(img.first);
00503     // loop over the image and transform
00504     for(int y=0; y < imgSize.y; ++y, ++yd.y)
00505     {
00506         // create x iterators
00507         SrcImageIterator xd(yd);
00508         for(int x=0; x < imgSize.x; ++x, ++xd.x)
00509         {
00510             double dx = x-middle.x;
00511             double dy = y-middle.y;
00512             if (dx*dx+dy*dy > r2) {
00513                 *xd = 0;
00514             }
00515         }
00516     }
00517 }
00518 
00520 template <class T>
00521 struct PassThroughFunctor
00522 {
00523     typedef T result_type;
00524 
00525     T operator()(const T & a) const
00526     {
00527         return a;
00528     }
00529 
00530     template <class T2>
00531     T2 operator()(const T2 & a, const hugin_utils::FDiff2D & p) const
00532     {
00533         return a;
00534     }
00535 
00536     template <class T2, class A>
00537     A
00538     hdrWeight(T2 v, A a) const
00539     {
00540         return a;
00541     }
00542 
00543 };
00544 
00545 
00549 template <class T>
00550 typename vigra::NumericTraits<T>::RealPromote
00551 normalizeValue(T v, vigra::VigraTrueType)
00552 {
00553     return vigra::NumericTraits<T>::toRealPromote(v) / vigra::NumericTraits<T>::max();
00554 }
00555 
00556 template <class T>
00557 typename vigra::NumericTraits<T>::RealPromote
00558 normalizeValue(T v, vigra::VigraFalseType)
00559 {
00560     return v;
00561 }
00562 
00563 
00564 
00565 template <class DestValueType>
00566 struct LinearTransform
00567 {
00568   public:
00569         /* the functors argument type (actually, since 
00570            <tt>operator()</tt> is a template, much more types are possible)
00571         */
00572     typedef DestValueType argument_type;
00573 
00574         /* the functors result type
00575         */
00576     typedef DestValueType result_type;
00577 
00578         /* init scale and offset
00579         */
00580     LinearTransform(float scale, float offset)
00581     : scale_(scale), offset_(offset)
00582     {}
00583     template <class SrcValueType>
00584     result_type operator()(SrcValueType const & s) const
00585     {
00586         return vigra::NumericTraits<result_type>::fromRealPromote(scale_ * (vigra::NumericTraits<SrcValueType>::toRealPromote(s) + offset_));
00587     }
00588   private:
00589 
00590     float scale_;
00591     float offset_;
00592 };
00593 
00594 
00595 struct ApplyLogFunctor
00596 {
00597     float minv;
00598     float maxv;
00599     float scale;
00600 
00601     ApplyLogFunctor(float min_, float max_)
00602     {
00603         // protect against zeros in image data
00604         if (min_ == 0.0f) {
00605             min_ = 1e-5f;
00606         }
00607         minv = std::log10(min_);
00608         maxv = std::log10(max_);
00609         scale = (maxv - minv)/255;
00610     }
00611 
00612     template <class T>
00613     unsigned char operator()(T v) const
00614     {
00615         typedef vigra::NumericTraits<vigra::UInt8>  DestTraits;
00616         return DestTraits::fromRealPromote((std::log10(float(v))-minv)/scale);
00617     }
00618 
00619     template <class T, unsigned int R, unsigned int G, unsigned int B>
00620     vigra::RGBValue<vigra::UInt8,0,1,2> operator()(const vigra::RGBValue<T,R,G,B> & v) const
00621     {
00622         typedef vigra::NumericTraits< vigra::RGBValue<vigra::UInt8,0,1,2> >  DestTraits;
00623         typedef vigra::NumericTraits< vigra::RGBValue<T,R,G,B> >  SrcTraits;
00624         return DestTraits::fromRealPromote((log10(SrcTraits::toRealPromote(v)) + (-minv))/scale);
00625     }
00626 };
00627 
00628 
00629 template <class TIn, class TOut=vigra::UInt8>
00630 struct ApplyGammaFunctor
00631 {
00632     float minv;
00633     float maxv;
00634     float gamma;
00635     float scale;
00636 
00637     ApplyGammaFunctor(TIn min_, TIn max_, float gamma_)
00638     {
00639         minv = min_;
00640         maxv = max_;
00641         gamma = gamma_;
00642         scale = float(maxv) - minv;
00643     }
00644 
00645     TOut operator()(TIn v) const
00646     {
00647         typedef vigra::NumericTraits<TOut>  DestTraits;
00648         return DestTraits::fromRealPromote(pow((float(v)-minv)/scale, gamma)*255);
00649     }
00650 
00651     vigra::RGBValue<TOut> operator()(const vigra::RGBValue<TIn> & v) const
00652     {
00653         typedef vigra::NumericTraits< vigra::RGBValue<TOut> >  DestTraits;
00654         typedef vigra::NumericTraits< vigra::RGBValue<TIn> >  SrcTraits;
00655         return DestTraits::fromRealPromote(vigra_ext::pow((SrcTraits::toRealPromote(v)+(-minv))/scale, gamma)*255);
00656     }
00657 };
00658 
00659 // gamma correction with lookup table
00660 template <>
00661 struct ApplyGammaFunctor<vigra::UInt16, vigra::UInt8>
00662 {
00663     vigra::UInt8 lut[65536];
00664 
00665     ApplyGammaFunctor(vigra::UInt16 min, vigra::UInt16 max, float gamma)
00666     {
00667         float scale = float(max) - min;
00668         for (int i=0; i<65536; i++) {
00669             lut[i] = hugin_utils::roundi(pow((float(i)-min)/scale, gamma)*255);
00670         }
00671     }
00672 
00673     vigra::UInt8 operator()(vigra::UInt16 v) const
00674     {
00675         return lut[v];
00676     }
00677 
00678     vigra::RGBValue<vigra::UInt8> operator()(const vigra::RGBValue<vigra::UInt16> & v) const
00679     {
00680         return vigra::RGBValue<vigra::UInt8>(lut[v[0]], lut[v[1]], lut[v[2]]);
00681     }
00682 };
00683 
00684 template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor, class T>
00685         void applyMapping(vigra::triple<SrcIterator, SrcIterator, SrcAccessor> img,
00686                           vigra::pair<DestIterator, DestAccessor> dest, T min, T max, int mapping )
00687 {
00688 
00689     switch (mapping)
00690     {
00691         case 0:
00692         {
00693             // linear
00694             float offset_ = -float(min);
00695             float scale_ = 255/float(max)-float(min);
00696             vigra::transformImage(img, dest,
00697                                   LinearTransform<typename DestAccessor::value_type>( scale_, offset_)
00698                                  );
00699             break;
00700         }
00701         case 1:
00702         {
00703             // log
00704             ApplyLogFunctor logfunc(min, max);
00705             transformImage(img, dest,
00706                            logfunc);
00707             break;
00708         }
00709         case 2:
00710         {
00711             // gamma
00712             ApplyGammaFunctor<T> logfunc(min, max, 1/2.2f);
00713             transformImage(img, dest,
00714                            logfunc);
00715             break;
00716         }
00717         default:
00718             vigra_fail("Unknown image mapping mode");
00719     }
00720 }
00721 
00722 template <class SrcImageIterator, class SrcAccessor,
00723 class DestImageIterator, class DestAccessor, class Functor>
00724 void
00725 transformImageSpatial(SrcImageIterator src_upperleft,
00726                       SrcImageIterator src_lowerright, SrcAccessor sa,
00727                       DestImageIterator dest_upperleft, DestAccessor da,
00728                       Functor const & f, vigra::Diff2D ul) 
00729 {
00730     vigra::Diff2D destSize = src_lowerright - src_upperleft;
00731 
00732     int offsetX=ul.x;
00733     for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y, ++ul.y)
00734     {
00735         typename SrcImageIterator::row_iterator s(src_upperleft.rowIterator());
00736         typename SrcImageIterator::row_iterator send(s+ destSize.x);
00737         typename DestImageIterator::row_iterator d(dest_upperleft.rowIterator());
00738         ul.x=offsetX;
00739         for(; s != send; ++s, ++d, ++ul.x) {
00740             da.set(f(sa(s), ul), d);
00741         }
00742     }
00743 }
00744 
00745 template <class SrcImageIterator, class SrcAccessor,
00746 class DestImageIterator, class DestAccessor, class Functor>
00747 void
00748 transformImageSpatial(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00749                       vigra::pair<DestImageIterator, DestAccessor> dest,
00750                       Functor const & f, vigra::Diff2D ul)
00751 {
00752     transformImageSpatial(src.first, src.second, src.third, dest.first, dest.second, f, ul);
00753 }
00754 
00756 template <class ImageType>
00757 void ConvertTo8Bit(ImageType& image)
00758 {
00759     typedef vigra::NumericTraits<typename ImageType::PixelType> DestTraits;
00760     double maxVal = vigra::NumericTraits<typename DestTraits::ValueType>::max();
00761     double minVal = vigra::NumericTraits<typename DestTraits::ValueType>::min();
00762     const std::string pixelType = vigra::TypeAsString<typename DestTraits::ValueType>::result();
00763     int mapping = 0;
00764     if (pixelType == "FLOAT" || pixelType == "DOUBLE")
00765     {
00766         vigra::FindMinMax<typename ImageType::PixelType> minmax;
00767         vigra::inspectImage(srcImageRange(image), minmax);
00768         minVal = vigra_ext::getMaxComponent(minmax.min);
00769         maxVal = vigra_ext::getMaxComponent(minmax.max);
00770         mapping = 1;
00771     }
00772     if (minVal != 0 || maxVal != 255)
00773     {
00774         vigra_ext::applyMapping(srcImageRange(image), destImage(image), minVal, maxVal, mapping);
00775     };
00776 };
00777 
00778 } // namespace
00779 
00780 #endif // VIGRA_EXT_UTILS_H

Generated on 10 Dec 2016 for Hugintrunk by  doxygen 1.4.7