IntelRealSense / librealsense

Intel® RealSense™ SDK
https://www.intelrealsense.com/
Apache License 2.0
7.53k stars 4.81k forks source link

Save 2D image with D455 #10483

Closed UserFLO closed 2 years ago

UserFLO commented 2 years ago

Hi, i would like to save a 2D image from D455. I succeed to get a depth but not the 2D image. How can i get this information with the command _auto frames = pipe.wait_forframes();

thank you ! This is my algorithm :

#include <iostream>
#include <algorithm> 
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>
#include <opencv2/opencv.hpp>

#include <librealsense2/rs.hpp> 

#include </usr/include/pcl-1.10/pcl/io/pcd_io.h>
#include <pcl/conversions.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/common/common_headers.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/parse.h>
#include <pcl/io/io.h>
#include <pcl/visualization/cloud_viewer.h>

using namespace std; 

typedef pcl::PointXYZRGB RGB_Cloud;
typedef pcl::PointCloud <RGB_Cloud> point_cloud; 
typedef point_cloud:: Ptr cloud_pointer;
typedef point_cloud:: Ptr prevCloud; 

void Load_PCDFile(void);
bool userInput(void); 
void cloudViewer(void);

string cloudfile;
string prevCloudFile;
int i =1; 

//int width = 560;
//int height = 280;

std::tuple<int,int,int> RGB_Texture(rs2::video_frame texture, rs2::texture_coordinate Texture_XY) 
{
    int width = texture.get_width(); 
    int height = texture.get_height();

    int x_value = min(max(int(Texture_XY.u * width + .5f),0), width-1); 
    int y_value = min(max(int(Texture_XY.v * height + .5f),0), height-1); 

    int bytes = x_value * texture.get_bytes_per_pixel(); 
    int strides = y_value * texture.get_stride_in_bytes(); 
    int Text_Index = (bytes + strides); 

    const auto New_Texture = reinterpret_cast<const uint8_t*>(texture.get_data()); 

    int NT1 = New_Texture[Text_Index]; 
    int NT2 = New_Texture[Text_Index +1]; 
    int NT3 = New_Texture[Text_Index +2]; 

    return std::tuple<int,int,int>(NT1,NT2,NT3); 
} 

cloud_pointer PCL_Conversion(const rs2::points&points, const rs2::video_frame &color){

    cloud_pointer cloud(new point_cloud); 
    std::tuple<uint8_t, uint8_t,uint8_t> RGB_Color; 

    auto sp = points.get_profile().as<rs2::video_stream_profile>();

    cloud->width = static_cast<uint32_t>( sp.width() );
    cloud->height = static_cast<uint32_t>( sp.height() );
    cloud->is_dense = false; 
    cloud->points.resize( points.size() ); 

    auto Texture_Coord = points.get_texture_coordinates(); 
    auto Vertex = points.get_vertices(); 

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

        RGB_Color = RGB_Texture(color, Texture_Coord[i]); 

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

    } 
    return cloud;
}

int main () try
{
    bool captureLoop = true; 

    pcl::PointCloud<pcl::PointXYZRGB>::Ptr newCloud (new pcl::PointCloud<pcl::PointXYZRGB>); 
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out (new pcl::PointCloud<pcl::PointXYZ>);
    boost::shared_ptr<pcl::visualization::PCLVisualizer> openCloud; 

    rs2::pointcloud pc; 
    rs2::pipeline pipe; 
    rs2::config cfg; 
    rs2::rates_printer printer;

    cfg.enable_stream(RS2_STREAM_COLOR,640,360); 
    cfg.enable_stream(RS2_STREAM_INFRARED,640,360);
    cfg.enable_stream(RS2_STREAM_DEPTH,640,360);

    rs2::pipeline_profile selection = pipe.start(cfg); 

    rs2::device selected_device = selection.get_device(); 
    auto depth_sensor = selected_device.first<rs2::depth_sensor>(); 

    if (depth_sensor.supports(RS2_OPTION_EMITTER_ENABLED))
    {
        depth_sensor.set_option(RS2_OPTION_EMITTER_ENABLED, 1.f); 
        pipe.wait_for_frames(); 
        depth_sensor.set_option(RS2_OPTION_EMITTER_ENABLED, 0.f); 
    }

    if (depth_sensor.supports(RS2_OPTION_LASER_POWER))
    {
        auto range = depth_sensor.get_option_range(RS2_OPTION_LASER_POWER); 
        depth_sensor.set_option(RS2_OPTION_LASER_POWER, range.max); 
        sleep(1); 
        depth_sensor.set_option(RS2_OPTION_LASER_POWER, 0.f); 
    } 

    /*while(captureLoop == true) {

        captureLoop = userInput(); 
        if (captureLoop == false) { break; } 

        for( int i = 0; i<30; i++) {
            auto frames = pipe.wait_for_frames(); 
        }*/

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

    pc.map_to(color); 

    //cv::imwrite("Image.jpg",color);

    auto points = pc.calculate(depth); 

    cloud_pointer cloud = PCL_Conversion(points,color);

    /*pcl::PassThrough<pcl::PointXYZRGB> Cloud_Filter; 
    Cloud_Filter.setInputCloud(cloud); 
    Cloud_Filter.setFilterFieldName("z");
    Cloud_Filter.setFilterLimits(0.0,1.0); 
    Cloud_Filter.filter(*newCloud); */ 

    pcl::copyPointCloud(*cloud,*cloud_out);
    pcl::io::savePCDFile ("cloudXYZ_fourches.pcd", *cloud_out);

        //cloudfile = "Captured_Frame" + to_string(i) + ".pcd"; 
    cloudfile = "Frame_carton_2.pcd"; 
    cout << "Generating PCD Point Cloud File..." <<endl; 
    pcl::io::savePCDFileASCII(cloudfile, *cloud); 
    cout<< cloudfile << "successfully generated."<< endl; 
    cout<<"Nombre points : "<<cloud->points.size ()<<endl;

    //Load_PCDFile(); 
//  i++;

    //}

    cout <<"Exiting Program..." <<endl; 
    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; 
}    

