PICCANTE  0.4
The hottest HDR imaging library!
poisson_solver.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_POISSON_SOLVER_HPP
19 #define PIC_ALGORITHMS_POISSON_SOLVER_HPP
20 
21 #include "../base.hpp"
22 
23 #include "../image.hpp"
24 
25 #ifndef PIC_DISABLE_EIGEN
26 
27 #ifndef PIC_EIGEN_NOT_BUNDLED
28  #include "../externals/Eigen/Sparse"
29  #include "../externals/Eigen/src/SparseCore/SparseMatrix.h"
30 #else
31  #include <Eigen/Sparse>
32  #include <Eigen/src/SparseCore/SparseMatrix.h>
33 #endif
34 
35 #endif
36 
37 namespace pic {
38 
39 #ifndef PIC_DISABLE_EIGEN
40 
48 {
49  if(f == NULL) {
50  return NULL;
51  }
52 
53  //allocate the output
54  if(ret == NULL) {
55  ret = f->allocateSimilarOne();
56  }
57 
58  int width = f->width;
59  int height = f->height;
60  int tot = height * width;
61 
62  #ifdef PIC_DEBUG
63  printf("Init matrix...");
64  #endif
65 
66  std::vector< Eigen::Triplet< double > > tL;
67 
68  for(int i = 0; i < height; i++) {
69  int tmpI = i * width;
70 
71  for(int j = 0; j < width; j++) {
72  int indI = tmpI + j;
73 
74  tL.push_back(Eigen::Triplet< double > (indI, indI, 4.0f));
75 
76  if(((indI + 1) < tot) &&
77  ((indI % width) != (width - 1))) {
78 
79  tL.push_back(Eigen::Triplet< double > (indI, indI + 1, -1.0f));
80  tL.push_back(Eigen::Triplet< double > (indI + 1, indI, -1.0f));
81  }
82  }
83  }
84 
85  for(int i = 0; i < (tot - width); i++) {
86  tL.push_back(Eigen::Triplet< double > (i + width, i , -1.0f));
87  tL.push_back(Eigen::Triplet< double > (i , i + width, -1.0f));
88  }
89 
90  #ifdef PIC_DEBUG
91  printf("Ok\n");
92  #endif
93 
94  //solve the linear system for each color channel
95  Eigen::SparseMatrix<double> A = Eigen::SparseMatrix<double>(tot, tot);
96  A.setFromTriplets(tL.begin(), tL.end());
97  Eigen::SimplicialCholesky<Eigen::SparseMatrix<double> > solver(A);
98 
99  for(int k = 0; k < f->channels; k++) {
100 
101  Eigen::VectorXd b, x;
102  b = Eigen::VectorXd::Zero(tot);
103 
104  //copy values from f to b
105  for(int i = 0; i < height; i++) {
106  int tmpI = i * width;
107  for(int j = 0; j < width; j++) {
108  int indI = (tmpI + j);
109  b[indI] = - f->data[indI * f->channels + k];
110  }
111  }
112 
113  x = solver.solve(b);
114 
115  if(solver.info() != Eigen::Success) {
116  #ifdef PIC_DEBUG
117  printf("SOLVER FAILED!\n");
118  #endif
119 
120  return ret;
121  }
122 
123  #ifdef PIC_DEBUG
124  printf("SOLVER SUCCESS!\n");
125  #endif
126 
127  for(int i = 0; i < height; i++) {
128  int tmpI = i * width;
129 
130  for(int j = 0; j < width; j++) {
131  (*ret)(j, i)[k] = float(x(tmpI + j));
132  }
133  }
134  }
135 
136  return ret;
137 }
138 
139 #endif
140 
150  std::vector<int> coords,
151  int maxSteps = 100)
152 {
153  #ifdef PIC_DEBUG
154  printf("Iterative Poisson solver... ");
155  #endif
156 
157  if(maxSteps < 1) {
158  maxSteps = 100;
159  }
160 
161  Image *tmpImg = img->clone();
162  Image *tmpSwap = NULL;
163 
164  int c, x, y;
165 
166  for(int i = 0; i < maxSteps; i++) {
167  for(unsigned int j = 0; j < coords.size(); j++) {
168  int coord = coords[j];
169  img->reverseAddress(coord, x, y);
170 
171  float workValue = -laplacian->data[coord];
172 
173  c = img->getAddress(x + 1, y);
174  workValue += img->data[c];
175 
176  c = img->getAddress(x - 1, y);
177  workValue += img->data[c];
178 
179  c = img->getAddress(x, y + 1);
180  workValue += img->data[c];
181 
182  c = img->getAddress(x, y - 1);
183  workValue += img->data[c];
184 
185  tmpImg->data[coord] = workValue / 4.0f;
186  }
187 
188  tmpSwap = img;
189  img = tmpImg;
190  tmpImg = tmpSwap;
191  }
192 
193  #ifdef PIC_DEBUG
194  printf("done.\n");
195  #endif
196 
197  return img;
198 }
199 
200 } // end namespace pic
201 
202 
203 #endif /* PIC_ALGORITHMS_POISSON_SOLVER_HPP */
204 
void reverseAddress(int ind, int &x, int &y)
reverseAddress computes (x, y) given a memory address
Definition: image.hpp:680
float * data
data is the main buffer where pixel values are stored.
Definition: image.hpp:91
int channels
Definition: image.hpp:80
int getAddress(int x, int y)
getAddress calculates a memory address from (x, y)
Definition: image.hpp:650
PIC_INLINE Image * computePoissonSolverIterative(Image *img, Image *laplacian, std::vector< int > coords, int maxSteps=100)
computePoissonSolverIterative
Definition: poisson_solver.hpp:149
PIC_INLINE Image * computePoissonSolver(Image *f, Image *ret=NULL)
computePoissonSolver
Definition: poisson_solver.hpp:47
#define PIC_INLINE
Definition: base.hpp:33
The Image class stores an image as buffer of float.
Definition: image.hpp:60
Image * clone() const
Clone creates a deep copy of the calling instance.
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