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");
32 
33  for (int i = 0; i < iterations; i++)
34  {
35  recursive_filter_horizontal<T>(frame_data, alpha, delta);
36  recursive_filter_vertical<T>(frame_data, alpha, delta);
37  }
38  }
39 
40  template <typename T>
41  void recursive_filter_horizontal(void * image_data, float alpha, float deltaZ)
42  {
43  size_t v{}, u{};
44 
45  // Handle conversions for invalid input data
47 
48  // Filtering integer values requires round-up to the nearest discrete value
49  const float round = fp ? 0.f : 0.5f;
50  // Disparity value of 0.001 corresponds to 0.5 mm at 0.5 meter to 5 mm at 5m
51  // For Depth values the smoothing will take place when the gradient is more than 4 level (~0.4mm)
52  const T noise = fp ? static_cast<T>(0.001f) : static_cast<T>(4);
53  const T max_radius = static_cast<T>(fp ? 2.f : deltaZ);
54 
55  auto image = reinterpret_cast<T*>(image_data);
56  size_t cur_fill = 0;
57 
58  for (v = 0; v < _height; v++)
59  {
60  // left to right
61  T *im = image + v * _width;
62  T val0 = im[0];
63  cur_fill = 0;
64 
65  for (u = 1; u < _width-1; u++)
66  {
67  T val1 = im[1];
68 
69  if (val0 >= noise)
70  {
71  if (val1 >= noise)
72  {
73  cur_fill = 0;
74  T diff = static_cast<T>(fabs(val1 - val0));
75 
76  if (diff >= noise && diff <= max_radius)
77  {
78  float filtered = val1 * alpha + val0 * (1.0f - alpha);
79  val1 = static_cast<T>(filtered + round);
80  im[1] = val1;
81  }
82  }
83  else // Only the old value is valid - appy holes filling
84  {
85  if (_holes_filling_radius)
86  {
87  if (++cur_fill <_holes_filling_radius)
88  im[1] = val1 = val0;
89  }
90  }
91  }
92 
93  val0 = val1;
94  im += 1;
95  }
96 
97  // right to left
98  im = image + (v + 1) * _width - 2; // end of row - two pixels
99  T val1 = im[1];
100  cur_fill = 0;
101 
102  for (u = _width - 1; u > 0; u--)
103  {
104  T val0 = im[0];
105 
106  if (val1 >= noise)
107  {
108  if (val0 > noise)
109  {
110  cur_fill = 0;
111  T diff = static_cast<T>(fabs(val1 - val0));
112 
113  if (diff >= noise && diff <= max_radius)
114  {
115  float filtered = val0 * alpha + val1 * (1.0f - alpha);
116  val0 = static_cast<T>(filtered + round);
117  im[0] = val0;
118  }
119  }
120  else // 'inertial' hole filling
121  {
122  if (_holes_filling_radius)
123  {
124  if (++cur_fill <_holes_filling_radius)
125  im[0] = val0 = val1;
126  }
127  }
128  }
129 
130  val1 = val0;
131  im -= 1;
132  }
133  }
134  }
135 
136  template <typename T>
137  void recursive_filter_vertical(void * image_data, float alpha, float deltaZ)
138  {
139  size_t v{}, u{};
140 
141  // Handle conversions for invalid input data
143 
144  // Filtering integer values requires round-up to the nearest discrete value
145  const float round = fp ? 0.f : 0.5f;
146  // Disparity value of 0.001 corresponds to 0.5 mm at 0.5 meter to 5 mm at 5m
147  // For Depth values the smoothing will take effect when the gradient is more than 4 level (~0.4mm)
148  const T noise = fp ? static_cast<T>(0.001f) : static_cast<T>(4);
149  const T max_radius = static_cast<T>(fp ? 2.f : deltaZ);
150 
151  auto image = reinterpret_cast<T*>(image_data);
152 
153  // we'll do one row at a time, top to bottom, then bottom to top
154 
155  // top to bottom
156 
157  T *im = image;
158  T im0{};
159  T imw{};
160  for (v = 1; v < _height; v++)
161  {
162  for (u = 0; u < _width; u++)
163  {
164  im0 = im[0];
165  imw = im[_width];
166 
167  if ((im0 >noise) && (imw > noise))
168  {
169  float delta = static_cast<float>(fabs(im0 - imw));
170  if (delta > noise && delta < max_radius)
171  {
172  float filtered = imw * alpha + im0 * (1.f - alpha);
173  im[_width] = static_cast<T>(filtered + round);
174  }
175  }
176  im += 1;
177  }
178  }
179 
180  // bottom to top
181  im = image + (_height - 2) * _width;
182  for (v = 1; v < _height; v++, im -= (_width * 2))
183  {
184  for (u = 0; u < _width; u++)
185  {
186  im0 = im[0];
187  imw = im[_width];
188 
189  if ((im0 >noise) && (imw > noise))
190  {
191  float delta = static_cast<float>(fabs(im0 - imw));
192  if (delta > noise && delta < max_radius)
193  {
194  float filtered = im0 * alpha + imw * (1.f - alpha);
195  im[0] = static_cast<T>(filtered + round);
196  }
197  }
198  im += 1;
199  }
200  }
201  }
202 
203  private:
204 
205  float _spatial_alpha_param;
206  uint8_t _spatial_delta_param;
207  uint8_t _spatial_iterations;
208  float _spatial_radius; // The convolution radius is domain-dependent
209  size_t _width, _height, _stride;
210  size_t _bpp;
211  rs2_extension _extension_type; // Strictly Depth/Disparity
212  size_t _current_frm_size_pixels;
213  rs2::stream_profile _source_stream_profile;
214  rs2::stream_profile _target_stream_profile;
215  bool _stereoscopic_depth;
216  float _focal_lenght_mm;
217  float _stereo_baseline_mm;
218  uint8_t _holes_filling_mode;
219  uint8_t _holes_filling_radius;
220  };
221 }
Definition: rs_frame.hpp:21
Definition: rs_frame.hpp:202
Definition: backend.h:351
void recursive_filter_horizontal(void *image_data, float alpha, float deltaZ)
Definition: spatial-filter.h:41
rs2::frame prepare_target_frame(const rs2::frame &f, const rs2::frame_source &source)
Definition: synthetic-stream.h:41
Definition: algo.h:16
Definition: rs_processing.hpp:13
void dxf_smooth(void *frame_data, float alpha, float delta, int iterations)
Definition: spatial-filter.h:29
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:93
void recursive_filter_vertical(void *image_data, float alpha, float deltaZ)
Definition: spatial-filter.h:137