spatial-filter.h
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2017 Intel Corporation. All Rights Reserved
4 // http://inf.ufrgs.br/~eslgastal/DomainTransform/Gastal_Oliveira_SIGGRAPH2011_Domain_Transform.pdf
5 // The filter also allows to apply holes filling extention that due to implementation constrains can be applied horizontally only
6 
7 #pragma once
8 
9 #include <map>
10 #include <vector>
11 #include <cmath>
12 
13 #include "../include/librealsense2/hpp/rs_frame.hpp"
14 #include "../include/librealsense2/hpp/rs_processing.hpp"
15 
16 namespace librealsense
17 {
19  {
20  public:
22 
23  protected:
24  void update_configuration(const rs2::frame& f);
25 
27  rs2::frame process_frame(const rs2::frame_source& source, const rs2::frame& f) override;
28 
29  template <typename T>
30  void dxf_smooth(void *frame_data, float alpha, float delta, int iterations)
31  {
32  static_assert((std::is_arithmetic<T>::value), "Spatial filter assumes numeric types");
34 
35  for (int i = 0; i < iterations; i++)
36  {
37  if (fp)
38  {
39  recursive_filter_horizontal_fp(frame_data, alpha, delta);
40  recursive_filter_vertical_fp(frame_data, alpha, delta);
41  }
42  else
43  {
44  recursive_filter_horizontal<T>(frame_data, alpha, delta);
45  recursive_filter_vertical<T>(frame_data, alpha, delta);
46  }
47  }
48 
49  // Disparity domain hole filling requires a second pass over the frame data
50  // For depth domain a more efficient in-place hole filling is performed
51  if (_holes_filling_mode && fp)
52  intertial_holes_fill<T>(static_cast<T*>(frame_data));
53  }
54 
55  void recursive_filter_horizontal_fp(void * image_data, float alpha, float deltaZ);
56  void recursive_filter_vertical_fp(void * image_data, float alpha, float deltaZ);
57 
58  template <typename T>
59  void recursive_filter_horizontal(void * image_data, float alpha, float deltaZ)
60  {
61  size_t v{}, u{};
62 
63  // Handle conversions for invalid input data
65 
66  // Filtering integer values requires round-up to the nearest discrete value
67  const float round = fp ? 0.f : 0.5f;
68  // define invalid inputs
69  const T valid_threshold = fp ? static_cast<T>(std::numeric_limits<T>::epsilon()) : static_cast<T>(1);
70  const T delta_z = static_cast<T>(deltaZ);
71 
72  auto image = reinterpret_cast<T*>(image_data);
73  size_t cur_fill = 0;
74 
75  for (v = 0; v < _height; v++)
76  {
77  // left to right
78  T *im = image + v * _width;
79  T val0 = im[0];
80  cur_fill = 0;
81 
82  for (u = 1; u < _width - 1; u++)
83  {
84  T val1 = im[1];
85 
86  if (fabs(val0) >= valid_threshold)
87  {
88  if (fabs(val1) >= valid_threshold)
89  {
90  cur_fill = 0;
91  T diff = static_cast<T>(fabs(val1 - val0));
92 
93  if (diff >= valid_threshold && diff <= delta_z)
94  {
95  float filtered = val1 * alpha + val0 * (1.0f - alpha);
96  val1 = static_cast<T>(filtered + round);
97  im[1] = val1;
98  }
99  }
100  else // Only the old value is valid - appy holes filling
101  {
103  {
104  if (++cur_fill <_holes_filling_radius)
105  im[1] = val1 = val0;
106  }
107  }
108  }
109 
110  val0 = val1;
111  im += 1;
112  }
113 
114  // right to left
115  im = image + (v + 1) * _width - 2; // end of row - two pixels
116  T val1 = im[1];
117  cur_fill = 0;
118 
119  for (u = _width - 1; u > 0; u--)
120  {
121  T val0 = im[0];
122 
123  if (val1 >= valid_threshold)
124  {
125  if (val0 > valid_threshold)
126  {
127  cur_fill = 0;
128  T diff = static_cast<T>(fabs(val1 - val0));
129 
130  if (diff <= delta_z)
131  {
132  float filtered = val0 * alpha + val1 * (1.0f - alpha);
133  val0 = static_cast<T>(filtered + round);
134  im[0] = val0;
135  }
136  }
137  else // 'inertial' hole filling
138  {
140  {
141  if (++cur_fill <_holes_filling_radius)
142  im[0] = val0 = val1;
143  }
144  }
145  }
146 
147  val1 = val0;
148  im -= 1;
149  }
150  }
151  }
152 
153  template <typename T>
154  void recursive_filter_vertical(void * image_data, float alpha, float deltaZ)
155  {
156  size_t v{}, u{};
157 
158  // Handle conversions for invalid input data
160 
161  // Filtering integer values requires round-up to the nearest discrete value
162  const float round = fp ? 0.f : 0.5f;
163  // define invalid range
164  const T valid_threshold = fp ? static_cast<T>(std::numeric_limits<T>::epsilon()) : static_cast<T>(1);
165  const T delta_z = static_cast<T>(deltaZ);
166 
167  auto image = reinterpret_cast<T*>(image_data);
168 
169  // we'll do one row at a time, top to bottom, then bottom to top
170 
171  // top to bottom
172 
173  T *im = image;
174  T im0{};
175  T imw{};
176  for (v = 1; v < _height; v++)
177  {
178  for (u = 0; u < _width; u++)
179  {
180  im0 = im[0];
181  imw = im[_width];
182 
183  //if ((fabs(im0) >= valid_threshold) && (fabs(imw) >= valid_threshold))
184  {
185  T diff = static_cast<T>(fabs(im0 - imw));
186  if (diff < delta_z)
187  {
188  float filtered = imw * alpha + im0 * (1.f - alpha);
189  im[_width] = static_cast<T>(filtered + round);
190  }
191  }
192  im += 1;
193  }
194  }
195 
196  // bottom to top
197  im = image + (_height - 2) * _width;
198  for (v = 1; v < _height; v++, im -= (_width * 2))
199  {
200  for (u = 0; u < _width; u++)
201  {
202  im0 = im[0];
203  imw = im[_width];
204 
205  if ((fabs(im0) >= valid_threshold) && (fabs(imw) >= valid_threshold))
206  {
207  T diff = static_cast<T>(fabs(im0 - imw));
208  if (diff < delta_z)
209  {
210  float filtered = im0 * alpha + imw * (1.f - alpha);
211  im[0] = static_cast<T>(filtered + round);
212  }
213  }
214  im += 1;
215  }
216  }
217  }
218 
219  template<typename T>
220  inline void intertial_holes_fill(T* image_data)
221  {
222  std::function<bool(T*)> fp_oper = [](T* ptr) { return !*((int *)ptr); };
223  std::function<bool(T*)> uint_oper = [](T* ptr) { return !(*ptr); };
224  auto empty = (std::is_floating_point<T>::value) ? fp_oper : uint_oper;
225 
226  size_t cur_fill = 0;
227 
228  T* p = image_data;
229  for (int j = 0; j < _height; ++j)
230  {
231  ++p;
232  cur_fill = 0;
233 
234  //Left to Right
235  for (size_t i = 1; i < _width; ++i)
236  {
237  if (empty(p))
238  {
239  if (++cur_fill < _holes_filling_radius)
240  *p = *(p - 1);
241  }
242  else
243  cur_fill = 0;
244 
245  ++p;
246  }
247 
248  --p;
249  cur_fill = 0;
250  //Right to left
251  for (size_t i = 1; i < _width; ++i)
252  {
253  if (empty(p))
254  {
255  if (++cur_fill < _holes_filling_radius)
256  *p = *(p + 1);
257  }
258  else
259  cur_fill = 0;
260  --p;
261  }
262  p += _width;
263  }
264  }
265 
266  private:
267 
273  size_t _bpp;
274  rs2_extension _extension_type; // Strictly Depth/Disparity
283  };
285 }
GLfloat GLfloat p
Definition: glext.h:12687
rs2::stream_profile _target_stream_profile
void recursive_filter_horizontal(void *image_data, float alpha, float deltaZ)
rs2::frame prepare_target_frame(const rs2::frame &f, const rs2::frame_source &source)
GLfloat value
void intertial_holes_fill(T *image_data)
dictionary frame_data
Definition: t265_stereo.py:80
unsigned char uint8_t
Definition: stdint.h:78
GLenum GLenum GLsizei void * image
GLdouble f
GLfloat GLfloat GLfloat alpha
rs2::stream_profile _source_stream_profile
void recursive_filter_horizontal_fp(void *image_data, float alpha, float deltaZ)
GLint j
void dxf_smooth(void *frame_data, float alpha, float delta, int iterations)
void recursive_filter_vertical_fp(void *image_data, float alpha, float deltaZ)
void update_configuration(const rs2::frame &f)
rs2_extension
Specifies advanced interfaces (capabilities) objects may implement.
Definition: rs_types.h:166
GLsizei GLsizei GLchar * source
int i
void recursive_filter_vertical(void *image_data, float alpha, float deltaZ)
im
Definition: rmse.py:121
GLdouble v
MAP_EXTENSION(RS2_EXTENSION_POINTS, librealsense::points)
rs2::frame process_frame(const rs2::frame_source &source, const rs2::frame &f) override


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:41