align.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 #include "../include/librealsense2/rsutil.h"
7 
8 #include "core/video.h"
10 #include "environment.h"
11 #include "align.h"
12 #include "stream.h"
13 
14 namespace librealsense
15 {
16  template<int N> struct bytes { byte b[N]; };
17 
18  template<class GET_DEPTH, class TRANSFER_PIXEL>
19  void align_images(const rs2_intrinsics& depth_intrin, const rs2_extrinsics& depth_to_other,
20  const rs2_intrinsics& other_intrin, GET_DEPTH get_depth, TRANSFER_PIXEL transfer_pixel)
21  {
22  // Iterate over the pixels of the depth image
23 #pragma omp parallel for schedule(dynamic)
24  for (int depth_y = 0; depth_y < depth_intrin.height; ++depth_y)
25  {
26  int depth_pixel_index = depth_y * depth_intrin.width;
27  for (int depth_x = 0; depth_x < depth_intrin.width; ++depth_x, ++depth_pixel_index)
28  {
29  // Skip over depth pixels with the value of zero, we have no depth data so we will not write anything into our aligned images
30  if (float depth = get_depth(depth_pixel_index))
31  {
32  // Map the top-left corner of the depth pixel onto the other image
33  float depth_pixel[2] = { depth_x - 0.5f, depth_y - 0.5f }, depth_point[3], other_point[3], other_pixel[2];
34  rs2_deproject_pixel_to_point(depth_point, &depth_intrin, depth_pixel, depth);
35  rs2_transform_point_to_point(other_point, &depth_to_other, depth_point);
36  rs2_project_point_to_pixel(other_pixel, &other_intrin, other_point);
37  const int other_x0 = static_cast<int>(other_pixel[0] + 0.5f);
38  const int other_y0 = static_cast<int>(other_pixel[1] + 0.5f);
39 
40  // Map the bottom-right corner of the depth pixel onto the other image
41  depth_pixel[0] = depth_x + 0.5f; depth_pixel[1] = depth_y + 0.5f;
42  rs2_deproject_pixel_to_point(depth_point, &depth_intrin, depth_pixel, depth);
43  rs2_transform_point_to_point(other_point, &depth_to_other, depth_point);
44  rs2_project_point_to_pixel(other_pixel, &other_intrin, other_point);
45  const int other_x1 = static_cast<int>(other_pixel[0] + 0.5f);
46  const int other_y1 = static_cast<int>(other_pixel[1] + 0.5f);
47 
48  if (other_x0 < 0 || other_y0 < 0 || other_x1 >= other_intrin.width || other_y1 >= other_intrin.height)
49  continue;
50 
51  // Transfer between the depth pixels and the pixels inside the rectangle on the other image
52  for (int y = other_y0; y <= other_y1; ++y)
53  {
54  for (int x = other_x0; x <= other_x1; ++x)
55  {
56  transfer_pixel(depth_pixel_index, y * other_intrin.width + x);
57  }
58  }
59  }
60  }
61  }
62  }
63 
64  align::align(rs2_stream to_stream) : align(to_stream, "Align")
65  {}
66 
68  const rs2::video_frame& depth, const rs2::video_stream_profile& other_profile, float z_scale)
69  {
70  byte* aligned_data = reinterpret_cast<byte*>(const_cast<void*>(aligned.get_data()));
71  auto aligned_profile = aligned.get_profile().as<rs2::video_stream_profile>();
72  memset(aligned_data, 0, aligned_profile.height() * aligned_profile.width() * aligned.get_bytes_per_pixel());
73 
75 
76  auto z_intrin = depth_profile.get_intrinsics();
77  auto other_intrin = other_profile.get_intrinsics();
78  auto z_to_other = depth_profile.get_extrinsics_to(other_profile);
79 
80  auto z_pixels = reinterpret_cast<const uint16_t*>(depth.get_data());
81  auto out_z = (uint16_t *)(aligned_data);
82 
83  align_images(z_intrin, z_to_other, other_intrin,
84  [z_pixels, z_scale](int z_pixel_index) { return z_scale * z_pixels[z_pixel_index]; },
85  [out_z, z_pixels](int z_pixel_index, int other_pixel_index)
86  {
87  out_z[other_pixel_index] = out_z[other_pixel_index] ?
88  std::min((int)out_z[other_pixel_index], (int)z_pixels[z_pixel_index]) :
89  z_pixels[z_pixel_index];
90  });
91  }
92 
93  template<int N, class GET_DEPTH>
94  void align_other_to_depth_bytes(byte* other_aligned_to_depth, GET_DEPTH get_depth, const rs2_intrinsics& depth_intrin, const rs2_extrinsics& depth_to_other, const rs2_intrinsics& other_intrin, const byte* other_pixels)
95  {
96  auto in_other = (const bytes<N> *)(other_pixels);
97  auto out_other = (bytes<N> *)(other_aligned_to_depth);
98  align_images(depth_intrin, depth_to_other, other_intrin, get_depth,
99  [out_other, in_other](int depth_pixel_index, int other_pixel_index) { out_other[depth_pixel_index] = in_other[other_pixel_index]; });
100  }
101 
102  template<class GET_DEPTH>
103  void align_other_to_depth(byte* other_aligned_to_depth, GET_DEPTH get_depth, const rs2_intrinsics& depth_intrin, const rs2_extrinsics & depth_to_other, const rs2_intrinsics& other_intrin, const byte* other_pixels, rs2_format other_format)
104  {
105  switch (other_format)
106  {
107  case RS2_FORMAT_Y8:
108  align_other_to_depth_bytes<1>(other_aligned_to_depth, get_depth, depth_intrin, depth_to_other, other_intrin, other_pixels);
109  break;
110  case RS2_FORMAT_Y16:
111  case RS2_FORMAT_Z16:
112  align_other_to_depth_bytes<2>(other_aligned_to_depth, get_depth, depth_intrin, depth_to_other, other_intrin, other_pixels);
113  break;
114  case RS2_FORMAT_RGB8:
115  case RS2_FORMAT_BGR8:
116  align_other_to_depth_bytes<3>(other_aligned_to_depth, get_depth, depth_intrin, depth_to_other, other_intrin, other_pixels);
117  break;
118  case RS2_FORMAT_RGBA8:
119  case RS2_FORMAT_BGRA8:
120  align_other_to_depth_bytes<4>(other_aligned_to_depth, get_depth, depth_intrin, depth_to_other, other_intrin, other_pixels);
121  break;
122  default:
123  assert(false); // NOTE: rs2_align_other_to_depth_bytes<2>(...) is not appropriate for RS2_FORMAT_YUYV/RS2_FORMAT_RAW10 images, no logic prevents U/V channels from being written to one another
124  }
125  }
126 
127  void align::align_other_to_z(rs2::video_frame& aligned, const rs2::video_frame& depth, const rs2::video_frame& other, float z_scale)
128  {
129  byte* aligned_data = reinterpret_cast<byte*>(const_cast<void*>(aligned.get_data()));
130  auto aligned_profile = aligned.get_profile().as<rs2::video_stream_profile>();
131  memset(aligned_data, 0, aligned_profile.height() * aligned_profile.width() * aligned.get_bytes_per_pixel());
132 
135 
136  auto z_intrin = depth_profile.get_intrinsics();
137  auto other_intrin = other_profile.get_intrinsics();
138  auto z_to_other = depth_profile.get_extrinsics_to(other_profile);
139 
140  auto z_pixels = reinterpret_cast<const uint16_t*>(depth.get_data());
141  auto other_pixels = reinterpret_cast<const byte*>(other.get_data());
142 
143  align_other_to_depth(aligned_data, [z_pixels, z_scale](int z_pixel_index) { return z_scale * z_pixels[z_pixel_index]; },
144  z_intrin, z_to_other, other_intrin, other_pixels, other_profile.format());
145  }
146 
147  std::shared_ptr<rs2::video_stream_profile> align::create_aligned_profile(
148  rs2::video_stream_profile& original_profile,
150  {
151  auto from_to = std::make_pair(original_profile.get()->profile, to_profile.get()->profile);
152  auto it = _align_stream_unique_ids.find(from_to);
153  if (it != _align_stream_unique_ids.end())
154  {
155  return it->second;
156  }
157  auto aligned_profile = std::make_shared<rs2::video_stream_profile>(original_profile.clone(original_profile.stream_type(), original_profile.stream_index(), original_profile.format()));
158  aligned_profile->get()->profile->set_framerate(original_profile.fps());
159  if (auto original_video_profile = As<video_stream_profile_interface>(original_profile.get()->profile))
160  {
161  if (auto to_video_profile = As<video_stream_profile_interface>(to_profile.get()->profile))
162  {
163  if (auto aligned_video_profile = As<video_stream_profile_interface>(aligned_profile->get()->profile))
164  {
165  aligned_video_profile->set_dims(to_video_profile->get_width(), to_video_profile->get_height());
166  auto aligned_intrinsics = to_video_profile->get_intrinsics();
167  aligned_intrinsics.width = to_video_profile->get_width();
168  aligned_intrinsics.height = to_video_profile->get_height();
169  aligned_video_profile->set_intrinsics([aligned_intrinsics]() { return aligned_intrinsics; });
170  aligned_profile->register_extrinsics_to(to_profile, { { 1,0,0,0,1,0,0,0,1 },{ 0,0,0 } });
171  }
172  }
173  }
174  _align_stream_unique_ids[from_to] = aligned_profile;
175  reset_cache(original_profile.stream_type(), to_profile.stream_type());
176  return aligned_profile;
177  }
178 
180  {
181  if (!frame)
182  return false;
183 
184  auto set = frame.as<rs2::frameset>();
185  if (!set)
186  return false;
187 
188  auto profile = frame.get_profile();
189  rs2_stream stream = profile.stream_type();
191  int index = profile.stream_index();
192 
193  //process composite frame only if it contains both a depth frame and the requested texture frame
194  bool has_tex = false, has_depth = false;
195  set.foreach_rs([this, &has_tex](const rs2::frame& frame) { if (frame.get_profile().stream_type() == _to_stream_type) has_tex = true; });
196  set.foreach_rs([&has_depth](const rs2::frame& frame)
197  { if (frame.get_profile().stream_type() == RS2_STREAM_DEPTH && frame.get_profile().format() == RS2_FORMAT_Z16) has_depth = true; });
198  if (!has_tex || !has_depth)
199  return false;
200 
201  return true;
202  }
203 
205  {
207  return ext;
208  }
209 
211  {
212  rs2::frame rv;
213  auto from_bytes_per_pixel = from.get_bytes_per_pixel();
214 
215  auto from_profile = from.get_profile().as<rs2::video_stream_profile>();
217 
218  auto aligned_profile = create_aligned_profile(from_profile, to_profile);
219 
220  auto ext = select_extension(from);
221 
222  rv = source.allocate_video_frame(
223  *aligned_profile,
224  from,
225  from_bytes_per_pixel,
226  to.get_width(),
227  to.get_height(),
228  to.get_width() * from_bytes_per_pixel,
229  ext);
230  return rv;
231  }
232 
234  {
235  auto from_profile = from.get_profile().as<rs2::video_stream_profile>();
237 
238  auto aligned_profile = aligned.get_profile().as<rs2::video_stream_profile>();
239 
240  if (to_profile.stream_type() == RS2_STREAM_DEPTH)
241  {
242  align_other_to_z(aligned, to, from, _depth_scale);
243  }
244  else
245  {
246  align_z_to_other(aligned, from, to_profile, _depth_scale);
247  }
248  }
249 
251  {
252  rs2::frame rv;
253  std::vector<rs2::frame> output_frames;
254  std::vector<rs2::frame> other_frames;
255 
256  auto frames = f.as<rs2::frameset>();
257  auto depth = frames.first_or_default(RS2_STREAM_DEPTH, RS2_FORMAT_Z16).as<rs2::depth_frame>();
258 
259  _depth_scale = ((librealsense::depth_frame*)depth.get())->get_units();
260 
262  frames.foreach_rs([&other_frames](const rs2::frame& f) {if ((f.get_profile().stream_type() != RS2_STREAM_DEPTH) && f.is<rs2::video_frame>()) other_frames.push_back(f); });
263  else
264  frames.foreach_rs([this, &other_frames](const rs2::frame& f) {if (f.get_profile().stream_type() == _to_stream_type) other_frames.push_back(f); });
265 
267  {
268  for (auto from : other_frames)
269  {
270  auto aligned_frame = allocate_aligned_frame(source, from, depth);
271  align_frames(aligned_frame, from, depth);
272  output_frames.push_back(aligned_frame);
273  }
274  }
275  else
276  {
277  auto to = other_frames.front();
278  auto aligned_frame = allocate_aligned_frame(source, depth, to);
279  align_frames(aligned_frame, depth, to);
280  output_frames.push_back(aligned_frame);
281  }
282 
283  auto new_composite = source.allocate_composite_frame(std::move(output_frames));
284  return new_composite;
285  }
286 }
std::map< std::pair< stream_profile_interface *, stream_profile_interface * >, std::shared_ptr< rs2::video_stream_profile > > _align_stream_unique_ids
Definition: align.h:48
static void rs2_transform_point_to_point(float to_point[3], const struct rs2_extrinsics *extrin, const float from_point[3])
Definition: rsutil.h:168
GLboolean GLboolean GLboolean b
GLint y
rs2_frame * get() const
Definition: rs_frame.hpp:590
virtual void align_other_to_z(rs2::video_frame &aligned, const rs2::video_frame &depth, const rs2::video_frame &other, float z_scale)
Definition: align.cpp:127
stream_profile get_profile() const
Definition: rs_frame.hpp:557
float _depth_scale
Definition: align.h:50
int get_bytes_per_pixel() const
Definition: rs_frame.hpp:707
GLint GLint GLsizei GLsizei GLsizei depth
const void * get_data() const
Definition: rs_frame.hpp:545
unsigned short uint16_t
Definition: stdint.h:79
virtual void reset_cache(rs2_stream from, rs2_stream to)
Definition: align.h:29
GLuint index
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
virtual void align_z_to_other(rs2::video_frame &aligned, const rs2::video_frame &depth, const rs2::video_stream_profile &other_profile, float z_scale)
Definition: align.cpp:67
GLdouble f
bool is() const
Definition: rs_frame.hpp:570
static void rs2_deproject_pixel_to_point(float point[3], const struct rs2_intrinsics *intrin, const float pixel[2], float depth)
Definition: rsutil.h:83
GLdouble x
bool should_process(const rs2::frame &frame) override
Definition: align.cpp:179
frame allocate_composite_frame(std::vector< frame > frames) const
GLint GLint GLsizei GLint GLenum format
void align_frames(rs2::video_frame &aligned, const rs2::video_frame &from, const rs2::video_frame &to)
Definition: align.cpp:233
virtual rs2_extension select_extension(const rs2::frame &input)
Definition: align.cpp:204
rs2_format
A stream&#39;s format identifies how binary data is encoded within a frame.
Definition: rs_sensor.h:59
int stream_index() const
Definition: rs_frame.hpp:34
rs2::frame process_frame(const rs2::frame_source &source, const rs2::frame &f) override
Definition: align.cpp:250
rs2_intrinsics get_intrinsics() const
Definition: rs_frame.hpp:238
rs2_stream
Streams are different types of data provided by RealSense devices.
Definition: rs_sensor.h:42
librealsense::stream_profile_interface * profile
Definition: context.h:34
Cross-stream extrinsics: encodes the topology describing how the different devices are oriented...
Definition: rs_sensor.h:96
stream_profile clone(rs2_stream type, int index, rs2_format format, int width, int height, const rs2_intrinsics &intr) const
Definition: rs_frame.hpp:266
rs2_format format() const
Definition: rs_frame.hpp:44
static void rs2_project_point_to_pixel(float pixel[2], const struct rs2_intrinsics *intrin, const float point[3])
Definition: rsutil.h:19
unsigned char byte
Definition: src/types.h:52
void align_other_to_depth_bytes(byte *other_aligned_to_depth, GET_DEPTH get_depth, const rs2_intrinsics &depth_intrin, const rs2_extrinsics &depth_to_other, const rs2_intrinsics &other_intrin, const byte *other_pixels)
Definition: align.cpp:94
rs2_stream _to_stream_type
Definition: align.h:47
rs2_extension
Specifies advanced interfaces (capabilities) objects may implement.
Definition: rs_types.h:166
static auto it
GLenum GLenum GLenum input
Definition: glext.h:10805
stream_profile to_profile(const stream_profile_interface *sp)
Definition: src/stream.h:185
std::shared_ptr< rs2::video_stream_profile > create_aligned_profile(rs2::video_stream_profile &original_profile, rs2::video_stream_profile &to_profile)
Definition: align.cpp:147
void align_images(const rs2_intrinsics &depth_intrin, const rs2_extrinsics &depth_to_other, const rs2_intrinsics &other_intrin, GET_DEPTH get_depth, TRANSFER_PIXEL transfer_pixel)
Definition: align.cpp:19
int get_height() const
Definition: rs_frame.hpp:671
int min(int a, int b)
Definition: lz4s.c:73
const rs2_stream_profile * get() const
Definition: rs_frame.hpp:137
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
Video stream intrinsics.
Definition: rs_types.h:58
GLsizei GLsizei GLchar * source
void align_other_to_depth(byte *other_aligned_to_depth, GET_DEPTH get_depth, const rs2_intrinsics &depth_intrin, const rs2_extrinsics &depth_to_other, const rs2_intrinsics &other_intrin, const byte *other_pixels, rs2_format other_format)
Definition: align.cpp:103
rs2_format format
align(rs2_stream to_stream)
Definition: align.cpp:64
rs2_stream stream_type() const
Definition: rs_frame.hpp:39
int get_width() const
Definition: rs_frame.hpp:659
int fps() const
Definition: rs_frame.hpp:49
T as() const
Definition: rs_frame.hpp:580
rs2::video_frame allocate_aligned_frame(const rs2::frame_source &source, const rs2::video_frame &from, const rs2::video_frame &to)
Definition: align.cpp:210


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