PICCANTE  0.4
The hottest HDR imaging library!
poisson_filling.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_FILLING_HPP
19 #define PIC_ALGORITHMS_POISSON_FILLING_HPP
20 
21 #include "../util/std_util.hpp"
22 #include "../util/buffer.hpp"
23 #include "../util/mask.hpp"
24 #include "../util/array.hpp"
25 #include "../util/math.hpp"
26 #include "../image.hpp"
27 
28 namespace pic {
29 
34 {
35 protected:
36  int maxIter;
37  float threshold, value;
38 
39  bool *mask, *maskPoisson;
41 
45  void release()
46  {
50  }
51 
57  void update(Image *imgOut, Image *imgIn)
58  {
59  imgOut->assign(imgIn);
60 
61  #pragma omp parallel for
62 
63  for(int i = 0; i < imgIn->height; i++) {
64  for(int j = 0; j < imgIn->width; j++) {
65  float *src = (*imgIn)(j, i);
66  float *n0 = (*imgIn)(j + 1, i);
67  float *n1 = (*imgIn)(j - 1, i);
68  float *n2 = (*imgIn)(j, i + 1);
69  float *n3 = (*imgIn)(j, i - 1);
70 
71  int ind = i * imgIn->width + j;
72 
73  float *out = (*imgOut)(j, i);
74 
75  for(int k = 0; k < imgIn->channels; k++) {
76 
77  if(equalf(src[k], value)) {
78  int div = 0;
79 
80  out[k] = 0.0f;
81 
82  if(!equalf(n0[k], value)) {
83  out[k] += n0[k];
84  div++;
85  }
86 
87  if(!equalf(n1[k], value)) {
88  out[k] += n1[k];
89  div++;
90  }
91 
92  if(!equalf(n2[k], value)) {
93  out[k] += n2[k];
94  div++;
95  }
96 
97  if(!equalf(n3[k], value)) {
98  out[k] += n3[k];
99  div++;
100  }
101 
102  if(div > 0) {
103  out[k] = out[k] / float(div);
104  mask[ind] = false;
105  }
106  } else { //Poisson solver
107  if(maskPoisson[ind]) {
108  int div = 0;
109  float tmp = 0.0f;
110 
111  if(!equalf(n0[k], value)) {
112  tmp += -src[k] + n0[k];
113  div++;
114  }
115 
116  if(!equalf(n1[k], value)) {
117  tmp += -src[k] + n1[k];
118  div++;
119  }
120 
121  if(!equalf(n2[k], value)) {
122  tmp += -src[k] + n2[k];
123  div++;
124  }
125 
126  if(!equalf(n3[k], value)) {
127  tmp += -src[k] + n3[k];
128  div++;
129  }
130 
131  out[k] = src[k] + tmp / float(div);
132  }
133  }
134  }
135  }
136  }
137  }
138 
139 public:
140 
145  {
146  imgTmp = NULL;
147  mask = NULL;
148  maskPoisson = NULL;
149 
150  this->value = value;
151  threshold = 1e-4f;
152 
153  maxIter = 1000;
154  }
155 
157  {
158  release();
159  }
160 
165  void setup(float value)
166  {
167  this->value = value;
168  }
169 
177  Image *execute(Image *imgIn, Image *imgOut, bool *mask = NULL)
178  {
179  if(imgIn == NULL) {
180  return NULL;
181  }
182 
183  if(!imgIn->isValid()) {
184  return NULL;
185  }
186 
187  if(imgTmp != NULL) {
188  if(!imgTmp->isSimilarType(imgIn)) {
189  release();
190  imgTmp = imgIn->clone();
191  }
192  } else {
193  imgTmp = imgIn->clone();
194  }
195 
196  if(imgOut == NULL) {
197  imgOut = imgIn->clone();
198  } else {
199  imgOut->assign(imgIn);
200  }
201 
202  if(mask == NULL) {
203  float *color = Arrayf::genValue(value, 3, NULL);
204 
205  mask = imgIn->convertToMask(color, threshold, false, NULL);
206 
207  delete_vec_s(color);
208  }
209 
211 
212  Image *work[2];
213  work[0] = imgTmp;
214  work[1] = imgOut;
215 
216  int i = 0;
217 
218  while(!Mask::empty(mask, imgIn->width, imgIn->height)) {
219  update(work[i % 2], work[(i + 1) % 2]);
220  i++;
221 
222  if(i > maxIter) {
223  break;
224  }
225  }
226 
227  if((i % 2) == 1) {
228  imgOut->assign(imgTmp);
229  }
230 
231  return imgOut;
232  }
233 };
234 
235 } // end namespace pic
236 
237 #endif /* PIC_ALGORITHMS_POISSON_FILLING_HPP */
238 
Image * execute(Image *imgIn, Image *imgOut, bool *mask=NULL)
execute
Definition: poisson_filling.hpp:177
bool * maskPoisson
Definition: poisson_filling.hpp:39
void assign(const Image *imgIn)
assign
Image * imgTmp
Definition: poisson_filling.hpp:40
static bool * clone(bool *bufferOut, bool *bufferIn, int n, int channels)
clone
Definition: filter_radial_basis_function.hpp:704
int channels
Definition: image.hpp:80
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
~PoissonFilling()
Definition: poisson_filling.hpp:156
bool isSimilarType(const Image *img)
isSimilarType checks if the current image is similar to img; i.e. if they have the same width...
static T * genValue(T value, int n, T *ret)
genValue
Definition: array.hpp:132
T * delete_vec_s(T *data)
delete_vec_s
Definition: std_util.hpp:138
void update(Image *imgOut, Image *imgIn)
update
Definition: poisson_filling.hpp:57
The PoissonFilling class.
Definition: poisson_filling.hpp:33
float threshold
Definition: poisson_filling.hpp:37
int nPixels() const
nPixels computes the number of pixels.
Definition: image.hpp:499
float value
Definition: poisson_filling.hpp:37
PoissonFilling(float value)
PoissonFilling.
Definition: poisson_filling.hpp:144
bool * convertToMask(float *color, float threshold, bool cmp, bool *mask)
convertToMask converts an Image into a boolean mask.
static bool empty(bool *dataIn, int width, int height)
MaskEmpty checks if a mask is empty.
Definition: mask.hpp:183
The Image class stores an image as buffer of float.
Definition: image.hpp:60
bool * mask
Definition: poisson_filling.hpp:39
Image * clone() const
Clone creates a deep copy of the calling instance.
void release()
release
Definition: poisson_filling.hpp:45
int maxIter
Definition: poisson_filling.hpp:36
Definition: bilateral_separation.hpp:25
bool isValid()
isValid checks if the current image is valid, which means if they have an allocated buffer or not...
PIC_INLINE bool equalf(float a, float b)
equalf checks if two float values are the same or not.
Definition: math.hpp:119
int width
Definition: image.hpp:80
int height
Definition: image.hpp:80
void setup(float value)
setup
Definition: poisson_filling.hpp:165