isl-org / Open3D

Open3D: A Modern Library for 3D Data Processing
http://www.open3d.org
Other
10.93k stars 2.24k forks source link

How to initialize a float Image from a vector in C++ #6683

Open amstrudy opened 4 months ago

amstrudy commented 4 months ago

Checklist

My Question

I'm looking to use the open3d::geometry::PointCloud::CreateFromDepthImage function from some depth images I have. These depth images are stored as TIFF files, where each value represents a distance in meters (unscaled), which I can then read into a 1D vector. However, I am unable to find a way to create an open3d image from this float vector.

I've tried creating a blank Image and then updating the .data_, .height_, etc parameters, but the data vector type is unsigned char.

// depth_data is a std::vector<float> and depth_mat is an OpenCV mat
auto depth_img = open3d::geometry::Image();

depth_img_p->data_ = depth_data; // ERROR HERE
depth_img.width_ = depth_mat.size().width;
depth_img.height_ = depth_mat.size().height;
depth_img.channels_ = depth_mat.channels();

I know that there are functions to convert an image to a float image, but the documentation is nonexistent and after running that function the type of the underlying data vector in the Image class is still unsigned char. Any help is much appreciated!

sitic commented 4 months ago

bytes_per_channel_ controls how the data_ values are interpreted, for float it should be 4 (one float32 stored as 4 uint8). Try something like

#include <cstring>

img->Prepare(width, height, num_of_channels, 4);
std::memcpy(img->data_.data(), depth_data.data(), img->data_.size());
ssheorey commented 4 months ago

Hi @amstrudy another option would be to store the data in mm as uint16 (multiply by 1000 and convert to uint16) This works for many indoor use cases (range about 16 meters and resolution 1mm).

Here is some documentation about @sitic 's answer : https://www.open3d.org/docs/latest/cpp_api/classopen3d_1_1geometry_1_1_image.html#a682431d2232ded7ba6e7a8a84ba2c4d7