Intel® RealSense™ Cross Platform API
Intel Realsense Cross-platform API
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 
28  template <typename T>
29  void dxf_smooth(void *frame_data, float alpha, float delta, int iterations)
30  {
31  static_assert((std::is_arithmetic<T>::value), "Spatial filter assumes numeric types");
33 
34  for (int i = 0; i < iterations; i++)
35  {
36  if (fp)
37  {
38  recursive_filter_horizontal_fp(frame_data, alpha, delta);
39  recursive_filter_vertical_fp(frame_data, alpha, delta);
40  }
41  else
42  {
43  recursive_filter_horizontal<T>(frame_data, alpha, delta);
44  recursive_filter_vertical<T>(frame_data, alpha, delta);
45  }
46  }
47 
48  // Disparity domain hole filling requires a second pass over the frame data
49  // For depth domain a more efficient in-place hole filling is performed
50  if (_holes_filling_mode && fp)
51  intertial_holes_fill<T>(static_cast<T*>(frame_data));
52  }
53 
54  void recursive_filter_horizontal_fp(void * image_data, float alpha, float deltaZ);
55  void recursive_filter_vertical_fp(void * image_data, float alpha, float deltaZ);
56 
57  template <typename T>
58  void recursive_filter_horizontal(void * image_data, float alpha, float deltaZ)
59  {
60  size_t v{}, u{};
61 
62  // Handle conversions for invalid input data
64 
65  // Filtering integer values requires round-up to the nearest discrete value
66  const float round = fp ? 0.f : 0.5f;
67  // define invalid inputs
68  const T valid_threshold = fp ? static_cast<T>(std::numeric_limits<T>::epsilon()) : static_cast<T>(1);
69  const T delta_z = static_cast<T>(deltaZ);
70 
71  auto image = reinterpret_cast<T*>(image_data);
72  size_t cur_fill = 0;
73 
74  for (v = 0; v < _height; v++)
75  {
76  // left to right
77  T *im = image + v * _width;
78  T val0 = im[0];
79  cur_fill = 0;
80 
81  for (u = 1; u < _width-1; u++)
82  {
83  T val1 = im[1];
84 
85  if (fabs(val0) >= valid_threshold)
86  {
87  if (fabs(val1) >= valid_threshold)
88  {
89  cur_fill = 0;
90  T diff = static_cast<T>(fabs(val1 - val0));
91 
92  if (diff >= valid_threshold && diff <= delta_z)
93  {
94  float filtered = val1 * alpha + val0 * (1.0f - alpha);
95  val1 = static_cast<T>(filtered + round);
96  im[1] = val1;
97  }
98  }
99  else // Only the old value is valid - appy holes filling
100  {
101  if (_holes_filling_radius)
102  {
103  if (++cur_fill <_holes_filling_radius)
104  im[1] = val1 = val0;
105  }
106  }
107  }
108 
109  val0 = val1;
110  im += 1;
111  }
112 
113  // right to left
114  im = image + (v + 1) * _width - 2; // end of row - two pixels
115  T val1 = im[1];
116  cur_fill = 0;
117 
118  for (u = _width - 1; u > 0; u--)
119  {
120  T val0 = im[0];
121 
122  if (val1 >= valid_threshold)
123  {
124  if (val0 > valid_threshold)
125  {
126  cur_fill = 0;
127  T diff = static_cast<T>(fabs(val1 - val0));
128 
129  if (diff <= delta_z)
130  {
131  float filtered = val0 * alpha + val1 * (1.0f - alpha);
132  val0 = static_cast<T>(filtered + round);
133  im[0] = val0;
134  }
135  }
136  else // 'inertial' hole filling
137  {
138  if (_holes_filling_radius)
139  {
140  if (++cur_fill <_holes_filling_radius)
141  im[0] = val0 = val1;
142  }
143  }
144  }
145 
146  val1 = val0;
147  im -= 1;
148  }
149  }
150  }
151 
152  template <typename T>
153  void recursive_filter_vertical(void * image_data, float alpha, float deltaZ)
154  {
155  size_t v{}, u{};
156 
157  // Handle conversions for invalid input data
159 
160  // Filtering integer values requires round-up to the nearest discrete value
161  const float round = fp ? 0.f : 0.5f;
162  // define invalid range
163  const T valid_threshold = fp ? static_cast<T>(std::numeric_limits<T>::epsilon()) : static_cast<T>(1);
164  const T delta_z = static_cast<T>(deltaZ);
165 
166  auto image = reinterpret_cast<T*>(image_data);
167 
168  // we'll do one row at a time, top to bottom, then bottom to top
169 
170  // top to bottom
171 
172  T *im = image;
173  T im0{};
174  T imw{};
175  for (v = 1; v < _height; v++)
176  {
177  for (u = 0; u < _width; u++)
178  {
179  im0 = im[0];
180  imw = im[_width];
181 
182  //if ((fabs(im0) >= valid_threshold) && (fabs(imw) >= valid_threshold))
183  {
184  T diff = static_cast<T>(fabs(im0 - imw));
185  if (diff < delta_z)
186  {
187  float filtered = imw * alpha + im0 * (1.f - alpha);
188  im[_width] = static_cast<T>(filtered + round);
189  }
190  }
191  im += 1;
192  }
193  }
194 
195  // bottom to top
196  im = image + (_height - 2) * _width;
197  for (v = 1; v < _height; v++, im -= (_width * 2))
198  {
199  for (u = 0; u < _width; u++)
200  {
201  im0 = im[0];
202  imw = im[_width];
203 
204  if ((fabs(im0) >= valid_threshold) && (fabs(imw) >= valid_threshold))
205  {
206  T diff = static_cast<T>(fabs(im0 - imw));
207  if ( diff < delta_z)
208  {
209  float filtered = im0 * alpha + imw * (1.f - alpha);
210  im[0] = static_cast<T>(filtered + round);
211  }
212  }
213  im += 1;
214  }
215  }
216  }
217 
218  template<typename T>
219  inline void intertial_holes_fill(T* image_data)
220  {
221  std::function<bool(T*)> fp_oper = [](T* ptr) { return !*((int *)ptr); };
222  std::function<bool(T*)> uint_oper = [](T* ptr) { return !(*ptr); };
223  auto empty = (std::is_floating_point<T>::value) ? fp_oper : uint_oper;
224 
225  size_t cur_fill = 0;
226 
227  T* p = image_data;
228  for (int j = 0; j < _height; ++j)
229  {
230  ++p;
231  cur_fill = 0;
232 
233  //Left to Right
234  for (size_t i = 1; i < _width; ++i)
235  {
236  if (empty(p))
237  {
238  if (++cur_fill < _holes_filling_radius)
239  *p = *(p - 1);
240  }
241  else
242  cur_fill = 0;
243 
244  ++p;
245  }
246 
247  --p;
248  cur_fill = 0;
249  //Right to left
250  for (size_t i = 1; i < _width; ++i)
251  {
252  if (empty(p))
253  {
254  if (++cur_fill < _holes_filling_radius)
255  *p = *(p + 1);
256  }
257  else
258  cur_fill = 0;
259  --p;
260  }
261  p += _width;
262  }
263  }
264 
265  private:
266 
267  float _spatial_alpha_param;
268  uint8_t _spatial_delta_param;
269  uint8_t _spatial_iterations;
270  float _spatial_edge_threshold;
271  size_t _width, _height, _stride;
272  size_t _bpp;
273  rs2_extension _extension_type; // Strictly Depth/Disparity
274  size_t _current_frm_size_pixels;
275  rs2::stream_profile _source_stream_profile;
276  rs2::stream_profile _target_stream_profile;
277  bool _stereoscopic_depth;
278  float _focal_lenght_mm;
279  float _stereo_baseline_mm;
280  uint8_t _holes_filling_mode;
281  uint8_t _holes_filling_radius;
282  };
283 }
Definition: rs_frame.hpp:21
Definition: rs_frame.hpp:202
Definition: backend.h:380
void recursive_filter_horizontal(void *image_data, float alpha, float deltaZ)
Definition: spatial-filter.h:58
rs2::frame prepare_target_frame(const rs2::frame &f, const rs2::frame_source &source)
Definition: synthetic-stream.h:41
void intertial_holes_fill(T *image_data)
Definition: spatial-filter.h:219
Definition: algo.h:16
Definition: rs_processing.hpp:13
void recursive_filter_horizontal_fp(void *image_data, float alpha, float deltaZ)
void dxf_smooth(void *frame_data, float alpha, float delta, int iterations)
Definition: spatial-filter.h:29
void recursive_filter_vertical_fp(void *image_data, float alpha, float deltaZ)
void update_configuration(const rs2::frame &f)
Definition: spatial-filter.h:18
rs2_extension
Specifies advanced interfaces (capabilities) objects may implement.
Definition: rs_types.h:94
void recursive_filter_vertical(void *image_data, float alpha, float deltaZ)
Definition: spatial-filter.h:153