Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
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/ar/vpPanda3DGeometryRenderer.h>
32#include <visp3/rbt/vpPanda3DDepthFilters.h>
33#if defined(VISP_HAVE_PANDA3D)
34
35#include "graphicsOutput.h"
36#include "graphicsEngine.h"
37#include "windowFramework.h"
38
39#include <visp3/gui/vpDisplayFactory.h>
40
42#define VP_STRINGIFY(x) #x
43#define VP_TOSTRING(x) VP_STRINGIFY(x)
44
45const std::string vpPanda3DDepthGaussianBlur::FRAGMENT_SHADER =
46"#version 330\n"
47"\n"
48"in vec2 texcoords;\n"
49"\n"
50"uniform sampler2D p3d_Texture0;\n"
51"uniform vec2 dp; // 1 divided by number of pixels\n"
52"\n"
53"const float kernel[25] = float[25](\n"
54" 2, 4, 5, 4, 2,\n"
55" 4, 9, 12, 9, 4,\n"
56" 5, 12, 15, 12, 5,\n"
57" 4, 9, 12, 9, 4,\n"
58" 2, 4, 5, 4, 2\n"
59");\n"
60"const float normalize = 1 / 159.0;\n"
61"\n"
62"vec2 offset[25] = vec2[25](\n"
63" 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"
64" 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"
65" 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"
66" 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"
67" 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"
68");\n"
69"\n"
70"out vec4 p3d_FragData;\n"
71"\n"
72"void main() {\n"
73" float v = 0.f;\n"
74"\n"
75" for(int i = 0; i < 25; ++i) {\n"
76" v += kernel[i] * texture(p3d_Texture0, texcoords + offset[i]).a;\n"
77" }\n"
78" p3d_FragData.a = v * normalize;\n"
79"}\n"
80")\n";
81
82vpPanda3DDepthGaussianBlur::vpPanda3DDepthGaussianBlur(const std::string &name, std::shared_ptr<vpPanda3DBaseRenderer> inputRenderer, bool isOutput)
83 : vpPanda3DPostProcessFilter(name, inputRenderer, isOutput, vpPanda3DDepthGaussianBlur::FRAGMENT_SHADER)
84{ }
85
87{
88 FrameBufferProperties fbp;
89 fbp.set_depth_bits(0);
90 fbp.set_rgba_bits(0, 0, 0, 32);
91 fbp.set_float_color(true);
92 return fbp;
93}
94
99
100const std::string vpPanda3DDepthCannyFilter::FRAGMENT_SHADER =
101"#version 330\n"
102"#define PI "
103VP_TOSTRING(M_PI)
104"\n"
105"\n"
106"in vec2 texcoords;\n"
107"\n"
108"uniform sampler2D p3d_Texture0;\n"
109"uniform vec2 dp; // 1 divided by number of pixels\n"
110"uniform float edgeThreshold;\n"
111"\n"
112"const float kernel[9] = float[9](\n"
113" 0.0, 1.0, 0.0,\n"
114" 1.0,-4.0, 1.0,\n"
115" 0.0, 1.0, 0.0\n"
116");\n"
117"\n"
118"const float kernel_h[9] = float[9](\n"
119" -1.0, 0.0, 1.0,\n"
120" -2.0, 0.0, 2.0,\n"
121" -1.0, 0.0, 1.0\n"
122");\n"
123"\n"
124"const float kernel_v[9] = float[9](\n"
125" -1.0, -2.0, -1.0,\n"
126" 0.0, 0.0, 0.0,\n"
127" 1.0, 2.0, 1.0\n"
128");\n"
129"\n"
130"vec2 offset[9] = vec2[9](\n"
131" vec2(-dp.x, -dp.y), vec2(0.0, -dp.y), vec2(dp.x, -dp.y),\n"
132" vec2(-dp.x, 0.0), vec2(0.0, 0.0), vec2(dp.x, 0.0),\n"
133" vec2(-dp.x, dp.y), vec2(0.0, dp.y), vec2(dp.x, dp.y)\n"
134");\n"
135"\n"
136"float textureValues[9];\n"
137"\n"
138"out vec3 p3d_FragData;\n"
139"\n"
140"void main() {\n"
141" if(texture(p3d_Texture0, texcoords).a == 0) {\n"
142" p3d_FragData = vec3(0.f, 0.f, 0.f);\n"
143" } else {\n"
144" float sum = 0.f;\n"
145" for(int i = 0; i < 9; ++i) {\n"
146" float pix = texture(p3d_Texture0, texcoords + offset[i]).a;\n"
147" pix = (pix < 1e-5f ? 1000.f: pix);\n"
148" textureValues[i] = pix;\n"
149" sum += pix * kernel[i];\n"
150" }\n"
151" if(abs(sum) > edgeThreshold) {\n"
152" float sum_h = 0.f;\n"
153" float sum_v = 0.f;\n"
154" for(int i = 0; i < 9; ++i) {\n"
155" float pix = textureValues[i];\n"
156" sum_h += pix * kernel_h[i];\n"
157" sum_v += pix * kernel_v[i];\n"
158" }\n"
159" vec2 orientationAndValid = (sum_h != 0.f) ? vec2(atan(sum_v, -sum_h), 1.f) : vec2(0.f, 0.f);\n"
160" float orientation = (orientationAndValid.x + PI) / (PI * 2);\n"
161" p3d_FragData = vec3(orientation, orientationAndValid.y, orientation);\n"
162" } else {\n"
163" p3d_FragData = vec3(0.f, 0.f, 0.f);\n"
164" }\n"
165" }\n"
166"}\n";
167
168vpPanda3DDepthCannyFilter::vpPanda3DDepthCannyFilter(const std::string &name, std::shared_ptr<vpPanda3DGeometryRenderer> inputRenderer, bool isOutput, float edgeThreshold)
169 : vpPanda3DPostProcessFilter(name, inputRenderer, isOutput, vpPanda3DDepthCannyFilter::FRAGMENT_SHADER), m_edgeThreshold(edgeThreshold), m_inputIsFast(inputRenderer->isFastAndApproximateRendering())
170{ }
171
173{
175 m_renderRoot.set_shader_input("edgeThreshold", LVector2f(m_edgeThreshold));
176}
177
179{
180
181 m_edgeThreshold = edgeThreshold;
182 float shaderValue = m_inputIsFast ? m_edgeThreshold / m_renderParameters.getFarClippingDistance() : m_edgeThreshold;
183 m_renderRoot.set_shader_input("edgeThreshold", LVector2f(shaderValue));
184}
185
187{
188 FrameBufferProperties fbp;
189 fbp.set_depth_bits(0);
190 fbp.set_rgba_bits(8, 8, 8, 0);
191 fbp.set_alpha_bits(0);
192
193 fbp.set_rgb_color(false);
194
195 fbp.set_float_color(false);
196 return fbp;
197}
198
199PointerTo<Texture> vpPanda3DDepthCannyFilter::setupTexture(const FrameBufferProperties &fbp) const
200{
201 PointerTo<Texture> tex = new Texture();
202 fbp.setup_color_texture(tex);
203 tex->set_format(Texture::F_rgb);
204 tex->set_component_type(Texture::T_unsigned_byte);
205 return tex;
206}
207
209{
210 if (!m_isOutput) {
211 throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
212 }
213
214 I.resize(m_renderParameters.getImageHeight(), m_renderParameters.getImageWidth());
215
216 valid.resize(I.getHeight(), I.getWidth());
217 const unsigned numComponents = m_texture->get_num_components();
218 int rowIncrement = I.getWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
219 uint8_t *data = (uint8_t *)(&(m_texture->get_ram_image().front()));
220 // Panda3D stores data upside down
221 data += rowIncrement * (I.getHeight() - 1);
222 rowIncrement = -rowIncrement;
223 if (numComponents != 3) {
224 throw;
225 }
226 for (unsigned int i = 0; i < I.getHeight(); ++i) {
227 float *colorRow = I[i];
228 unsigned char *validRow = valid[i];
229 for (unsigned int j = 0; j < I.getWidth(); ++j) {
230 colorRow[j] = static_cast<float>(data[j * numComponents]) / std::numeric_limits<uint8_t>::max() * M_PI * 2 - M_PI;
231 validRow[j] = static_cast<unsigned char>((data[j * numComponents + 1] > 0) * 255);
232 }
233 data += rowIncrement;
234 }
235}
236
237void vpPanda3DDepthCannyFilter::getRender(vpImage<float> &I, vpImage<unsigned char> &valid, const vpRect &bb, unsigned int h, unsigned w) const
238{
239 if (!m_isOutput) {
240 throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
241 }
242
243 I.resize(h, w, 0.f);
244 valid.resize(I.getHeight(), I.getWidth(), 0);
245 const unsigned top = static_cast<unsigned int>(std::max(0.0, bb.getTop()));
246 const unsigned left = static_cast<unsigned int>(std::max(0.0, bb.getLeft()));
247 const unsigned numComponents = m_texture->get_num_components();
248 const unsigned rowIncrement = m_renderParameters.getImageWidth() * numComponents;
249
250 const uint8_t *data = (uint8_t *)(&(m_texture->get_ram_image().front()));
251 data += rowIncrement * (m_renderParameters.getImageHeight() - 1);
252 if (numComponents != 3) {
253 throw vpException(vpException::dimensionError, "Expected panda texture to have 3 components!");
254 }
255 for (unsigned int i = 0; i < m_renderParameters.getImageHeight(); ++i) {
256 const uint8_t *rowData = data - i * rowIncrement;
257 float *colorRow = I[top + i];
258 unsigned char *validRow = valid[top + i];
259 for (unsigned int j = 0; j < m_renderParameters.getImageWidth(); ++j) {
260 colorRow[left + j] = static_cast<float>(rowData[j * numComponents]) / std::numeric_limits<uint8_t>::max() * M_PI * 2 - M_PI;
261 validRow[left + j] = static_cast<unsigned char>((rowData[j * numComponents + 1] > 0) * 255);
262 }
263 }
264}
265
266END_VISP_NAMESPACE
267
268#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
Definition of the vpImage class member functions.
Definition vpImage.h:131
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
NodePath m_renderRoot
Rendering parameters.
vpPanda3DRenderParameters m_renderParameters
Pointer to owning window, which can create buffers etc. It is not necessarily visible.
FrameBufferProperties getBufferProperties() const VP_OVERRIDE
vpPanda3DDepthCannyFilter(const std::string &name, std::shared_ptr< vpPanda3DGeometryRenderer > inputRenderer, bool isOutput, float edgeThreshold)
PointerTo< Texture > setupTexture(const FrameBufferProperties &fbp) const VP_OVERRIDE
void setEdgeThreshold(float edgeThreshold)
void getRender(vpImage< float > &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
void getRenderBasic(vpImage< unsigned char > &I) const
virtual void setupScene() VP_OVERRIDE
Initialize the scene for this specific renderer.
vpPanda3DPostProcessFilter(const std::string &name, std::shared_ptr< vpPanda3DBaseRenderer > inputRenderer, bool isOutput, std::string fragmentShader)
Defines a rectangle in the plane.
Definition vpRect.h:79