PICCANTE  0.4
The hottest HDR imaging library!
tmqi.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_METRICS_TMQI_HPP
19 #define PIC_METRICS_TMQI_HPP
20 
21 #include <math.h>
22 
23 #include "../base.hpp"
24 #include "../image.hpp"
25 #include "../image_vec.hpp"
26 
27 #include "../metrics/base.hpp"
28 
29 #include "../util/indexed_array.hpp"
30 #include "../util/array.hpp"
31 #include "../util/math.hpp"
32 #include "../util/std_util.hpp"
33 #include "../util/tile_list.hpp"
34 #include "../util/string.hpp"
35 
36 #include "../algorithms/pyramid.hpp"
37 
38 #include "../filtering/filter_luminance.hpp"
39 #include "../filtering/filter_gaussian_2d.hpp"
40 #include "../filtering/filter_downsampler_2d.hpp"
41 #include "../filtering/filter_down_pp.hpp"
42 
43 #include "../filtering/filter_tmqi.hpp"
44 
45 namespace pic {
46 
50 class TMQI
51 {
52 public:
53  float a, invA, alpha, beta;
54  std::vector<float> weights;
58 
62  TMQI()
63  {
64  a = 0.8012f;
65  invA = 1.0f - a;
66  alpha = 0.3046f;
67  beta = 0.7088f;
68 
69  flt_gauss2D.update(1.5f);
70 
71  weights.push_back(0.0448f);
72  weights.push_back(0.2856f);
73  weights.push_back(0.3001f);
74  weights.push_back(0.2363f);
75  weights.push_back(0.1333f);
76  }
77 
83  {
84  if(L_LDR == NULL) {
85  return FLT_MAX;
86  }
87 
88  if(L_LDR->channels != 1) {
89  return FLT_MAX;
90  }
91 
92  float u;
93  L_LDR->getMeanVal(NULL, &u);
94 
95  TileList tl(11, L_LDR->width, L_LDR->height);
96 
97  float sig = 0.0f;
98  int n = int(tl.size());
99  for(int i = 0; i < n; i++) {
100  auto j = tl.getNext();
101 
102  auto box = tl.getBBox(j);
103 
104  float var_i;
105  L_LDR->getVarianceVal(NULL, &box, &var_i);
106 
107  sig += sqrtf(var_i);
108  }
109 
110  sig /= float(n);
111 
112  float p_hat[] ={4.4f, 10.1f};
113  float beta_mode = (p_hat[0] - 1.0f) / (p_hat[0] + p_hat[1] - 2.0f);
114 
115  float C_0 = betaPDF(beta_mode, p_hat[0], p_hat[1]);
116  float C = betaPDF(sig / 64.29f, p_hat[0], p_hat[1]);
117  float pc = C / C_0;
118 
119  float mu_hat = 115.94f;
120  float sigma_hat = 27.99f;
121 
122  float B = normalDistribution(u, mu_hat, sigma_hat);
123  float B_0 = normalDistribution(mu_hat, mu_hat, sigma_hat);
124 
125  float pb = B / B_0;
126 
127  return pb * pc;
128  }
129 
138  Image* localStructuralFidelity(Image *L_HDR, Image *L_LDR, float sf, float &S, Image *s_map = NULL)
139  {
140  Image *img1 = L_HDR->clone();
141  Image *img2 = L_LDR->clone();
142 
143  Image *mu1 = flt_gauss2D.Process(Single(img1), NULL);
144  Image *mu2 = flt_gauss2D.Process(Single(img2), NULL);
145 
146  Image img12 = (*L_HDR) * (*L_LDR);
147 
148  delete L_HDR;
149  delete L_LDR;
150 
151  Image mu12 = (*mu1) * (*mu2);
152 
153  mu1->applyFunction(square);
154  mu2->applyFunction(square);
155  img1->applyFunction(square);
156  img2->applyFunction(square);
157 
158  Image *sigma1 = flt_gauss2D.Process(Single(img1), NULL);
159  *sigma1 -= *mu1;
160  delete mu1;
161  sigma1->applyFunction(sqrtf_s);
162 
163  Image *sigma2 = flt_gauss2D.Process(Single(img2), NULL);
164  *sigma2 -= *mu2;
165  delete mu2;
166  sigma2->applyFunction(sqrtf_s);
167 
168  Image *sigma12 = flt_gauss2D.Process(Single(&img12), NULL);
169  *sigma12 -= mu12;
170  mu12.release();
171 
172  flt_tmqi.update(sf);
173 
174  ImageVec vec = Triple(sigma1, sigma2, sigma12);
175  s_map = flt_tmqi.Process(vec, s_map);
176 
177  s_map->getMeanVal(NULL, &S);
178 
179  stdVectorClear<Image>(vec);
180  delete_s(img1);
181  delete_s(img2);
182 
183  return s_map;
184  }
185 
192  float structuralFidelity(Image *L_HDR, Image *L_LDR)
193  {
194  float S = 1.0f;
195  float f = 32.0f;
196 
197  Image *t_HDR = L_HDR;
198  Image *t_LDR = L_LDR;
199  for(auto i = 0; i < weights.size(); i++) {
200  f /= 2.0f;
201 
202  if(t_HDR != NULL && t_LDR != NULL) {
203  float S_i;
204  localStructuralFidelity(t_HDR, t_LDR, f, S_i, NULL);
205 
206  S *= powf(S_i, weights[i]);
207 
208  int width = t_HDR->width >> 1;
209  int height = t_HDR->height >> 1;
210  t_HDR = FilterSampler2D::execute(t_HDR, NULL, width, height);
211  t_LDR = FilterSampler2D::execute(t_LDR, NULL, width, height);
212  } else {
213  break;
214  }
215  }
216 
217  return S;
218  }
219 
230  Image *execute(ImageVec imgIn, float &Q, float &N, float &S, Image *tmqi_map = NULL)
231  {
232  N = -1.0f;
233  S = -1.0f;
234  Q = -1.0f;
235 
236  bool bCheckInput = ImageVecCheck(imgIn, 2) && ImageVecCheckSimilarType(imgIn);
237 
238  if(!bCheckInput) {
239  return tmqi_map;
240  }
241 
242  float max_img_LDR;
243  imgIn[1]->getMaxVal(NULL, &max_img_LDR);
244 
245  if(max_img_LDR <= 1.0f) {
246  return tmqi_map;
247  }
248 
249  Image *L_HDR = flt_lum.Process(Single(imgIn[0]), NULL);
250  Image *L_LDR = flt_lum.Process(Single(imgIn[1]), NULL);
251 
252  float min_L_HDR, max_L_HDR;
253 
254  L_HDR->getMinVal(NULL, &min_L_HDR);
255  L_HDR->getMaxVal(NULL, &max_L_HDR);
256 
257  *L_HDR -= min_L_HDR;
258 
259  float scale = (powf(2.0f, 32.0f) - 1.0f) / (max_L_HDR - min_L_HDR);
260  *L_HDR *= scale;
261 
262  N = statisticalNaturalness(L_LDR);
263 
264  S = structuralFidelity(L_HDR, L_LDR);
265 
266  Q = a * powf(S, alpha) + invA * powf(N, beta);
267 
268  return tmqi_map;
269  }
270 
271 };
272 
273 } // end namespace pic
274 
275 #endif /* PIC_METRICS_TMQI_HPP */
276 
float invA
Definition: tmqi.hpp:53
PIC_INLINE bool ImageVecCheck(ImageVec &imgIn, int minInputImages)
ImageVecCheck.
Definition: image_vec.hpp:147
uint size()
size
float structuralFidelity(Image *L_HDR, Image *L_LDR)
structuralFidelity
Definition: tmqi.hpp:192
int channels
Definition: image.hpp:80
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
PIC_INLINE bool ImageVecCheckSimilarType(ImageVec &stack)
ImageVecCheckSimilarType.
Definition: image_vec.hpp:126
TMQI()
TMQI.
Definition: tmqi.hpp:62
Image * execute(ImageVec imgIn, float &Q, float &N, float &S, Image *tmqi_map=NULL)
execute
Definition: tmqi.hpp:230
std::vector< Image * > ImageVec
ImageVec an std::vector of pic::Image.
Definition: image_vec.hpp:29
float * getMeanVal(BBox *box, float *ret)
getMeanVal computes the mean for the current Image.
float beta
Definition: tmqi.hpp:53
void update(float sf)
update
Definition: filter_tmqi.hpp:91
FilterGaussian2D flt_gauss2D
Definition: tmqi.hpp:56
FilterLuminance flt_lum
Definition: tmqi.hpp:55
BBox getBBox(int index)
genBBox
virtual Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter.hpp:390
The FilterLuminance class.
Definition: filter_luminance.hpp:33
float a
Definition: tmqi.hpp:53
float * getMinVal(BBox *box, float *ret)
getMinVal computes the minimum value for the current Image.
The TMQI class.
Definition: tmqi.hpp:50
The FilterTMQI class.
Definition: filter_tmqi.hpp:30
The TileList class.
Definition: tile_list.hpp:33
float alpha
Definition: tmqi.hpp:53
float statisticalNaturalness(Image *L_LDR)
statisticalNaturalness
Definition: tmqi.hpp:82
PIC_INLINE float betaPDF(float x, float A, float B)
betaPDF
Definition: math.hpp:536
Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter_npasses.hpp:310
uint getNext()
getNext returns the index of the next tile to process.
PIC_INLINE float square(float x)
Square applies square function to a value.
Definition: math.hpp:188
void release()
release frees allocated buffers.
void applyFunction(float(*func)(float))
applyFunction is an operator that applies an input function to all values in data.
std::vector< float > weights
Definition: tmqi.hpp:54
static Image * execute(Image *imgIn, Image *imgOut, float scale, ImageSampler *isb=NULL)
execute
Definition: filter_sampler_2d.hpp:149
The Image class stores an image as buffer of float.
Definition: image.hpp:60
float * getMeanVal(BBox *box, float *ret)
getMeanVal computes the mean for the current Image.
Definition: filter_radial_basis_function.hpp:1501
void update(float sigma)
update
Definition: filter_gaussian_2d.hpp:72
PIC_INLINE ImageVec Triple(Image *img1, Image *img2, Image *img3)
Triple creates an std::vector which contains img1, img2, and img3; this is for filters input...
Definition: image_vec.hpp:64
Image * clone() const
Clone creates a deep copy of the calling instance.
PIC_INLINE float sqrtf_s(float x)
sqrtf_s
Definition: math.hpp:198
FilterTMQI flt_tmqi
Definition: tmqi.hpp:57
PIC_INLINE ImageVec Single(Image *img)
Single creates an std::vector which contains img; this is for filters input.
Definition: image_vec.hpp:36
Definition: bilateral_separation.hpp:25
The FilterGaussian2D class.
Definition: filter_gaussian_2d.hpp:31
float * getMaxVal(BBox *box, float *ret)
getMaxVal computes the maximum value for the current Image.
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80
float * getVarianceVal(float *meanVal, BBox *box, float *ret)
getVarianceVal computes the variance for the current Image.
Image * localStructuralFidelity(Image *L_HDR, Image *L_LDR, float sf, float &S, Image *s_map=NULL)
localStructuralFidelity
Definition: tmqi.hpp:138
PIC_INLINE float normalDistribution(float x, float mu=0.0f, float sigma=1.0f)
normalDistribution
Definition: math.hpp:460