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_GL_FILTERING_FILTER_BILATERAL_2DS_HPP
19 #define PIC_GL_FILTERING_FILTER_BILATERAL_2DS_HPP
20 
21 #include "../../util/std_util.hpp"
22 
23 #include "../../gl/filtering/filter.hpp"
24 #include "../../util/file_lister.hpp"
25 #include "../../gl/point_samplers/sampler_random_m.hpp"
26 
27 namespace pic {
28 
30 
37 {
38  int ret = -1;
39  switch(type) {
40  case BF_CLASSIC:
41  ret = 0;
42  break;
43 
44  case BF_CROSS:
45  ret = 1;
46  break;
47 
48  case BF_BRUSH:
49  ret = 2;
50  break;
51 
52  default:
53  ret = 0;
54  break;
55  }
56 
57  return ret;
58 }
59 
64 {
65 protected:
66  float sigma_s, sigma_r;
68 
69  //Random numbers tile
72  //Fragment Brush
73  std::vector<std::string> fragment_sources;
74 
75  void initShaders();
76  void FragmentShader();
77 
78 public:
86 
88 
95  void update(float sigma_s, float sigma_r, BF_TYPE type);
96 
100  void releaseAux()
101  {
103  delete_s(ms);
104  }
105 
113  static ImageGL *execute(ImageGL *imgIn, float sigma_s, float sigma_r)
114  {
116  BF_CLASSIC);
117 
118  ImageGL *imgOut = filter->Process(SingleGL(imgIn), NULL);
119 
120  delete filter;
121  return imgOut;
122  }
123 
133  static ImageGL *execute(std::string nameFile, std::string nameOut,
134  float sigma_s, float sigma_r, int testing = 1)
135  {
136  ImageGL imgIn(nameFile);
137  imgIn.generateTextureGL(GL_TEXTURE_2D, GL_FLOAT, false);
138 
140  BF_CLASSIC);
141 
142  ImageGL *imgOut = new ImageGL(1, imgIn.width, imgIn.height, imgIn.channels,
143  IMG_GPU_CPU, GL_TEXTURE_2D);
144 
145  GLuint testTQ1;
146 
147  if(testing > 1) {
148  filter->Process(SingleGL(&imgIn), imgOut);
149 
150  testTQ1 = glBeginTimeQuery();
151 
152  for(int i = 0; i < testing; i++) {
153  filter->Process(SingleGL(&imgIn), imgOut);
154  }
155  } else {
156  testTQ1 = glBeginTimeQuery();
157  filter->Process(SingleGL(&imgIn), imgOut);
158  }
159 
160  GLuint64EXT timeVal = glEndTimeQuery(testTQ1);
161  double ms = double(timeVal) / (double(testing) * 1000000.0);
162  printf("Stochastic Bilateral Filter on GPU time: %f ms\n", ms);
163 
164  std::string nameTime = FileLister::getFileNumber(genBilString("S", sigma_s,
165  sigma_r), "txt");
166 
167  FILE *file = fopen(nameTime.c_str(), "w");
168 
169  if(file != NULL) {
170  fprintf(file, "%f", ms);
171  fclose(file);
172  }
173 
174  //Read from the GPU
175  imgOut->loadToMemory();
176  imgOut->Write(nameOut);
177 
178  return imgOut;
179  }
180 
188  {
189  imgOut = allocateOutputMemory(imgIn, imgOut, false);
190  return imgOut;
191  }
192 };
193 
195  BF_TYPE type = BF_CLASSIC): FilterGL()
196 {
197  ms = NULL;
198  imageRand = NULL;
199 
200  this->type = type;
201 
202  FragmentShader();
203 
204  initShaders();
205 
206  update(sigma_s, sigma_r, type);
207 }
208 
210 {
211  release();
212 }
213 
215 {
216  std::string fragment_source_classic = MAKE_STRING
217  (
218  uniform sampler2D u_tex;
219  uniform isampler2D u_poisson;
220  uniform sampler2D u_rand;
221  uniform int nSamples;
222  uniform float sigma_s_sq_2;
223  uniform float sigma_r_sq_2;
224  uniform int kernelSize;
225  uniform float kernelSizef;
226  out vec4 f_color;
227 
228  void main(void) {
229  vec3 color = vec3(0.0, 0.0, 0.0);
230  ivec2 coordsFrag = ivec2(gl_FragCoord.xy);
231  vec3 tmpCol;
232 
233  vec3 colRef = texelFetch(u_tex, coordsFrag, 0).xyz;
234  float weight = 0.0;
235 
236  float shifter = texture(u_rand, gl_FragCoord.xy).x;
237 
238  for(int i = 0; i < nSamples; i++) {
239  //Coordinates
240  ivec3 coords = texelFetch(u_poisson, ivec2(i, shifter), 0).xyz;
241 
242  //Texture fetch
243  tmpCol = texelFetch(u_tex, coordsFrag.xy + coords.xy, 0).xyz;
244  vec3 tmpCol2 = tmpCol - colRef;
245  float dstR = dot(tmpCol2.xyz, tmpCol2.xyz);
246  int coordsz = coords.x * coords.x + coords.y * coords.y;
247  float tmp = exp(-dstR / sigma_r_sq_2 - float(coordsz) / sigma_s_sq_2);
248  color.xyz += tmpCol * tmp;
249  weight += tmp;
250  }
251 
252  f_color = vec4(weight > 0 ? (color / weight) : colRef, 1.0);
253  }
254  );
255 
256  std::string fragment_source_cross = MAKE_STRING
257  (
258  uniform sampler2D u_tex;
259  uniform sampler2D u_edge;
260  uniform isampler2D u_poisson;
261  uniform sampler2D u_rand;
262  uniform int nSamples;
263  uniform float sigma_s_sq_2;
264  uniform float sigma_r_sq_2;
265  out vec4 f_color;
266 
267  void main(void) {
268  vec3 color = vec3(0.0, 0.0, 0.0);
269  ivec2 coordsFrag = ivec2(gl_FragCoord.xy);
270 
271  vec3 colRef = texelFetch(u_tex, coordsFrag, 0).xyz;
272  vec3 edgeRef = texelFetch(u_edge, coordsFrag, 0).xyz;
273 
274  float weight = 0.0;
275  float shifter = texture(u_rand, gl_FragCoord.xy, 0).x;
276 
277  for(int i = 0; i < nSamples; i++) {
278  //Coordinates
279  ivec3 coords = texelFetch(u_poisson, ivec2(i, shifter), 0).xyz;
280 
281  //Range difference
282  vec3 tmpEdge = texelFetch(u_edge, coordsFrag.xy + coords.xy, 0).xyz;
283  vec3 tmpEdge2 = tmpEdge - edgeRef;
284  float dstR = dot(tmpEdge2.xyz, tmpEdge2.xyz);
285  float tmp = exp(-dstR / sigma_r_sq_2 - float(coords.z) / sigma_s_sq_2);
286 
287  //Texture Fetch
288  vec3 tmpCol = texelFetch(u_tex, coordsFrag.xy + coords.xy, 0).xyz;
289  color.xyz += tmpCol * tmp;
290  weight += tmp;
291  }
292 
293  f_color = vec4(weight > 0.0 ? color / weight : colRef, 1.0);
294  }
295  );
296 
297  std::string fragment_source_brush = MAKE_STRING
298  (
299  uniform sampler2D u_tex;
300  uniform isampler2D u_poisson;
301  uniform sampler2D u_rand;
302  uniform sampler2D u_mask;
303  uniform int nSamples;
304  uniform float sigma_s_sq_2;
305  uniform float sigma_r_sq_2;
306  out vec4 f_color;
307 
308  void main(void) {
309  vec3 color = vec3(0.0, 0.0, 0.0);
310  ivec2 coordsFrag = ivec2(gl_FragCoord.xy);
311  vec3 tmpCol;
312 
313  float w = texelFetch(u_mask, coordsFrag, 0).x;
314  vec3 colRef = texelFetch(u_tex, coordsFrag, 0).xyz;
315 
316  if(w > 0.0f) {
317  w = min(w, 1.0f);
318  float weight = 0.0;
319  float shifter = texture(u_rand, gl_FragCoord.xy, 0).x;
320 
321  for(int i = 0; i < nSamples; i++) {
322  //Coordinates
323  ivec3 coords = texelFetch(u_poisson, ivec2(i, shifter), 0).xyz;
324  //Texture fetch
325  tmpCol = texelFetch(u_tex, coordsFrag.xy + coords.xy, 0).xyz;
326  vec3 tmpCol2 = tmpCol - colRef;
327  float dstR = dot(tmpCol2.xyz, tmpCol2.xyz);
328  float tmp = exp(-dstR / sigma_r_sq_2 - float(coords.z) / sigma_s_sq_2);
329  color.xyz += tmpCol * tmp;
330  weight += tmp;
331  }
332 
333  color = weight > 0.0 ? color / weight : colRef;
334  f_color = vec4(color.xyz * w + (1 - w) * colRef.xyz, 1.0);
335  } else {
336  f_color = vec4(colRef.xyz, 1.0);
337  }
338  }
339  );
340 
341  fragment_sources.push_back(fragment_source_classic);
342  fragment_sources.push_back(fragment_source_cross);
343  fragment_sources.push_back(fragment_source_brush);
344 }
345 
347 {
348  technique.initStandard("330", vertex_source, fragment_sources[getValueBF(type)], "FilterGLBilateral2DS");
349 }
350 
351 PIC_INLINE void FilterGLBilateral2DS::update(float sigma_s, float sigma_r, BF_TYPE type)
352 {
353  this->type = type;
354 
355  bool flag = false;
356 
357  if(sigma_s > 0.0f) {
358  flag = (this->sigma_s != sigma_s);
359  this->sigma_s = sigma_s;
360  }
361 
362  if(sigma_r > 0.0f) {
363  flag = flag || (this->sigma_r != sigma_r);
364  this->sigma_r = sigma_r;
365  }
366 
367  int kernelSize = PrecomputedGaussian::getKernelSize(this->sigma_s);
368  int halfKernelSize = kernelSize >> 1;
369 
370  //Poisson samples
371 #ifdef PIC_DEBUG
372  printf("Window: %d\n", halfKernelSize);
373 #endif
374 
375  if(imageRand == NULL) {
376  imageRand = new ImageGL(1, 128, 128, 1, IMG_CPU, GL_TEXTURE_2D);
377  imageRand->setRand(1);
379  *imageRand -= 0.5f;
380  }
381 
382  if(flag) {
383  int nSamplers = 1;
384  Vec2i window = Vec2i(halfKernelSize, halfKernelSize);
385 
386  if(ms == NULL) {
387  ms = new MRSamplersGL<2>(ST_BRIDSON, window, halfKernelSize, 1,
388  nSamplers);
389  ms->generateTexture();
390  } else {
391  ms->updateGL(window, halfKernelSize);
392  param.clear();
393  }
394 
395  #ifdef PIC_DEBUG
396  printf("Number of samples: %d\n", ms->nSamples);
397  #endif
398 
399  if(param.empty()) {
400  param.push_back(ms->getImage());
401  param.push_back(imageRand);
402  }
403  }
404 
405  //shader update
406  float sigma_s_sq_2 = 2.0f * this->sigma_s * this->sigma_s;
407  float sigma_r_sq_2 = 2.0f * this->sigma_r * this->sigma_r;
408 
409  technique.bind();
410  technique.setUniform1i("u_tex", 0);
411 
412  if(type == BF_CROSS) {
413  technique.setUniform1i("u_edge", 1);
414  technique.setUniform1i("u_poisson", 2);
415  technique.setUniform1i("u_rand", 3);
416  technique.setUniform1i("u_mask", 4);
417  } else {
418  technique.setUniform1i("u_poisson", 1);
419  technique.setUniform1i("u_rand", 2);
420  technique.setUniform1i("u_mask", 3);
421  }
422 
423  technique.setUniform1f("sigma_s_sq_2", sigma_s_sq_2);
424  technique.setUniform1f("sigma_r_sq_2", sigma_r_sq_2);
425  technique.setUniform1i("kernelSize", kernelSize);
426  technique.setUniform1f("kernelSizef", float(kernelSize));
427  technique.setUniform1i("nSamples", ms->nSamples >> 1);
428  technique.unbind();
429 }
430 
431 } // end namespace pic
432 
433 #endif /* PIC_GL_FILTERING_FILTER_BILATERAL_2DS_HPP */
434 
static std::string getFileNumber(std::string nameFile, std::string nameExt)
Definition: file_lister.hpp:36
static ImageGL * execute(ImageGL *imgIn, float sigma_s, float sigma_r)
execute
Definition: filter_bilateral_2ds.hpp:113
TechniqueGL technique
Definition: display.hpp:45
Definition: image.hpp:37
int channels
Definition: filter_radial_basis_function.hpp:80
static int getKernelSize(float sigma)
KernelSize computes the size of a kernel in pixel give its sigma.
Definition: precomputed_gaussian.hpp:121
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
ImageGL * setupAux(ImageGLVec imgIn, ImageGL *imgOut)
setupAux
Definition: filter_bilateral_2ds.hpp:187
GLuint generateTextureGL(GLenum target, GLenum format_type, bool mipmap)
generateTextureGL
ImageGL * allocateOutputMemory(ImageGLVec imgIn, ImageGL *imgOut, bool bDelete)
allocateOutputMemory
Definition: display.hpp:217
void bind()
bind
Definition: display.hpp:189
GLuint glBeginTimeQuery()
glBeginTimeQuery
Definition: timings.hpp:29
#define MAKE_STRING(input_string)
Definition: filter_bilateral_2ds.hpp:29
PIC_INLINE ImageGLVec SingleGL(ImageGL *img)
SingleGL creates a single for filters input.
Definition: image_vec.hpp:39
Definition: image.hpp:37
ImageGL * imageRand
Definition: filter_bilateral_2ds.hpp:71
void releaseAux()
releaseAux
Definition: filter_bilateral_2ds.hpp:100
GLuint64 glEndTimeQuery(GLuint64 ret)
glEndTimeQuery
Definition: timings.hpp:46
Definition: filter_bilateral_2ds.hpp:29
std::vector< std::string > fragment_sources
Definition: filter_bilateral_2ds.hpp:73
The ImageGL class.
Definition: image.hpp:42
Vec< 2, int > Vec2i
Vec2i.
Definition: vec.hpp:829
Definition: filter_bilateral_2ds.hpp:29
bool Write(std::string nameFile, LDR_type typeWrite, int writerCounter)
Write saves an Image into a file on the disk.
Definition: filter_radial_basis_function.hpp:1924
PIC_INLINE int getValueBF(BF_TYPE type)
getValueBF
Definition: filter_bilateral_2ds.hpp:36
void setUniform1f(const char *name_uniform, float value0)
SetUniform1f.
Definition: display.hpp:247
BF_TYPE type
Definition: filter_bilateral_2ds.hpp:67
virtual ImageGL * Process(ImageGLVec imgIn, ImageGL *imgOut)
Process.
Definition: display.hpp:258
The FilterGLBilateral2DS class.
Definition: filter_bilateral_2ds.hpp:63
float sigma_s
Definition: filter_bilateral_2ds.hpp:66
void updateGL(Vec< N, int > window, int nSamples)
updateGL
Definition: sampler_random_m.hpp:129
MRSamplersGL< 2 > * ms
Definition: filter_bilateral_2ds.hpp:70
The FilterGL class.
Definition: filter.hpp:35
BF_TYPE
Definition: filter_bilateral_2ds.hpp:29
void setRand(unsigned int seed)
setRand
Definition: filter_radial_basis_function.hpp:1392
GLuint generateTexture()
generateTexture
Definition: sampler_random_m.hpp:151
std::string genBilString(std::string type, float sigma_s, float sigma_r)
genBilString
Definition: string.hpp:366
The FilterGL class.
Definition: display.hpp:35
The MRSamplersGL class.
Definition: sampler_random_m.hpp:45
#define PIC_INLINE
Definition: base.hpp:33
static ImageGL * execute(std::string nameFile, std::string nameOut, float sigma_s, float sigma_r, int testing=1)
execute
Definition: filter_bilateral_2ds.hpp:133
The ImageGL class.
Definition: display.hpp:42
The Vec class.
Definition: display.hpp:35
int width
Definition: filter_radial_basis_function.hpp:80
bool initStandard(std::string version_number, std::string vertex_shader_source, std::string fragment_shader_source, std::string name)
initStandard
Definition: display.hpp:114
ImageGLVec param
Definition: display.hpp:49
Definition: point_samplers.hpp:51
void unbind()
unbind
Definition: display.hpp:197
void loadToMemory()
loadToMemory
std::string vertex_source
Definition: display.hpp:57
Definition: bilateral_separation.hpp:25
BF_TYPE
Definition: display.hpp:29
FilterGLBilateral2DS(float sigma_s, float sigma_r, BF_TYPE type)
FilterGLBilateral2DS.
int nSamples
Definition: display.hpp:53
float sigma_r
Definition: filter_bilateral_2ds.hpp:66
ImageGL * getImage()
getImage
Definition: display.hpp:89
void update(float sigma_s, float sigma_r, BF_TYPE type)
update
std::vector< ImageGL * > ImageGLVec
ImageGLVec an std::vector of pic::ImageGL.
Definition: image_vec.hpp:32
int height
Definition: filter_radial_basis_function.hpp:80
void release()
release
Definition: display.hpp:85
void setUniform1i(const char *name_uniform, int value0)
SetUniform.
Definition: display.hpp:236
void loadFromMemory()
loadFromMemory