PICCANTE  0.4
The hottest HDR imaging library!
filter_bilateral_2ds.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_FILTERING_FILTER_BILATERAL_2DS_HPP
19 #define PIC_FILTERING_FILTER_BILATERAL_2DS_HPP
20 
21 #include <random>
22 
23 #include "../base.hpp"
24 #include "../util/string.hpp"
25 #include "../util/std_util.hpp"
26 
27 #include "../filtering/filter.hpp"
28 #include "../util/precomputed_gaussian.hpp"
29 #include "../point_samplers/sampler_random_m.hpp"
30 
31 namespace pic {
32 
37 {
38 protected:
42  int seed;
43  int nSamples;
44 
51  void ProcessBBox(Image *dst, ImageVec src, BBox *box);
52 
53 public:
54 
59  {
60  seed = 1;
61  pg = NULL;
62  ms = NULL;
63  }
64 
66  {
67  delete_s(pg);
68  delete_s(ms);
69  }
70 
76  FilterBilateral2DS(std::string nameFile, float sigma_r);
77 
85  FilterBilateral2DS(float sigma_s, float sigma_r, int mult, SAMPLER_TYPE type);
86 
94  void update(float sigma_s, float sigma_r, int mult, SAMPLER_TYPE type);
95 
100  std::string signature()
101  {
102  return genBilString("S", sigma_s, sigma_r);
103  }
104 
110  bool Write(std::string filename);
111 
117  bool Read(std::string filename);
118 
126  static Image *execute(Image *imgIn,
127  float sigma_s, float sigma_r)
128  {
129  //create the filter
131  //filter
132  Image *imgOut = filter.Process(Single(imgIn), NULL);
133  return imgOut;
134  }
135 
144  static Image *execute(Image *imgIn, Image *imgEdge,
145  float sigma_s, float sigma_r)
146  {
148  Image *imgOut;
149 
150  if(imgEdge == NULL) {
151  imgOut = filter.Process(Single(imgIn), NULL);
152  } else {
153  imgOut = filter.Process(Double(imgIn, imgEdge), NULL);
154  }
155  return imgOut;
156  }
157 
163  static inline float getK(int kernelSize)
164  {
165  // float ret = 0.9577f/(0.6466f*float(kernelSize)-0.9175f)+0.4505;
166  float ret = 0.4055f / (0.6437f * float(kernelSize) - 1.1083f) + 0.7347f;
167  ret = (ret > 0.0f) ? ret : 3.0f;
168 
169  return ret;
170  }
171 
177  static inline float getK2(int kernelSize)
178  {
179  float ret = 0.3233f / (0.5053f * float(kernelSize) - 0.8272f) + 0.7366f;
180  ret = (ret > 0.0f) ? ret : 2.5f;
181  return ret;
182  }
183 
187  static void precomputeKernels()
188  {
189  for(int i = 0; i < 6; i++) {
190  float sigma_s = powf(2.0f, float(i));
191 
193  int nSamplesDiv2 = nSamples / 2;
194  int nMaxSamples = nSamplesDiv2 * nSamplesDiv2;
195  int oldNSamples = -1;
196 
197  printf("Compute kernel sigma_s: %f\n", sigma_s);
198 
199  for(int j = 1; j <= 16; j++) {
200  printf("Multiplier: %d\n", j);
201  nSamples = MIN((nSamplesDiv2 * j), nMaxSamples);
202 
203  if(nSamples == oldNSamples) {
204  break;
205  }
206 
207  FilterBilateral2DS f2DS(sigma_s, 0.01f, j, ST_BRIDSON);
208  f2DS.Write("kernel_" + fromNumberToString(sigma_s) + "_" + fromNumberToString(j) + ".txt");
209  oldNSamples = nSamples;
210  }
211  }
212  }
213 };
214 
216  float sigma_r) : Filter()
217 {
218  ms = NULL;
219  pg = NULL;
220  Read(nameFile);
221  this->sigma_r = sigma_r;
222 }
223 
225  float sigma_s, float sigma_r, int mult = 1, SAMPLER_TYPE type = ST_BRIDSON) : Filter()
226 {
227  pg = NULL;
228  ms = NULL;
229  update(sigma_s, sigma_r, mult, type);
230 }
231 
233  float sigma_r, int mult = 1, SAMPLER_TYPE type = ST_BRIDSON)
234 {
235  //protected values are assigned/computed
236  this->sigma_s = sigma_s > 0.0f ? sigma_s : 1.0f;
237  this->sigma_r = sigma_r > 0.0f ? sigma_r : 0.01f;
238  this->sigma_r_sq_2 = this->sigma_r * this->sigma_r * 2.0f;
239 
240  //Precomputation of the Gaussian Kernel
241  pg = delete_s(pg);
242  pg = new PrecomputedGaussian(sigma_s);//, sigma_r);
243 
244  //Poisson samples
245  int nMaxSamples = pg->halfKernelSize * pg->halfKernelSize;
246 
247  int nSamples = int(lround(float(pg->kernelSize)) * getK(int(sigma_s))) * mult;
248 
249  nSamples = MIN(nSamples, nMaxSamples);
250  // nSamples = MIN( (pg->halfKernelSize*mult), nMaxSamples);
251 
252 #ifdef PIC_DEBUG
253  printf("Nsamples: %d %f\n", nSamples, sigma_s);
254 #endif
255 
257 
258  ms = delete_s(ms);
259  ms = new MRSamplers<2>(type, window, nSamples, 1, 64);
260 
261  seed = 1;
262 }
263 
265  BBox *box)
266 {
267  Image *edge, *base;
268 
269  switch(src.size()) {
270  //cross bilateral filter
271  case 2:
272  base = src[0];
273  edge = src[1];
274  break;
275 
276  default:
277  base = src[0];
278  edge = src[0];
279  }
280 
281  int channels = dst->channels;
282  int edgeChannels = edge->channels;
283 
284  //Mersenne Twister
285  std::mt19937 m(seed);
286 
287  for(int j = box->y0; j < box->y1; j++) {
288  for(int i = box->x0; i < box->x1; i++) {
289  float *dst_data = (*dst )(i, j);
290  float *edge_data = (*edge)(i, j);
291 
292  Array<float>::assign(0.0f, dst_data, channels);
293 
294  RandomSampler<2> *ps = ms->getSampler(&m);
295  int nSamples = int(ps->samplesR.size());
296 
297  float sum = 0.0f;
298  for(int k = 0; k < nSamples; k += 2) {
299  //fetch addresses
300  int ci = i + ps->samplesR[k ];
301  int cj = j + ps->samplesR[k + 1];
302 
303  //
304  //fetch the precomputed Spatial Gaussian kernel
305  //
306  float G1 = pg->coeff[ps->samplesR[k ] + pg->halfKernelSize] *
307  pg->coeff[ps->samplesR[k + 1] + pg->halfKernelSize];
308 
309  float *edge_data_ci_cj = (*edge)(ci, cj);
310 
311  //
312  //compute the Range Gaussian kernel
313  //
314  float acc_delta_range_sq = Arrayf::distanceSq(edge_data_ci_cj, edge_data, edgeChannels);
315 
316  float G2 = exp(-acc_delta_range_sq / sigma_r_sq_2);
317 
318  //
319  //compute the final weight
320  //
321  float weight = G1 * G2;
322  sum += weight;
323 
324  float *base_data_ci_cj = (*base)(ci, cj);
325 
326  //filter
327  for(int l = 0; l < channels; l++) {
328  dst_data[l] += base_data_ci_cj[l] * weight;
329  }
330  }
331 
332  //normalization
333  if(sum > 0.0f) {
334  Arrayf::div(dst_data, channels, sum);
335  } else {
336  float *base_data = (*base)(i, j);
337  Arrayf::assign(base_data, channels, dst_data);
338  }
339 
340  }
341  }
342 }
343 
344 PIC_INLINE bool FilterBilateral2DS::Write(std::string nameFile)
345 {
346  //TODO: add the writing of (sigms_s, sigma_r)
347  return ms->Write(nameFile);
348 }
349 
350 PIC_INLINE bool FilterBilateral2DS::Read(std::string filename)
351 {
352  //TODO: add the reading of (sigms_s, sigma_r)
353  //Precomputation of the Gaussian Kernel
354  pg = delete_s(pg);
356 
357  ms = delete_s(ms);
358  ms = new MRSamplers<2>();
359  return ms->Read(filename);
360 }
361 
362 } // end namespace pic
363 
364 #endif /* PIC_FILTERING_FILTER_BILATERAL_2DS_HPP */
365 
The BBox class manages the creation of bounding boxes for images.
Definition: bbox.hpp:29
std::string fromNumberToString(T num)
fromNumberToString converts a number into a string.
Definition: string.hpp:102
static int getKernelSize(float sigma)
KernelSize computes the size of a kernel in pixel give its sigma.
Definition: precomputed_gaussian.hpp:121
int channels
Definition: image.hpp:80
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
bool Write(std::string name)
Write saves into an existing file.
Definition: sampler_random_m.hpp:217
std::vector< Image * > ImageVec
ImageVec an std::vector of pic::Image.
Definition: image_vec.hpp:29
int x0
Definition: bbox.hpp:32
PIC_INLINE long lround(double x)
lround rounds double numbers properly.
Definition: math.hpp:229
The MRSamplers class.
Definition: sampler_random_m.hpp:34
bool Write(std::string filename)
Write.
Definition: filter_bilateral_2ds.hpp:344
The Filter class.
Definition: filter.hpp:50
PrecomputedGaussian * pg
Definition: filter_bilateral_2ds.hpp:40
virtual Image * Process(ImageVec imgIn, Image *imgOut)
Process.
Definition: filter.hpp:390
static float getK(int kernelSize)
getK
Definition: filter_bilateral_2ds.hpp:163
float * coeff
Definition: precomputed_gaussian.hpp:67
void ProcessBBox(Image *dst, ImageVec src, BBox *box)
ProcessBBox.
Definition: filter_bilateral_2ds.hpp:264
Vec< 2, int > Vec2i
Vec2i.
Definition: vec.hpp:829
int nSamples
Definition: filter_bilateral_2ds.hpp:43
static T distanceSq(T *data0, T *data1, int n)
distanceSq
Definition: array.hpp:195
static float getK2(int kernelSize)
getK2
Definition: filter_bilateral_2ds.hpp:177
void update(float sigma_s, float sigma_r, int mult, SAMPLER_TYPE type)
update
Definition: filter_bilateral_2ds.hpp:232
int y0
Definition: bbox.hpp:32
bool Read(std::string name)
Read.
Definition: sampler_random_m.hpp:145
float sigma_s
Definition: filter_bilateral_2ds.hpp:39
RandomSampler< N > * getSampler(std::mt19937 *m)
getSampler gets a sampler at a given level
Definition: sampler_random_m.hpp:139
float sigma_r
Definition: filter_bilateral_2ds.hpp:39
PIC_INLINE ImageVec Double(Image *img1, Image *img2)
Double creates an std::vector which contains img1 and img2; this is for filters input.
Definition: image_vec.hpp:49
FilterBilateral2DS()
FilterBilateral2DS.
Definition: filter_bilateral_2ds.hpp:58
~FilterBilateral2DS()
Definition: filter_bilateral_2ds.hpp:65
std::string genBilString(std::string type, float sigma_s, float sigma_r)
genBilString
Definition: string.hpp:366
#define PIC_INLINE
Definition: base.hpp:33
SAMPLER_TYPE
Definition: point_samplers.hpp:51
std::vector< int > samplesR
Definition: sampler_random.hpp:53
static Image * execute(Image *imgIn, Image *imgEdge, float sigma_s, float sigma_r)
execute
Definition: filter_bilateral_2ds.hpp:144
#define MIN(a, b)
Definition: math.hpp:69
The Image class stores an image as buffer of float.
Definition: image.hpp:60
std::string signature()
signature
Definition: filter_bilateral_2ds.hpp:100
static void div(T *data, int size, T value)
div
Definition: array.hpp:353
The PrecomputedGaussian class.
Definition: precomputed_gaussian.hpp:30
int halfKernelSize
Definition: precomputed_gaussian.hpp:66
virtual void f(FilterFData *data)
f
Definition: filter_radial_basis_function.hpp:69
Definition: point_samplers.hpp:51
int kernelSize
Definition: precomputed_gaussian.hpp:66
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
static T * assign(T *data, int size, T *ret)
assign
Definition: array.hpp:464
static Image * execute(Image *imgIn, float sigma_s, float sigma_r)
execute
Definition: filter_bilateral_2ds.hpp:126
int seed
Definition: filter_bilateral_2ds.hpp:42
static void precomputeKernels()
PrecomputedKernels.
Definition: filter_bilateral_2ds.hpp:187
The RandomSampler class.
Definition: sampler_random.hpp:43
bool Read(std::string filename)
Read.
Definition: filter_bilateral_2ds.hpp:350
float sigma_r_sq_2
Definition: filter_bilateral_2ds.hpp:39
MRSamplers< 2 > * ms
Definition: filter_bilateral_2ds.hpp:41
The Vec class.
Definition: vec.hpp:35
The FilterBilateral2DS class.
Definition: filter_bilateral_2ds.hpp:36