HDRUtils.h

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00024 #ifndef _VIGRA_EXT_HDRUTILS_H
00025 #define _VIGRA_EXT_HDRUTILS_H
00026 
00027 #include "ROIImage.h"
00028 #include "utils.h"
00029 #include "lut.h"
00030 
00031 
00032 namespace vigra_ext {
00033 
00034     
00035 template<class VALUETYPE=vigra::RGBValue<float> >
00036 class ReduceToHDRFunctor
00037 {
00038 public:
00039     typedef VALUETYPE   argument_type;
00040     typedef VALUETYPE   first_argument_type;
00041     typedef VALUETYPE   second_argument_type;
00042     typedef VALUETYPE   result_type;
00043     
00044     typedef typename vigra::NumericTraits<VALUETYPE> Traits;
00045     typedef typename Traits::RealPromote real_type;
00046 
00047     ReduceToHDRFunctor()
00048     {
00049         reset();
00050     }
00051 
00052     void reset ()
00053     {
00054         result = vigra::NumericTraits<real_type>::zero();
00055         weight = 0;
00056 
00057         maxComp = DBL_MIN;
00058         minComp = DBL_MAX;
00059         maxW= 0;
00060         minW= 1;
00061     }
00062 
00063     // add a new measurement for the current pixel
00064     template<class T, class M> 
00065     void operator() (T const &v, M const &m)
00066     {
00067         // normalize to 0..1
00068         double nm = m / (double)vigra_ext::LUTTraits<M>::max();
00069 
00070         // use a gaussian weight function.
00071 //        double w = (nm - 0.5)/0.18;
00072 //        w = exp( -w*w);
00073         // a simple triangular function should also work ok
00074         double w = 0.5-fabs(nm-0.5);
00075 
00076         result += w*v;
00077         weight += w;
00078 
00079         // store minimum and maximum weight and pixel values
00080         if (nm > maxW) {
00081             maxW = w;
00082         }
00083         if ( w < minW) {
00084             minW = w;
00085         }
00086 
00087         double cmax = getMaxComponent(v);
00088 
00089         if (cmax > maxComp)
00090         {
00091             maxComp = cmax;
00092             maxValue = v;
00093         }
00094         if (cmax < minComp)
00095         {
00096             minComp = cmax;
00097             minValue = v;
00098         }
00099     }
00100 
00102     real_type operator() () const
00103     {
00104         double eps = 1e-7;
00105         // heuristics to deal with over and underexposed images.
00106         if (minW > (1.0-eps) && maxW > (1.0-eps)) {
00107             // all pixels overexposed, just use smallest value
00108             return minValue;
00109         } else if (minW < eps && maxW < eps) {
00110             // all pixels underexposed. use brightest value
00111             return maxValue;
00112         }
00113         if (weight > 0)
00114             return result/weight;
00115         else
00116             return result;
00117     }
00118     
00119 protected:
00120     real_type result;
00121     double weight;
00122 
00123     real_type maxValue;
00124     double maxComp;
00125     real_type minValue;
00126     double minComp;
00127     double maxW;
00128     double minW;
00129 };
00130 
00131 #if 0
00132 
00138 template <class In>
00139 double calcSigmoidHDRWeight(In val)
00140 {
00141     // normalize to 0..1
00142     double x = getMaxComponent(val)/((double) vigra_ext::LUTTraits<In>::max());
00143 
00144     // sigomid function between -6 ... 6
00145     x = (x-0.5)*12;
00146 
00147     // calculate sigmoidal stuff
00148     double y = 1.0 / ( 1.0 + exp(-x));
00149 
00150     double min = 1.0 / ( 1.0 + exp(+6.0));
00151     double max = 1.0 / ( 1.0 + exp(-6.0));
00152     return (y - min)/(max-min);
00153 }
00154 
00155 
00160 struct HDRWeightFunctor
00161 {
00162     HDRWeightFunctor()
00163     {
00164         m_lut.resize(256);
00165         std::cerr << "w = [";
00166         for (int i=0;i<256;i++) {
00167             // gaussian 
00168             float x = (i/255.0f - 0.5f)/0.18f;
00169             vigra::UInt8 w = std::min(utils::ceili(255*exp( -x*x)), 255);
00170 
00171             // hat function
00172             //vigra::UInt8 w = std::max( utils::ceili( (1-pow((2.0*i/255.0)-1.0, 4.0) )*255), 1);
00173             m_lut[i] = w;
00174             std::cerr << (int) w << " ";
00175         }
00176     }
00177 
00178     template <class T>
00179     vigra::UInt8 operator()(vigra::RGBValue<T> rgb) const
00180     {
00181         // mean is not so good since it can create overexposed
00182         // pixels in the image.
00183         //T x = (rgb[0] + rgb[1] + rgb[2])/T(3);
00184 
00185         T x = std::max(rgb[0], std::max(rgb[1], rgb[2]));
00186         return operator()(x);
00187     }
00188 
00189     vigra::UInt8 operator()(float x) const
00190     {
00191         x = x*255;
00192         vigra::UInt8 i = 0;
00193         if (x> 0 || x <=255)
00194             i = (vigra::UInt8) x;
00195         return m_lut[i];
00196     }
00197 
00198 
00199     vigra::UInt8 operator()(vigra::UInt16 x) const
00200     {
00201         x <<= 8;
00202         return m_lut[x];
00203     }
00204 
00205     vigra::UInt8 operator()(vigra::UInt8 x) const
00206     {
00207         return m_lut[x];
00208     }
00209 
00210     vigra::ArrayVector<vigra::UInt8> m_lut;
00211 };
00212 
00213 #endif
00214 
00215 
00216 } //namespace
00217 #endif //_H

Generated on Wed Jul 16 01:25:38 2014 for Hugintrunk by  doxygen 1.3.9.1