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