Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/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
1.3.9.1