Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to get only Voxel locations and colors. I don't want vertex normals and faces. #6411

Closed
piyush2989 opened this issue May 18, 2020 · 8 comments

Comments

@piyush2989
Copy link

  • Before opening a new issue, we wanted to provide you with some useful suggestions (Click "Preview" above for a better view):

  • All users are welcomed to report bugs, ask questions, suggest or request enhancements and generally feel free to open new issue, even if they haven't followed any of the suggestions above :)


Required Info
Camera Model D435i
Firmware Version 05.11.15.00
Operating System & Version Linux (Ubuntu 18.04)
Kernel Version (Linux Only) (e.g. 4.14.13)
Platform PC
SDK Version 2.33.1 }
Language {C++ }
Segment

Issue Description

I can save point cloud from C++ using the following:

auto frames = pipe.wait_for_frames();
auto depth = frames.get_depth_frame();
auto color = frames.get_color_frame();
pc.map_to(color);
points = pc.calculate(depth);
points.export_to_ply("your_filename.ply", color);

Howsoever, the saved ply, is a mesh with faces. Is there a way to disable this.

Also, the saved ply is heavy, can I decimate and control number of points, before saving.

Regards.

@MartyG-RealSense
Copy link
Collaborator

MartyG-RealSense commented May 18, 2020

The best approach to getting a voxelized cloud with RealSense may be to use Point Cloud Library (PCL), as the RealSense SDK 2.0 software has a compatibility 'wrapper' for PCL. Please google for
'pcl voxels' for more details. Here is an example from such a search:

https://stackoverflow.com/questions/57916947/understanding-the-voxel-grid-implementation-of-pcl-library

The RealSense PCL wrapper can be found here:

https://github.com/IntelRealSense/librealsense/tree/master/wrappers/pcl

In regard to decimation of point cloud data with C++ in RealSense, I hope that the link below will be helpful

#2100

@piyush2989
Copy link
Author

Okay,
So using the code fragment from /wrappers/pcl/pcl/rs-pcl.cpp I am able to get the point cloud locations, and able to save it using PCL's functions.


auto pcl_points = points_to_pcl(points);
pcl::io::savePLYFileASCII ("test_ply.ply", *pcl_points);

For getting the color values for each vertex,
I tried to extend the helper function points_to_pcl using
pcl_ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
What are the color fields on rs2::points& points side ?

for (auto& p : cloud->points)
    {
        p.x = ptr->x;
        p.y = ptr->y;
        p.z = ptr->z;
        p.r = **?**
        p.g = **?**
        p.b = **?**
        ptr++;
    }

@piyush2989
Copy link
Author

I am reading on this
#1143

@MartyG-RealSense
Copy link
Collaborator

Apologies for the delay in responding further, as I was researching your question extensively because I am not familiar with PCL programming. The only other reference I could find that seemed relevant was this one:

#1601 (comment)

@piyush2989
Copy link
Author

Okay so finally able to get it.

Some Reference: https://github.com/Resays/xyz_rgb_realsense/blob/ede2bf9cc81d67ff0a7b616a5c70ff529e43bfe3/xyz_rgb_realsense.cpp

Here is a working code snippet (dirty), if it helps someone.

#include <librealsense2/rs.hpp> // Include RealSense Cross Platform API

#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>

using pcl_ptr = pcl::PointCloud<pcl::PointXYZRGB>::Ptr;

std::tuple<uint8_t, uint8_t, uint8_t> get_texcolor(rs2::video_frame texture, rs2::texture_coordinate texcoords)
{
    const int w = texture.get_width(), h = texture.get_height();
    int x = std::min(std::max(int(texcoords.u*w + .5f), 0), w - 1);
    int y = std::min(std::max(int(texcoords.v*h + .5f), 0), h - 1);
    int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes();
    const auto texture_data = reinterpret_cast<const uint8_t*>(texture.get_data());
    return std::tuple<uint8_t, uint8_t, uint8_t>( texture_data[idx], texture_data[idx + 1], texture_data[idx + 2] );
}

// **Passed colors as well**
pcl_ptr points_to_pcl(const rs2::points& points, auto colors)
{
    //  pcl_ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    pcl_ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    auto sp = points.get_profile().as<rs2::video_stream_profile>();
    cloud->width = sp.width();
    cloud->height = sp.height();
    cloud->is_dense = false;
    cloud->points.resize(points.size());
    auto ptr = points.get_vertices();
    auto tex_coord = points.get_texture_coordinates();

    for (int i = 0; i < points.size(); i++)
    {
        cloud->points[i].x = ptr[i].x;

        cloud->points[i].y = ptr[i].y;
        cloud->points[i].z = ptr[i].z;
        auto current_color  =  get_texcolor(colors,tex_coord[i]);

        cloud->points[i].r = std::get<0>(current_color);
        cloud->points[i].g =  std::get<1>(current_color);
        cloud->points[i].b = std::get<2>(current_color);

    }
    return cloud;
}

int main(int argc, char * argv[]) try
{


    rs2::pointcloud pc;
    // We want the points object to be persistent so we can display the last cloud when a frame drops
    rs2::points points;

    // Declare RealSense pipeline, encapsulating the actual device and sensors
    rs2::pipeline pipe;
    // Start streaming with default recommended configuration
    pipe.start();


    for (int i = 0; i < 30;  i++) {

        auto frames = pipe.wait_for_frames();
    }

    // Wait for the next set of frames from the camera
    auto frames = pipe.wait_for_frames();

    auto color = frames.get_color_frame();
    auto depth = frames.get_depth_frame();

    // Tell pointcloud object to map to this color frame
    pc.map_to(color);
    // Generate the pointcloud and texture mappings
    points = pc.calculate(depth);

    auto pcl_points = points_to_pcl(points,color);


    pcl::io::savePLYFileASCII ("test_ply.ply", *pcl_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;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_EXPORT_COMPILE_COMMANDS=ON)
project(rspcl)

find_package(PCL 1.2 REQUIRED)
# Find librealsense2 installed package
find_package(realsense2 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})

link_directories(${PCL_LIBRARY_DIRS})

add_definitions(${PCL_DEFINITIONS})

add_executable (output main.cpp)
target_link_libraries (output ${PCL_LIBRARIES} ${realsense2_LIBRARY})

@MartyG-RealSense
Copy link
Collaborator

Great news that you found a solution - thanks so much for sharing your code with the RealSense community :)

@AndreV84
Copy link

@piyush2989 @MartyG-RealSense
Could you extend how to build execute the code below in order to get .ply with mesh, please?

auto frames = pipe.wait_for_frames();
auto depth = frames.get_depth_frame();
auto color = frames.get_color_frame();
pc.map_to(color);
points = pc.calculate(depth);
points.export_to_ply("your_filename.ply", color);

@MartyG-RealSense
Copy link
Collaborator

Hi @AndreV84 Saving a ply with color and normals in Python will be very difficult to achieve. The only working method I know of for exporting a color ply successfully in Python is to export without normals using scripting at #6194 (comment)

If you are able to use C++ then you could potentially use save_to_ply() (which provides a range of ply customization settings) instead of export_to_ply to save the color and mesh to ply.

#4906
#6979 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants