PICCANTE  0.4
The hottest HDR imaging library!
lischinski_minimization.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_ALGORITHMS_LISCHINSKI_MINIMIZATION_HPP
19 #define PIC_ALGORITHMS_LISCHINSKI_MINIMIZATION_HPP
20 
21 #ifndef PIC_DISABLE_EIGEN
22 
23 #ifndef PIC_EIGEN_NOT_BUNDLED
24  #include "../externals/Eigen/Sparse"
25  #include "../externals/Eigen/src/SparseCore/SparseMatrix.h"
26 #else
27  #include <Eigen/Sparse>
28  #include <Eigen/src/SparseCore/SparseMatrix.h>
29 #endif
30 
31 #endif
32 
33 #include "../base.hpp"
34 #include "../image.hpp"
35 
36 namespace pic {
52 inline float LischinskiFunction(float Lcur, float Lref, float param[2],
53  float LISCHINSKI_EPSILON = 0.0001f)
54 {
55  return -param[1] / (powf(fabsf(Lcur - Lref), param[0]) + LISCHINSKI_EPSILON);
56 }
57 
65 inline float LischinskiFunctionGauss(float Lcur, float Lref, float param[2])
66 {
67  return expf(-powf(Lcur - Lref, 2.0f) * 10.0f);
68 }
69 
83  Image *g,
84  Image *omega = NULL,
85  float omega_global = 1.0f,
86  Image *gOut = NULL,
87  float alpha = 1.0f,
88  float lambda = 0.4f,
89  float LISCHINSKI_EPSILON = 1e-4f)
90 {
91  if(L == NULL || g == NULL) {
92  return gOut;
93  }
94 
95 #ifndef PIC_DISABLE_EIGEN
96  bool bOmega = (omega == NULL);
97 
98  int width = L->width;
99  int height = L->height;
100  int tot = height * width;
101 
102  float param[2];
103  param[0] = alpha;
104  param[1] = lambda;
105 
106  Eigen::VectorXd b, x;
107  b = Eigen::VectorXd::Zero(tot);
108 
109  #ifdef PIC_DEBUG
110  printf("Init matrix...");
111  #endif
112 
113  std::vector< Eigen::Triplet< double > > tL;
114 
115  for(int i = 0; i < height; i++) {
116  int tmpInd = i * width;
117 
118  for(int j = 0; j < width; j++) {
119 
120  float sum = 0.0f;
121  float tmp;
122  int indJ;
123  int indI = tmpInd + j;
124  float Lref = L->data[indI];
125 
126  float omega_val;
127  if(bOmega) {
128  omega_val = omega_global;
129  } else {
130  omega_val = omega->data[indI];
131  }
132 
133  b[indI] = omega_val * g->data[indI];
134 
135  if((i - 1) >= 0) {
136  indJ = indI - width;
137  tmp = LischinskiFunction(L->data[indJ], Lref, param, LISCHINSKI_EPSILON);
138  tL.push_back(Eigen::Triplet< double > (indI, indJ, tmp));
139  sum += tmp;
140  }
141 
142  if((i + 1) < height) {
143  indJ = indI + width;
144  tmp = LischinskiFunction(L->data[indJ], Lref, param, LISCHINSKI_EPSILON);
145  tL.push_back(Eigen::Triplet< double > (indI, indJ, tmp));
146  sum += tmp;
147  }
148 
149  if((j - 1) >= 0) {
150  indJ = indI - 1;
151  tmp = LischinskiFunction(L->data[indJ], Lref, param, LISCHINSKI_EPSILON);
152  tL.push_back(Eigen::Triplet< double > (indI, indJ, tmp));
153  sum += tmp;
154  }
155 
156  if((j + 1) < width) {
157  indJ = indI + 1;
158  tmp = LischinskiFunction(L->data[indJ], Lref, param, LISCHINSKI_EPSILON);
159  tL.push_back(Eigen::Triplet< double > (indI, indJ, tmp));
160  sum += tmp;
161  }
162 
163  tL.push_back(Eigen::Triplet< double > (indI, indI, omega_val - sum));
164  }
165  }
166 
167  #ifdef PIC_DEBUG
168  printf("Ok\n");
169  #endif
170 
171  Eigen::SparseMatrix<double> A = Eigen::SparseMatrix<double>(tot, tot);
172  A.setFromTriplets(tL.begin(), tL.end());
173 
174  Eigen::SimplicialCholesky<Eigen::SparseMatrix<double> > solver(A);
175  x = solver.solve(b);
176 
177  if(solver.info() != Eigen::Success) {
178  #ifdef PIC_DEBUG
179  printf("SOLVER FAILED!\n");
180  #endif
181  return NULL;
182  }
183 
184  #ifdef PIC_DEBUG
185  printf("SOLVER SUCCESS!\n");
186  #endif
187 
188  if(gOut == NULL) {
189  gOut = g->allocateSimilarOne();
190  } else {
191  if(!gOut->isSimilarType(g)) {
192  gOut = g->allocateSimilarOne();
193  }
194  }
195 
196  for(int i = 0; i < height; i++) {
197  int counter = i * width;
198 
199  for(int j = 0; j < width; j++) {
200  (*gOut)(j, i)[0] = float(x(counter + j));
201  }
202  }
203 
204  return gOut;
205 #else
206  return gOut;
207 #endif
208 }
209 
210 } // end namespace pic
211 
212 #endif /* PIC_ALGORITHMS_LISCHINSKI_MINIMIZATION_HPP */
213 
float * data
data is the main buffer where pixel values are stored.
Definition: image.hpp:91
float LischinskiFunction(float Lcur, float Lref, float param[2], float LISCHINSKI_EPSILON=0.0001f)
LischinskiFunction.
Definition: lischinski_minimization.hpp:52
float LischinskiFunctionGauss(float Lcur, float Lref, float param[2])
LischinskiFunctionGauss.
Definition: lischinski_minimization.hpp:65
PIC_INLINE Image * LischinskiMinimization(Image *L, Image *g, Image *omega=NULL, float omega_global=1.0f, Image *gOut=NULL, float alpha=1.0f, float lambda=0.4f, float LISCHINSKI_EPSILON=1e-4f)
LischinskiMinimization.
Definition: lischinski_minimization.hpp:82
#define PIC_INLINE
Definition: base.hpp:33
The Image class stores an image as buffer of float.
Definition: image.hpp:60
Image * allocateSimilarOne()
allocateSimilarOne creates an Image with similar size of the calling instance.
Definition: bilateral_separation.hpp:25
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80