Visual Servoing Platform  version 3.6.1 under development (2025-02-17)
vpPanda3DDepthFilters.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30 
31 #include <visp3/rbt/vpPanda3DDepthFilters.h>
32 
33 #if defined(VISP_HAVE_PANDA3D)
34 
35 #include "graphicsOutput.h"
36 #include "graphicsEngine.h"
37 #include "windowFramework.h"
38 
39 BEGIN_VISP_NAMESPACE
40 
41 const std::string vpPanda3DDepthGaussianBlur::FRAGMENT_SHADER =
42 "#version 330\n"
43 "\n"
44 "in vec2 texcoords;\n"
45 "\n"
46 "uniform sampler2D p3d_Texture0;\n"
47 "uniform vec2 dp; // 1 divided by number of pixels\n"
48 "\n"
49 "const float kernel[25] = float[25](\n"
50 " 2, 4, 5, 4, 2,\n"
51 " 4, 9, 12, 9, 4,\n"
52 " 5, 12, 15, 12, 5,\n"
53 " 4, 9, 12, 9, 4,\n"
54 " 2, 4, 5, 4, 2\n"
55 ");\n"
56 "const float normalize = 1 / 159.0;\n"
57 "\n"
58 "vec2 offset[25] = vec2[25](\n"
59 " vec2(-2*dp.x,-2*dp.y), vec2(-dp.x,-2*dp.y), vec2(0,-2*dp.y), vec2(dp.x,-2*dp.y), vec2(2*dp.x,-2*dp.y),\n"
60 " vec2(-2*dp.x,-dp.y), vec2(-dp.x, -dp.y), vec2(0.0, -dp.y), vec2(dp.x, -dp.y), vec2(2*dp.x,-dp.y),\n"
61 " vec2(-2*dp.x,0.0), vec2(-dp.x, 0.0), vec2(0.0, 0.0), vec2(dp.x, 0.0), vec2(2*dp.x,0.0),\n"
62 " vec2(-2*dp.x, dp.y), vec2(-dp.x, dp.y), vec2(0.0, dp.y), vec2(dp.x, dp.y), vec2(2*dp.x, dp.y),\n"
63 " vec2(-2*dp.x, 2*dp.y), vec2(-dp.x, 2*dp.y), vec2(0.0, 2*dp.y), vec2(dp.x, 2*dp.y), vec2(2*dp.x, 2*dp.y)\n"
64 ");\n"
65 "\n"
66 "out vec4 p3d_FragData;\n"
67 "\n"
68 "void main() {\n"
69 " float v = 0.f;\n"
70 "\n"
71 " for(int i = 0; i < 25; ++i) {\n"
72 " v += kernel[i] * texture(p3d_Texture0, texcoords + offset[i]).a;\n"
73 " }\n"
74 " p3d_FragData.a = v * normalize;\n"
75 "}\n"
76 ")\n";
77 
78 vpPanda3DDepthGaussianBlur::vpPanda3DDepthGaussianBlur(const std::string &name, std::shared_ptr<vpPanda3DBaseRenderer> inputRenderer, bool isOutput)
79  : vpPanda3DPostProcessFilter(name, inputRenderer, isOutput, vpPanda3DDepthGaussianBlur::FRAGMENT_SHADER)
80 { }
81 
83 {
84  FrameBufferProperties fbp;
85  fbp.set_depth_bits(0);
86  fbp.set_rgba_bits(0, 0, 0, 32);
87  fbp.set_float_color(true);
88  return fbp;
89 }
90 
92 {
94 }
95 
96 const std::string vpPanda3DDepthCannyFilter::FRAGMENT_SHADER =
97 "#version 330\n"
98 "\n"
99 "in vec2 texcoords;\n"
100 "\n"
101 "uniform sampler2D p3d_Texture0;\n"
102 "uniform vec2 dp; // 1 divided by number of pixels\n"
103 "uniform float edgeThreshold;\n"
104 "\n"
105 "const float kernel[9] = float[9](\n"
106 " 0.0, 1.0, 0.0,\n"
107 " 1.0,-4.0, 1.0,\n"
108 " 0.0, 1.0, 0.0\n"
109 ");\n"
110 "\n"
111 "const float kernel_h[9] = float[9](\n"
112 " -1.0, 0.0, 1.0,\n"
113 " -2.0, 0.0, 2.0,\n"
114 " -1.0, 0.0, 1.0\n"
115 ");\n"
116 "\n"
117 "const float kernel_v[9] = float[9](\n"
118 " -1.0, -2.0, -1.0,\n"
119 " 0.0, 0.0, 0.0,\n"
120 " 1.0, 2.0, 1.0\n"
121 ");\n"
122 "\n"
123 "vec2 offset[9] = vec2[9](\n"
124 " vec2(-dp.x, -dp.y), vec2(0.0, -dp.y), vec2(dp.x, -dp.y),\n"
125 " vec2(-dp.x, 0.0), vec2(0.0, 0.0), vec2(dp.x, 0.0),\n"
126 " vec2(-dp.x, dp.y), vec2(0.0, dp.y), vec2(dp.x, dp.y)\n"
127 ");\n"
128 "\n"
129 "float textureValues[9];\n"
130 "\n"
131 "out vec4 p3d_FragData;\n"
132 "\n"
133 "void main() {\n"
134 " if(texture(p3d_Texture0, texcoords).a == 0) {\n"
135 " p3d_FragData = vec4(0.f, 0.f, 0.f, 0.f);\n"
136 " } else {\n"
137 " float sum = 0.f;\n"
138 " for(int i = 0; i < 9; ++i) {\n"
139 " float pix = texture(p3d_Texture0, texcoords + offset[i]).a;\n"
140 " pix = (pix < 1e-5f ? 1000.f: pix);\n"
141 " textureValues[i] = pix;\n"
142 " sum += pix * kernel[i];\n"
143 " }\n"
144 " if(abs(sum) > edgeThreshold) {\n"
145 " float sum_h = 0.f;\n"
146 " float sum_v = 0.f;\n"
147 " for(int i = 0; i < 9; ++i) {\n"
148 " float pix = textureValues[i];\n"
149 " sum_h += pix * kernel_h[i];\n"
150 " sum_v += pix * kernel_v[i];\n"
151 " }\n"
152 " float norm = sqrt(sum_v * sum_v + sum_h * sum_h);\n"
153 " vec2 orientationAndValid = (sum_h != 0.f) ? vec2(atan(sum_v, -sum_h), 1.f) : vec2(0.f, 0.f);\n"
154 " p3d_FragData.bgra = vec4(sum_h, sum_v, orientationAndValid.x, orientationAndValid.y);\n"
155 " } else {\n"
156 " p3d_FragData = vec4(0.f, 0.f, 0.f, 0.f);\n"
157 " }\n"
158 " }\n"
159 "}\n";
160 
161 vpPanda3DDepthCannyFilter::vpPanda3DDepthCannyFilter(const std::string &name, std::shared_ptr<vpPanda3DBaseRenderer> inputRenderer, bool isOutput, float edgeThreshold)
162  : vpPanda3DPostProcessFilter(name, inputRenderer, isOutput, vpPanda3DDepthCannyFilter::FRAGMENT_SHADER), m_edgeThreshold(edgeThreshold)
163 { }
164 
166 {
168  m_renderRoot.set_shader_input("edgeThreshold", LVector2f(m_edgeThreshold));
169 }
170 
172 {
173  m_edgeThreshold = edgeThreshold;
174  m_renderRoot.set_shader_input("edgeThreshold", LVector2f(m_edgeThreshold));
175 }
176 
177 
179 {
180  FrameBufferProperties fbp;
181  fbp.set_depth_bits(0);
182  fbp.set_rgba_bits(32, 32, 32, 32);
183  fbp.set_float_color(true);
184  return fbp;
185 }
186 
188 {
189  if (!m_isOutput) {
190  throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
191  }
192 
194 
195  valid.resize(I.getHeight(), I.getWidth());
196  const unsigned numComponents = m_texture->get_num_components();
197  int rowIncrement = I.getWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
198  float *data = (float *)(&(m_texture->get_ram_image().front()));
199  // Panda3D stores data upside down
200  data += rowIncrement * (I.getHeight() - 1);
201  rowIncrement = -rowIncrement;
202  if (numComponents != 4) {
203  throw;
204  }
205  for (unsigned int i = 0; i < I.getHeight(); ++i) {
206  vpRGBf *colorRow = I[i];
207  unsigned char *validRow = valid[i];
208  for (unsigned int j = 0; j < I.getWidth(); ++j) {
209  colorRow[j].R = data[j * numComponents];
210  colorRow[j].G = data[j * numComponents + 1];
211  colorRow[j].B = data[j * numComponents + 2];
212  validRow[j] = static_cast<unsigned char>(data[j * numComponents + 3]);
213  }
214  data += rowIncrement;
215  }
216 }
217 
218 void vpPanda3DDepthCannyFilter::getRender(vpImage<vpRGBf> &I, vpImage<unsigned char> &valid, const vpRect &bb, unsigned int h, unsigned w) const
219 {
220  if (!m_isOutput) {
221  throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
222  }
223 
224  I.resize(h, w, 0.f);
225  valid.resize(I.getHeight(), I.getWidth(), 0);
226 
227  const unsigned top = static_cast<unsigned int>(std::max(0.0, bb.getTop()));
228  const unsigned left = static_cast<unsigned int>(std::max(0.0, bb.getLeft()));
229  const unsigned numComponents = m_texture->get_num_components();
230  const unsigned rowIncrement = m_renderParameters.getImageWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
231 
232  const float *data = (float *)(&(m_texture->get_ram_image().front()));
233  data += rowIncrement * (m_renderParameters.getImageHeight() - 1);
234  if (numComponents != 4) {
235  throw vpException(vpException::dimensionError, "Expected panda texture to have 4 components!");
236  }
237  for (unsigned int i = 0; i < m_renderParameters.getImageHeight(); ++i) {
238  const float *rowData = data - i * rowIncrement;
239  vpRGBf *colorRow = I[top + i];
240  unsigned char *validRow = valid[top + i];
241  for (unsigned int j = 0; j < m_renderParameters.getImageWidth(); ++j) {
242  colorRow[left + j].R = rowData[j * numComponents];
243  colorRow[left + j].G = rowData[j * numComponents + 1];
244  colorRow[left + j].B = rowData[j * numComponents + 2];
245  validRow[left + j] = static_cast<unsigned char>(rowData[j * numComponents + 3]);
246  }
247  }
248 }
249 
250 END_VISP_NAMESPACE
251 
252 #endif
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ dimensionError
Bad dimension.
Definition: vpException.h:71
@ fatalError
Fatal error.
Definition: vpException.h:72
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:544
unsigned int getHeight() const
Definition: vpImage.h:181
NodePath m_renderRoot
Rendering parameters.
vpPanda3DRenderParameters m_renderParameters
Pointer to owning window, which can create buffers etc. It is not necessarily visible.
Implementation of canny filtering, using Sobel kernels.
FrameBufferProperties getBufferProperties() const VP_OVERRIDE
vpPanda3DDepthCannyFilter(const std::string &name, std::shared_ptr< vpPanda3DBaseRenderer > inputRenderer, bool isOutput, float edgeThreshold)
void setEdgeThreshold(float edgeThreshold)
void getRender(vpImage< vpRGBf > &I, vpImage< unsigned char > &valid) const
void setupScene() VP_OVERRIDE
Initialize the scene for this specific renderer.
vpPanda3DDepthGaussianBlur(const std::string &name, std::shared_ptr< vpPanda3DBaseRenderer > inputRenderer, bool isOutput)
void getRender(vpImage< unsigned char > &I) const
FrameBufferProperties getBufferProperties() const VP_OVERRIDE
Base class for postprocessing filters that map the result of a vpPanda3DBaseRenderer to a new image.
void getRenderBasic(vpImage< unsigned char > &I) const
virtual void setupScene() VP_OVERRIDE
Initialize the scene for this specific renderer.
Definition: vpRGBf.h:64
float B
Blue component.
Definition: vpRGBf.h:157
float G
Green component.
Definition: vpRGBf.h:156
float R
Red component.
Definition: vpRGBf.h:155
Defines a rectangle in the plane.
Definition: vpRect.h:79
double getLeft() const
Definition: vpRect.h:173
double getTop() const
Definition: vpRect.h:192