colorizer.cpp
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.
3 
4 #include "../include/librealsense2/hpp/rs_sensor.hpp"
5 #include "../include/librealsense2/hpp/rs_processing.hpp"
6 
8 #include "context.h"
9 #include "environment.h"
10 #include "option.h"
11 #include "colorizer.h"
12 #include "disparity-transform.h"
13 
14 namespace librealsense
15 {
16  static color_map hue{ {
17  { 255, 0, 0 },
18  { 255, 255, 0 },
19  { 0, 255, 0 },
20  { 0, 255, 255 },
21  { 0, 0, 255 },
22  { 255, 0, 255 },
23  { 255, 0, 0 },
24  } };
25 
26  static color_map jet{ {
27  { 0, 0, 255 },
28  { 0, 255, 255 },
29  { 255, 255, 0 },
30  { 255, 0, 0 },
31  { 50, 0, 0 },
32  } };
33 
34  static color_map classic{ {
35  { 30, 77, 203 },
36  { 25, 60, 192 },
37  { 45, 117, 220 },
38  { 204, 108, 191 },
39  { 196, 57, 178 },
40  { 198, 33, 24 },
41  } };
42 
43  static color_map grayscale{ {
44  { 255, 255, 255 },
45  { 0, 0, 0 },
46  } };
47 
49  { 0, 0, 0 },
50  { 255, 255, 255 },
51  } };
52 
53  static color_map biomes{ {
54  { 0, 0, 204 },
55  { 204, 230, 255 },
56  { 255, 255, 153 },
57  { 170, 255, 128 },
58  { 0, 153, 0 },
59  { 230, 242, 255 },
60  } };
61 
62  static color_map cold{ {
63  { 230, 247, 255 },
64  { 0, 92, 230 },
65  { 0, 179, 179 },
66  { 0, 51, 153 },
67  { 0, 5, 15 }
68  } };
69 
70  static color_map warm{ {
71  { 255, 255, 230 },
72  { 255, 204, 0 },
73  { 255, 136, 77 },
74  { 255, 51, 0 },
75  { 128, 0, 0 },
76  { 10, 0, 0 }
77  } };
78 
79  static color_map quantized{ {
80  { 255, 255, 255 },
81  { 0, 0, 0 },
82  }, 6 };
83 
84  static color_map pattern{ {
85  { 255, 255, 255 },
86  { 0, 0, 0 },
87  { 255, 255, 255 },
88  { 0, 0, 0 },
89  { 255, 255, 255 },
90  { 0, 0, 0 },
91  { 255, 255, 255 },
92  { 0, 0, 0 },
93  { 255, 255, 255 },
94  { 0, 0, 0 },
95  { 255, 255, 255 },
96  { 0, 0, 0 },
97  { 255, 255, 255 },
98  { 0, 0, 0 },
99  { 255, 255, 255 },
100  { 0, 0, 0 },
101  { 255, 255, 255 },
102  { 0, 0, 0 },
103  { 255, 255, 255 },
104  { 0, 0, 0 },
105  { 255, 255, 255 },
106  { 0, 0, 0 },
107  { 255, 255, 255 },
108  { 0, 0, 0 },
109  { 255, 255, 255 },
110  { 0, 0, 0 },
111  { 255, 255, 255 },
112  { 0, 0, 0 },
113  { 255, 255, 255 },
114  { 0, 0, 0 },
115  { 255, 255, 255 },
116  { 0, 0, 0 },
117  { 255, 255, 255 },
118  { 0, 0, 0 },
119  { 255, 255, 255 },
120  { 0, 0, 0 },
121  { 255, 255, 255 },
122  { 0, 0, 0 },
123  { 255, 255, 255 },
124  { 0, 0, 0 },
125  { 255, 255, 255 },
126  { 0, 0, 0 },
127  { 255, 255, 255 },
128  { 0, 0, 0 },
129  { 255, 255, 255 },
130  { 0, 0, 0 },
131  { 255, 255, 255 },
132  { 0, 0, 0 },
133  { 255, 255, 255 },
134  { 0, 0, 0 },
135  } };
136 
138  : colorizer("Depth Visualization")
139  {}
140 
143  _min(0.f), _max(6.f), _equalize(true),
145  {
146  _histogram = std::vector<int>(MAX_DEPTH, 0);
147  _hist_data = _histogram.data();
150 
152 
153  auto min_opt = std::make_shared< ptr_option< float > >( 0.f, 16.f, 0.1f, 0.f, &_min, "Min range in meters" );
154 
155  auto max_opt = std::make_shared< ptr_option< float > >( 0.f, 16.f, 0.1f, 6.f, &_max, "Max range in meters" );
156 
157  auto max_dist_opt = std::make_shared< max_distance_option >( max_opt, min_opt );
158 
159  auto min_dist_opt = std::make_shared< min_distance_option >( min_opt, max_opt );
160 
161  register_option( RS2_OPTION_MAX_DISTANCE, max_dist_opt );
162 
163  register_option( RS2_OPTION_MIN_DISTANCE, min_dist_opt );
164 
165  auto hist_opt = std::make_shared< ptr_option< bool > >( false,
166  true,
167  true,
168  true,
169  &_equalize,
170  "Perform histogram equalization" );
171 
172  auto weak_hist_opt = std::weak_ptr< ptr_option< bool > >( hist_opt );
173 
174  max_dist_opt->add_observer( [weak_hist_opt]( float val ) {
175  auto strong_hist_opt = weak_hist_opt.lock();
176  if( strong_hist_opt )
177  strong_hist_opt->set( false );
178  } );
179 
180  min_dist_opt->add_observer( [weak_hist_opt]( float val ) {
181  auto strong_hist_opt = weak_hist_opt.lock();
182  if( strong_hist_opt )
183  strong_hist_opt->set( false );
184  } );
185 
186  auto color_map = std::make_shared<ptr_option<int>>(0, (int)_maps.size() - 1, 1, 0, &_map_index, "Color map");
187  color_map->set_description(0.f, "Jet");
188  color_map->set_description(1.f, "Classic");
189  color_map->set_description(2.f, "White to Black");
190  color_map->set_description(3.f, "Black to White");
191  color_map->set_description(4.f, "Bio");
192  color_map->set_description(5.f, "Cold");
193  color_map->set_description(6.f, "Warm");
194  color_map->set_description(7.f, "Quantized");
195  color_map->set_description(8.f, "Pattern");
196  color_map->set_description(9.f, "Hue");
198 
199  auto preset_opt = std::make_shared<ptr_option<int>>(0, 3, 1, 0, &_preset, "Preset depth colorization");
200  preset_opt->set_description(0.f, "Dynamic");
201  preset_opt->set_description(1.f, "Fixed");
202  preset_opt->set_description(2.f, "Near");
203  preset_opt->set_description(3.f, "Far");
204 
205  preset_opt->on_set([this](float val)
206  {
207  if (fabs(val - 0.f) < 1e-6)
208  {
209  // Dynamic
210  _equalize = true;
211  _map_index = 0;
212  }
213  if (fabs(val - 1.f) < 1e-6)
214  {
215  // Fixed
216  _equalize = false;
217  _map_index = 0;
218  _min = 0.f;
219  _max = 6.f;
220  }
221  if (fabs(val - 2.f) < 1e-6)
222  {
223  // Near
224  _equalize = false;
225  _map_index = 1;
226  _min = 0.3f;
227  _max = 1.5f;
228  }
229  if (fabs(val - 3.f) < 1e-6)
230  {
231  // Far
232  _equalize = false;
233  _map_index = 0;
234  _min = 1.f;
235  _max = 16.f;
236  }
237  });
239 
241  }
242 
244  {
245  if (!frame || frame.is<rs2::frameset>())
246  return false;
247 
248  if (frame.get_profile().stream_type() != RS2_STREAM_DEPTH)
249  return false;
250 
251  return true;
252  }
253 
255  {
256  if (f.as<rs2::depth_frame>())
257  _depth_units = ((depth_frame*)f.get())->get_units();
258  if (f.get_profile().get() != _source_stream_profile.get())
259  {
262 
263  // workaround for D457
264  //auto info = disparity_info::update_info_from_frame(f);
265  //_d2d_convert_factor = info.d2d_convert_factor;
266  _d2d_convert_factor = 681678.625;
267  }
268 
270  {
271  auto depth_format = depth.get_profile().format();
272  const auto w = depth.get_width(), h = depth.get_height();
273  auto rgb_data = reinterpret_cast<uint8_t*>(const_cast<void *>(rgb.get_data()));
274  auto coloring_function = [&, this](float data) {
275  auto hist_data = _hist_data[(int)data];
276  auto pixels = (float)_hist_data[MAX_DEPTH - 1];
277  return (hist_data / pixels);
278  };
279 
281  {
282  auto depth_data = reinterpret_cast<const float*>(depth.get_data());
283  update_histogram(_hist_data, depth_data, w, h);
284  make_rgb_data<float>(depth_data, rgb_data, w, h, coloring_function);
285  }
286  else if (depth_format == RS2_FORMAT_Z16)
287  {
288  auto depth_data = reinterpret_cast<const uint16_t*>(depth.get_data());
289  update_histogram(_hist_data, depth_data, w, h);
290  make_rgb_data<uint16_t>(depth_data, rgb_data, w, h, coloring_function);
291  }
292  };
293 
295  {
296  auto depth_format = depth.get_profile().format();
297  const auto w = depth.get_width(), h = depth.get_height();
298  auto rgb_data = reinterpret_cast<uint8_t*>(const_cast<void *>(rgb.get_data()));
299 
301  {
302  auto depth_data = reinterpret_cast<const float*>(depth.get_data());
303  // convert from depth min max to disparity min max
304  // note: max min value is inverted in disparity domain
305  auto __min = _min;
306  if (__min < 1e-6f) { __min = 1e-6f; } // Min value set to prevent zero division. only when _min is zero.
307  auto max = (_d2d_convert_factor / (__min)) * _depth_units + .5f;
308  auto min = (_d2d_convert_factor / (_max)) * _depth_units + .5f;
309  auto coloring_function = [&, this](float data) {
310  return (data - min) / (max - min);
311  };
312  make_rgb_data<float>(depth_data, rgb_data, w, h, coloring_function);
313  }
314  else if (depth_format == RS2_FORMAT_Z16)
315  {
316  auto depth_data = reinterpret_cast<const uint16_t*>(depth.get_data());
317  auto min = _min;
318  auto max = _max;
319  auto coloring_function = [&, this](float data) {
320  if (min >= max) return 0.f;
321  return (data * _depth_units - min) / (max - min);
322  };
323  make_rgb_data<uint16_t>(depth_data, rgb_data, w, h, coloring_function);
324  }
325  };
326 
327  rs2::frame ret;
328 
329  auto vf = f.as<rs2::video_frame>();
330  ret = source.allocate_video_frame(_target_stream_profile, f, 3, vf.get_width(), vf.get_height(), vf.get_width() * 3, RS2_EXTENSION_VIDEO_FRAME);
331 
332  if (_equalize)
333  make_equalized_histogram(f, ret);
334  else
335  make_value_cropped_frame(f, ret);
336 
337  return ret;
338  }
339 }
static color_map hue
Definition: colorizer.cpp:16
GLsizei GLsizei GLchar * source
static color_map cold
Definition: colorizer.cpp:62
rs2::stream_profile _source_stream_profile
Definition: colorizer.h:167
GLuint const GLchar * name
GLuint GLfloat * val
static const int MAX_DEPTH
Definition: colorizer.h:117
rs2_format format() const
Definition: rs_frame.hpp:44
static color_map pattern
Definition: colorizer.cpp:84
bool should_process(const rs2::frame &frame) override
Definition: colorizer.cpp:243
static color_map quantized
Definition: colorizer.cpp:79
static color_map grayscale
Definition: colorizer.cpp:43
static color_map inv_grayscale
Definition: colorizer.cpp:48
GLint GLint GLsizei GLsizei GLsizei depth
unsigned short uint16_t
Definition: stdint.h:79
static color_map classic
Definition: colorizer.cpp:34
rs2::frame process_frame(const rs2::frame_source &source, const rs2::frame &f) override
Definition: colorizer.cpp:254
GLdouble GLdouble GLdouble w
static color_map warm
Definition: colorizer.cpp:70
bool is() const
Definition: rs_frame.hpp:572
unsigned char uint8_t
Definition: stdint.h:78
e
Definition: rmse.py:177
frame allocate_video_frame(const stream_profile &profile, const frame &original, int new_bpp=0, int new_width=0, int new_height=0, int new_stride=0, rs2_extension frame_type=RS2_EXTENSION_VIDEO_FRAME) const
void register_option(rs2_option id, std::shared_ptr< option > option)
Definition: options.h:86
void make_equalized_histogram(depth_pixel *dst, const rs2::video_frame &depth, const color_map &cm)
std::vector< int > _histogram
Definition: colorizer.h:162
std::vector< color_map * > _maps
Definition: colorizer.h:159
T as() const
Definition: rs_frame.hpp:582
rs2::stream_profile _target_stream_profile
Definition: colorizer.h:166
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
int stream_index() const
Definition: rs_frame.hpp:34
int get_height() const
Definition: rs_frame.hpp:673
const rs2_stream_profile * get() const
Definition: rs_frame.hpp:137
int get_width() const
Definition: rs_frame.hpp:661
const void * get_data() const
Definition: rs_frame.hpp:547
int min(int a, int b)
Definition: lz4s.c:73
GLdouble f
static color_map jet
Definition: colorizer.cpp:26
static color_map biomes
Definition: colorizer.cpp:53
static void update_histogram(int *hist, const T *depth_data, int w, int h)
Definition: colorizer.h:104
GLushort pattern
GLboolean * data
rs2_stream stream_type() const
Definition: rs_frame.hpp:39
int h
Definition: sw.py:17
rs2_frame * get() const
Definition: rs_frame.hpp:592
void make_value_cropped_frame(depth_pixel *dst, const rs2::video_frame &depth, const color_map &cm, float depth_min, float depth_max, float depth_units)
Definition: parser.hpp:153
stream_profile clone(rs2_stream type, int index, rs2_format format) const
Definition: rs_frame.hpp:63
stream_profile get_profile() const
Definition: rs_frame.hpp:559


librealsense2
Author(s): LibRealSense ROS Team
autogenerated on Thu Dec 22 2022 03:43:16