You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
7.5 KiB
221 lines
7.5 KiB
2 months ago
|
// License: Apache 2.0. See LICENSE file in root directory.
|
||
|
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
|
||
|
|
||
|
#include <librealsense2/rs.hpp> // Include RealSense Cross Platform API
|
||
|
#include <librealsense2/hpp/rs_internal.hpp>
|
||
|
#include "example.hpp"
|
||
|
|
||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||
|
#include <stb_image_write.h>
|
||
|
#include <int-rs-splash.hpp>
|
||
|
|
||
|
#define STB_IMAGE_IMPLEMENTATION
|
||
|
#include <stb_image.h>
|
||
|
|
||
|
const int W = 640;
|
||
|
const int H = 480;
|
||
|
const int BPP = 2;
|
||
|
|
||
|
struct synthetic_frame
|
||
|
{
|
||
|
int x, y, bpp;
|
||
|
std::vector<uint8_t> frame;
|
||
|
};
|
||
|
|
||
|
class custom_frame_source
|
||
|
{
|
||
|
public:
|
||
|
custom_frame_source()
|
||
|
{
|
||
|
depth_frame.x = W;
|
||
|
depth_frame.y = H;
|
||
|
depth_frame.bpp = BPP;
|
||
|
|
||
|
last = std::chrono::high_resolution_clock::now();
|
||
|
|
||
|
std::vector<uint8_t> pixels_depth(depth_frame.x * depth_frame.y * depth_frame.bpp, 0);
|
||
|
depth_frame.frame = std::move(pixels_depth);
|
||
|
|
||
|
auto realsense_logo = stbi_load_from_memory(splash, (int)splash_size, &color_frame.x, &color_frame.y, &color_frame.bpp, false);
|
||
|
|
||
|
std::vector<uint8_t> pixels_color(color_frame.x * color_frame.y * color_frame.bpp, 0);
|
||
|
|
||
|
memcpy(pixels_color.data(), realsense_logo, color_frame.x*color_frame.y * 4);
|
||
|
|
||
|
for (auto i = 0; i< color_frame.y; i++)
|
||
|
for (auto j = 0; j < color_frame.x * 4; j += 4)
|
||
|
{
|
||
|
if (pixels_color.data()[i*color_frame.x * 4 + j] == 0)
|
||
|
{
|
||
|
pixels_color.data()[i*color_frame.x * 4 + j] = 22;
|
||
|
pixels_color.data()[i*color_frame.x * 4 + j + 1] = 115;
|
||
|
pixels_color.data()[i*color_frame.x * 4 + j + 2] = 185;
|
||
|
}
|
||
|
}
|
||
|
color_frame.frame = std::move(pixels_color);
|
||
|
stbi_image_free( realsense_logo );
|
||
|
}
|
||
|
|
||
|
synthetic_frame& get_synthetic_texture()
|
||
|
{
|
||
|
return color_frame;
|
||
|
}
|
||
|
|
||
|
synthetic_frame& get_synthetic_depth(glfw_state& app_state)
|
||
|
{
|
||
|
draw_text(50, 50, "This point-cloud is generated from a synthetic device:");
|
||
|
|
||
|
auto now = std::chrono::high_resolution_clock::now();
|
||
|
if (now - last > std::chrono::milliseconds(1))
|
||
|
{
|
||
|
app_state.yaw -= 1;
|
||
|
wave_base += 0.1f;
|
||
|
last = now;
|
||
|
|
||
|
for (int i = 0; i < depth_frame.y; i++)
|
||
|
{
|
||
|
for (int j = 0; j < depth_frame.x; j++)
|
||
|
{
|
||
|
auto d = 2 + 0.1 * (1 + sin(wave_base + j / 50.f));
|
||
|
((uint16_t*)depth_frame.frame.data())[i*depth_frame.x + j] = (int)(d * 0xff);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return depth_frame;
|
||
|
}
|
||
|
|
||
|
rs2_intrinsics create_texture_intrinsics()
|
||
|
{
|
||
|
rs2_intrinsics intrinsics = { color_frame.x, color_frame.y,
|
||
|
(float)color_frame.x / 2, (float)color_frame.y / 2,
|
||
|
(float)color_frame.x / 2, (float)color_frame.y / 2,
|
||
|
RS2_DISTORTION_BROWN_CONRADY ,{ 0,0,0,0,0 } };
|
||
|
|
||
|
return intrinsics;
|
||
|
}
|
||
|
|
||
|
rs2_intrinsics create_depth_intrinsics()
|
||
|
{
|
||
|
rs2_intrinsics intrinsics = { depth_frame.x, depth_frame.y,
|
||
|
(float)depth_frame.x / 2, (float)depth_frame.y / 2,
|
||
|
(float)depth_frame.x , (float)depth_frame.y ,
|
||
|
RS2_DISTORTION_BROWN_CONRADY ,{ 0,0,0,0,0 } };
|
||
|
|
||
|
return intrinsics;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
synthetic_frame depth_frame;
|
||
|
synthetic_frame color_frame;
|
||
|
|
||
|
std::chrono::high_resolution_clock::time_point last;
|
||
|
float wave_base = 0.f;
|
||
|
};
|
||
|
|
||
|
int main(int argc, char * argv[]) try
|
||
|
{
|
||
|
window app(1280, 1500, "RealSense Capture Example");
|
||
|
glfw_state app_state;
|
||
|
register_glfw_callbacks(app, app_state);
|
||
|
rs2::colorizer color_map; // Save colorized depth for preview
|
||
|
|
||
|
rs2::pointcloud pc;
|
||
|
rs2::points points;
|
||
|
int frame_number = 0;
|
||
|
|
||
|
custom_frame_source app_data;
|
||
|
|
||
|
auto texture = app_data.get_synthetic_texture();
|
||
|
|
||
|
rs2_intrinsics color_intrinsics = app_data.create_texture_intrinsics();
|
||
|
rs2_intrinsics depth_intrinsics = app_data.create_depth_intrinsics();
|
||
|
|
||
|
//==================================================//
|
||
|
// Declare Software-Only Device //
|
||
|
//==================================================//
|
||
|
|
||
|
rs2::software_device dev; // Create software-only device
|
||
|
|
||
|
auto depth_sensor = dev.add_sensor("Depth"); // Define single sensor
|
||
|
auto color_sensor = dev.add_sensor("Color"); // Define single sensor
|
||
|
|
||
|
auto depth_stream = depth_sensor.add_video_stream({ RS2_STREAM_DEPTH, 0, 0,
|
||
|
W, H, 60, BPP,
|
||
|
RS2_FORMAT_Z16, depth_intrinsics });
|
||
|
|
||
|
auto color_stream = color_sensor.add_video_stream({ RS2_STREAM_COLOR, 0, 1, texture.x,
|
||
|
texture.y, 60, texture.bpp,
|
||
|
RS2_FORMAT_RGBA8, color_intrinsics });
|
||
|
|
||
|
dev.create_matcher( RS2_MATCHER_DEFAULT ); // Compare all streams according to timestamp
|
||
|
rs2::syncer sync;
|
||
|
|
||
|
depth_sensor.open(depth_stream);
|
||
|
color_sensor.open(color_stream);
|
||
|
|
||
|
depth_sensor.start(sync);
|
||
|
color_sensor.start(sync);
|
||
|
|
||
|
depth_stream.register_extrinsics_to(color_stream, { { 1,0,0,0,1,0,0,0,1 },{ 0,0,0 } });
|
||
|
|
||
|
while (app) // Application still alive?
|
||
|
{
|
||
|
synthetic_frame& depth_frame = app_data.get_synthetic_depth(app_state);
|
||
|
|
||
|
// The timestamp jumps are closely correlated to the FPS passed above to the video streams:
|
||
|
// syncer expects frames to arrive every 1000/FPS milliseconds!
|
||
|
rs2_time_t timestamp = (rs2_time_t)frame_number * 16;
|
||
|
auto domain = RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK;
|
||
|
|
||
|
depth_sensor.on_video_frame( { depth_frame.frame.data(), // Frame pixels from capture API
|
||
|
[]( void * ) {}, // Custom deleter (if required)
|
||
|
depth_frame.x * depth_frame.bpp, // Stride
|
||
|
depth_frame.bpp,
|
||
|
timestamp, domain, frame_number,
|
||
|
depth_stream, 0.001f } ); // depth unit
|
||
|
|
||
|
|
||
|
color_sensor.on_video_frame( { texture.frame.data(), // Frame pixels from capture API
|
||
|
[]( void * ) {}, // Custom deleter (if required)
|
||
|
texture.x * texture.bpp, // Stride
|
||
|
texture.bpp,
|
||
|
timestamp, domain, frame_number,
|
||
|
color_stream } );
|
||
|
|
||
|
++frame_number;
|
||
|
|
||
|
rs2::frameset fset = sync.wait_for_frames();
|
||
|
rs2::frame depth = fset.first_or_default(RS2_STREAM_DEPTH);
|
||
|
rs2::frame color = fset.first_or_default(RS2_STREAM_COLOR);
|
||
|
// We cannot expect the syncer to always output both depth and color -- especially on the
|
||
|
// first few frames! Hiccups can always occur: OS stalls, processing demands, etc...
|
||
|
if (depth && color)
|
||
|
{
|
||
|
if (auto as_depth = depth.as<rs2::depth_frame>())
|
||
|
{
|
||
|
pc.map_to(color);
|
||
|
points = pc.calculate(as_depth);
|
||
|
}
|
||
|
|
||
|
// Upload the color frame to OpenGL
|
||
|
app_state.tex.upload(color);
|
||
|
}
|
||
|
draw_pointcloud(app.width(), app.height(), app_state, points);
|
||
|
}
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
catch (const rs2::error & e)
|
||
|
{
|
||
|
std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
catch (const std::exception& e)
|
||
|
{
|
||
|
std::cerr << e.what() << std::endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|