void Load_PCDFile(void) 
{
    string openFileName; 
    pcl::PointCloud<pcl::PointXYZRGB> ::Ptr cloudView (new pcl::PointCloud<pcl::PointXYZRGB>);

    openFileName = "cloudXYZ.pcd";
    pcl::io::loadPCDFile (openFileName, *cloudView); 

    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("Captured Frame XYZ")); 

    viewer->setBackgroundColor(0,0,0); 
    viewer->addPointCloud<pcl::PointXYZRGB> (cloudView, "Cloud"); 
    viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,1,"Cloud"); 
    viewer->initCameraParameters(); 

    cout<<endl; 
    cout<<"Press [Q] in viewer to continue."<<endl; 
    viewer->spin(); 
}   

bool userInput(void){

    bool setLoopFlag; 
    bool inputCheck = false; 
    char takeFrame; 
    do {
        cout<<endl; 
        cout<<"Generate a Point cloud? [y/n]"; 
        cin>>takeFrame; 
        cout<<endl; 

        if (takeFrame=='y' || takeFrame=='Y'){
            setLoopFlag = true; 
            inputCheck = true; 
            takeFrame = 0; 
        } 

        else if (takeFrame=='n' || takeFrame=='N'){ 
            setLoopFlag = false; 
            inputCheck = false; 
            takeFrame = 0; 
        } 

        else {
            inputCheck = false; 
            cout <<"Invalid Input."<<endl; 
        } 
    } while(inputCheck==false);
    return setLoopFlag; 

}
MartyG-RealSense commented 2 years ago

Hi @UserFLO The RealSense SDK has a C++ example program called rs-save-to-disk that demonstrates saving 2D depth and RGB to PNG image file.

https://github.com/IntelRealSense/librealsense/tree/master/examples/save-to-disk https://github.com/IntelRealSense/librealsense/blob/master/examples/save-to-disk/rs-save-to-disk.cpp#L34

UserFLO commented 2 years ago

@MartyG-RealSense Thank you for your answer. But i don't want to save the depth as 2D image but the capture from one single camera (left for example) and save it. (an image XYRGB) with openCV

MartyG-RealSense commented 2 years ago

Would Intel's RealSense OpenCV Getting Started tutorial at the link below help to meet your needs, please?

https://github.com/IntelRealSense/librealsense/blob/master/doc/stepbystep/getting_started_with_openCV.md

It provides example scripts for displaying color or left infrared images with the OpenCV imshow instruction. You could conceivably change imshow to the imwrite instruction to save the images instead of showing them on screen.

https://github.com/IntelRealSense/librealsense/issues/1480 also provides an example of scripting for exporting IR and color to PNG image file with imwrite.

MartyG-RealSense commented 2 years ago

Hi @UserFLO Do you require further assistance with this case, please? Thanks!

UserFLO commented 2 years ago

@MartyG-RealSense No thank you !

MartyG-RealSense commented 2 years ago

That's great to hear. Thanks very much for the update! As you do not require further assistance, I will close this case. Thanks again!