orbbec / OrbbecSDK

Orbbec SDK v1&v2 Pre-Compiled Repo
https://www.orbbec3d.com/
Other
115 stars 16 forks source link

Compile "Sample-PointCloud" in Visual Studio #144

Open triplecmike opened 2 weeks ago

triplecmike commented 2 weeks ago

Hi,

I'm new to this device and C++ and have a quite basic question. I was trying to compile and run the sample program Sample-PointCloud in Visual Studio. I've added directories through Project -> Properties: VC++ Directories

C:\OrbbecSDK_v1.10.12\SDK\include
C:\OrbbecSDK_v1.10.12\SDK\lib

Linker -> Input

OrbbecSDK.lib

image Many errors popped out when I tried debugging and built the project:

Severity    Code    Description Project File    Line    Suppression State   Details
Error (active)  E0020   identifier "kbhit" is undefined PointCloudTest  C:\Users\mchang\source\repos\PointCloudTest\PointCloudTest\Source.cpp   152     
Error (active)  E0020   identifier "getch" is undefined PointCloudTest  C:\Users\mchang\source\repos\PointCloudTest\PointCloudTest\Source.cpp   153     
Warning C4251   'ob::Context::impl_': 'std::unique_ptr<ContextImpl,std::default_delete<ContextImpl>>' needs to have dll-interface to be used by clients of 'ob::Context'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Context.hpp   23      
Warning C4251   'std::enable_shared_from_this<ob::Filter>::_Wptr': 'std::weak_ptr<_Ty>' needs to have dll-interface to be used by clients of 'std::enable_shared_from_this<ob::Filter>'
        with
        [
            _Ty=ob::Filter
        ]   PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Filter.hpp    27      
Warning C4251   'ob::Filter::impl_': 'std::shared_ptr<FilterImpl>' needs to have dll-interface to be used by clients of 'ob::Filter'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Filter.hpp    103     
Warning C4251   'ob::Filter::type_': 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' needs to have dll-interface to be used by clients of 'ob::Filter'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Filter.hpp    104     
Warning C4251   'ob::Device::impl_': 'std::unique_ptr<DeviceImpl,std::default_delete<DeviceImpl>>' needs to have dll-interface to be used by clients of 'ob::Device'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Device.hpp    31      
Warning C4251   'ob::DeviceInfo::impl_': 'std::unique_ptr<DeviceInfoImpl,std::default_delete<DeviceInfoImpl>>' needs to have dll-interface to be used by clients of 'ob::DeviceInfo'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Device.hpp    642     
Warning C4251   'ob::DeviceList::impl_': 'std::unique_ptr<DeviceListImpl,std::default_delete<DeviceListImpl>>' needs to have dll-interface to be used by clients of 'ob::DeviceList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Device.hpp    759     
Warning C4251   'ob::CameraParamList::impl_': 'std::unique_ptr<CameraParamListImpl,std::default_delete<CameraParamListImpl>>' needs to have dll-interface to be used by clients of 'ob::CameraParamList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Device.hpp    869     
Warning C4251   'ob::OBDepthWorkModeList::impl_': 'std::unique_ptr<OBDepthWorkModeListImpl,std::default_delete<OBDepthWorkModeListImpl>>' needs to have dll-interface to be used by clients of 'ob::OBDepthWorkModeList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Device.hpp    896     
Warning C4251   'ob::DevicePresetList::impl_': 'std::unique_ptr<DevicePresetListImpl,std::default_delete<DevicePresetListImpl>>' needs to have dll-interface to be used by clients of 'ob::DevicePresetList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Device.hpp    940     
Warning C4251   'ob::Error::impl_': 'std::unique_ptr<ErrorImpl,std::default_delete<ErrorImpl>>' needs to have dll-interface to be used by clients of 'ob::Error'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Error.hpp 16      
Warning C4251   'std::enable_shared_from_this<ob::Frame>::_Wptr': 'std::weak_ptr<_Ty>' needs to have dll-interface to be used by clients of 'std::enable_shared_from_this<ob::Frame>'
        with
        [
            _Ty=ob::Frame
        ]   PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Frame.hpp 42      
Warning C4251   'ob::Frame::impl_': 'std::unique_ptr<FrameImpl,std::default_delete<FrameImpl>>' needs to have dll-interface to be used by clients of 'ob::Frame'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Frame.hpp 44      
Warning C4251   'ob::Pipeline::impl_': 'std::unique_ptr<PipelineImpl,std::default_delete<PipelineImpl>>' needs to have dll-interface to be used by clients of 'ob::Pipeline'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Pipeline.hpp  30      
Warning C4251   'ob::Config::impl_': 'std::unique_ptr<ConfigImpl,std::default_delete<ConfigImpl>>' needs to have dll-interface to be used by clients of 'ob::Config'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Pipeline.hpp  212     
Warning C4251   'ob::Recorder::impl_': 'std::unique_ptr<RecorderImpl,std::default_delete<RecorderImpl>>' needs to have dll-interface to be used by clients of 'ob::Recorder'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\RecordPlayback.hpp    25      
Warning C4251   'ob::Playback::impl_': 'std::unique_ptr<PlaybackImpl,std::default_delete<PlaybackImpl>>' needs to have dll-interface to be used by clients of 'ob::Playback'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\RecordPlayback.hpp    65      
Warning C4251   'ob::Sensor::impl_': 'std::unique_ptr<SensorImpl,std::default_delete<SensorImpl>>' needs to have dll-interface to be used by clients of 'ob::Sensor'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Sensor.hpp    33      
Warning C4251   'ob::SensorList::impl_': 'std::unique_ptr<SensorListImpl,std::default_delete<SensorListImpl>>' needs to have dll-interface to be used by clients of 'ob::SensorList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Sensor.hpp    82      
Warning C4251   'ob::OBFilterList::impl_': 'std::unique_ptr<OBFilterListImpl,std::default_delete<OBFilterListImpl>>' needs to have dll-interface to be used by clients of 'ob::OBFilterList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\Sensor.hpp    127     
Warning C4251   'std::enable_shared_from_this<ob::StreamProfile>::_Wptr': 'std::weak_ptr<_Ty>' needs to have dll-interface to be used by clients of 'std::enable_shared_from_this<ob::StreamProfile>'
        with
        [
            _Ty=ob::StreamProfile
        ]   PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\StreamProfile.hpp 22      
Warning C4251   'ob::StreamProfile::impl_': 'std::unique_ptr<StreamProfileImpl,std::default_delete<StreamProfileImpl>>' needs to have dll-interface to be used by clients of 'ob::StreamProfile'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\StreamProfile.hpp 24      
Warning C4251   'ob::StreamProfileList::impl_': 'std::unique_ptr<StreamProfileListImpl,std::default_delete<StreamProfileListImpl>>' needs to have dll-interface to be used by clients of 'ob::StreamProfileList'    PointCloudTest  C:\OrbbecSDK_v1.10.12\SDK\include\libobsensor\hpp\StreamProfile.hpp 214     
Error   C4996   'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. PointCloudTest  C:\Users\mchang\source\repos\PointCloudTest\PointCloudTest\Source.cpp   15      
Error   C4996   'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. PointCloudTest  C:\Users\mchang\source\repos\PointCloudTest\PointCloudTest\Source.cpp   37      
Error   C3861   'kbhit': identifier not found   PointCloudTest  C:\Users\mchang\source\repos\PointCloudTest\PointCloudTest\Source.cpp   152     
Error   C3861   'getch': identifier not found   PointCloudTest  C:\Users\mchang\source\repos\PointCloudTest\PointCloudTest\Source.cpp   153     

And here's the original code in the sample folder:

#include "libobsensor/ObSensor.hpp"
// #include "opencv2/opencv.hpp"
#include <fstream>
#include <iostream>
// #include "utils.hpp"
#include "libobsensor/hpp/Utils.hpp"

#define KEY_ESC 27
#define KEY_R 82
#define KEY_r 114

// Save point cloud data to ply
void savePointsToPly(std::shared_ptr<ob::Frame> frame, std::string fileName) {
    int   pointsSize = frame->dataSize() / sizeof(OBPoint);
    FILE* fp = fopen(fileName.c_str(), "wb+");
    fprintf(fp, "ply\n");
    fprintf(fp, "format ascii 1.0\n");
    fprintf(fp, "element vertex %d\n", pointsSize);
    fprintf(fp, "property float x\n");
    fprintf(fp, "property float y\n");
    fprintf(fp, "property float z\n");
    fprintf(fp, "end_header\n");

    OBPoint* point = (OBPoint*)frame->data();
    for (int i = 0; i < pointsSize; i++) {
        fprintf(fp, "%.3f %.3f %.3f\n", point->x, point->y, point->z);
        point++;
    }

    fflush(fp);
    fclose(fp);
}

// Save colored point cloud data to ply
void saveRGBPointsToPly(std::shared_ptr<ob::Frame> frame, std::string fileName) {
    int   pointsSize = frame->dataSize() / sizeof(OBColorPoint);
    FILE* fp = fopen(fileName.c_str(), "wb+");
    fprintf(fp, "ply\n");
    fprintf(fp, "format ascii 1.0\n");
    fprintf(fp, "element vertex %d\n", pointsSize);
    fprintf(fp, "property float x\n");
    fprintf(fp, "property float y\n");
    fprintf(fp, "property float z\n");
    fprintf(fp, "property uchar red\n");
    fprintf(fp, "property uchar green\n");
    fprintf(fp, "property uchar blue\n");
    fprintf(fp, "end_header\n");

    OBColorPoint* point = (OBColorPoint*)frame->data();
    for (int i = 0; i < pointsSize; i++) {
        fprintf(fp, "%.3f %.3f %.3f %d %d %d\n", point->x, point->y, point->z, (int)point->r, (int)point->g, (int)point->b);
        point++;
    }

    fflush(fp);
    fclose(fp);
}

int main(int argc, char** argv) try {
    ob::Context::setLoggerSeverity(OB_LOG_SEVERITY_WARN);
    // create pipeline
    ob::Pipeline pipeline;

    // Configure which streams to enable or disable for the Pipeline by creating a Config
    std::shared_ptr<ob::Config> config = std::make_shared<ob::Config>();

    // Turn on D2C alignment, which needs to be turned on when generating RGBD point clouds

    std::shared_ptr<ob::VideoStreamProfile> colorProfile = nullptr;
    try {
        // Get all stream profiles of the color camera, including stream resolution, frame rate, and frame format
        auto colorProfiles = pipeline.getStreamProfileList(OB_SENSOR_COLOR);
        if (colorProfiles) {
            auto profile = colorProfiles->getProfile(OB_PROFILE_DEFAULT);
            colorProfile = profile->as<ob::VideoStreamProfile>();
        }
        config->enableStream(colorProfile);
    }
    catch (ob::Error& e) {
        config->setAlignMode(ALIGN_DISABLE);
        std::cerr << "Current device is not support color sensor!" << std::endl;
    }

    // Get all stream profiles of the depth camera, including stream resolution, frame rate, and frame format
    std::shared_ptr<ob::StreamProfileList> depthProfileList;
    OBAlignMode                            alignMode = ALIGN_DISABLE;
    if (colorProfile) {
        // Try find supported depth to color align hardware mode profile
        depthProfileList = pipeline.getD2CDepthProfileList(colorProfile, ALIGN_D2C_HW_MODE);
        if (depthProfileList->count() > 0) {
            alignMode = ALIGN_D2C_HW_MODE;
        }
        else {
            // Try find supported depth to color align software mode profile
            depthProfileList = pipeline.getD2CDepthProfileList(colorProfile, ALIGN_D2C_SW_MODE);
            if (depthProfileList->count() > 0) {
                alignMode = ALIGN_D2C_SW_MODE;
            }
        }

        try {
            // Enable frame synchronization
            pipeline.enableFrameSync();
        }
        catch (ob::Error& e) {
            std::cerr << "Current device is not support frame sync!" << std::endl;
        }
    }
    else {
        depthProfileList = pipeline.getStreamProfileList(OB_SENSOR_DEPTH);
    }

    if (depthProfileList->count() > 0) {
        std::shared_ptr<ob::StreamProfile> depthProfile;
        try {
            // Select the profile with the same frame rate as color.
            if (colorProfile) {
                depthProfile = depthProfileList->getVideoStreamProfile(OB_WIDTH_ANY, OB_HEIGHT_ANY, OB_FORMAT_ANY, colorProfile->fps());
            }
        }
        catch (...) {
            depthProfile = nullptr;
        }

        if (!depthProfile) {
            // If no matching profile is found, select the default profile.
            depthProfile = depthProfileList->getProfile(OB_PROFILE_DEFAULT);
        }
        config->enableStream(depthProfile);
    }
    config->setAlignMode(alignMode);

    // start pipeline with config
    pipeline.start(config);

    // Create a point cloud Filter object (the device parameters will be obtained inside the Pipeline when the point cloud filter is created, so try to
    // configure the device before creating the filter)
    ob::PointCloudFilter pointCloud;

    // get camera intrinsic and extrinsic parameters form pipeline and set to point cloud filter
    auto cameraParam = pipeline.getCameraParam();
    pointCloud.setCameraParam(cameraParam);

    // operation prompt
    std::cout << "Press R or r to create RGBD PointCloud and save to ply file! " << std::endl;
    std::cout << "Press D or d to create Depth PointCloud and save to ply file! " << std::endl;
    std::cout << "Press ESC to exit! " << std::endl;

    int count = 0;
    while (true) {
        auto frameset = pipeline.waitForFrames(100);
        if (kbhit()) {
            int key = getch();
            // Press the ESC key to exit
            if (key == KEY_ESC) {
                break;
            }
            if (key == 'R' || key == 'r') {
                count = 0;
                // Limit up to 10 repetitions
                while (count++ < 10) {
                    // Wait for a frame of data, the timeout is 100ms
                    auto frameset = pipeline.waitForFrames(100);
                    if (frameset != nullptr && frameset->depthFrame() != nullptr && frameset->colorFrame() != nullptr) {
                        // point position value multiply depth value scale to convert uint to millimeter (for some devices, the default depth value uint is not
                        // millimeter)
                        auto depthValueScale = frameset->depthFrame()->getValueScale();
                        pointCloud.setPositionDataScaled(depthValueScale);
                        try {
                            // Generate a colored point cloud and save it
                            std::cout << "Save RGBD PointCloud ply file..." << std::endl;
                            pointCloud.setCreatePointFormat(OB_FORMAT_RGB_POINT);
                            std::shared_ptr<ob::Frame> frame = pointCloud.process(frameset);
                            saveRGBPointsToPly(frame, "RGBPoints.ply");
                            std::cout << "RGBPoints.ply Saved" << std::endl;
                        }
                        catch (std::exception& e) {
                            std::cout << "Get point cloud failed" << std::endl;
                        }
                        break;
                    }
                    else {
                        std::cout << "Get color frame or depth frame failed!" << std::endl;
                    }
                }
            }
            else if (key == 'D' || key == 'd') {
                count = 0;
                // Limit up to 10 repetitions
                while (count++ < 10) {
                    // Wait for up to 100ms for a frameset in blocking mode.
                    auto frameset = pipeline.waitForFrames(100);
                    if (frameset != nullptr && frameset->depthFrame() != nullptr) {
                        // point position value multiply depth value scale to convert uint to millimeter (for some devices, the default depth value uint is not
                        // millimeter)
                        auto depthValueScale = frameset->depthFrame()->getValueScale();
                        pointCloud.setPositionDataScaled(depthValueScale);
                        try {
                            // generate point cloud and save
                            std::cout << "Save Depth PointCloud to ply file..." << std::endl;
                            pointCloud.setCreatePointFormat(OB_FORMAT_POINT);
                            std::shared_ptr<ob::Frame> frame = pointCloud.process(frameset);
                            savePointsToPly(frame, "DepthPoints.ply");
                            std::cout << "DepthPoints.ply Saved" << std::endl;
                        }
                        catch (std::exception& e) {
                            std::cout << "Get point cloud failed" << std::endl;
                        }
                        break;
                    }
                }
            }
        }
    }
    // stop the pipeline
    pipeline.stop();

    return 0;
}
catch (ob::Error& e) {
    std::cerr << "function:" << e.getName() << "\nargs:" << e.getArgs() << "\nmessage:" << e.getMessage() << "\ntype:" << e.getExceptionType() << std::endl;
    exit(EXIT_FAILURE);
}

Could anyone help me with this? Thank you very much!

zhonghong322 commented 2 weeks ago

You can refer to this document to compile the sample. https://github.com/orbbec/OrbbecSDK/blob/main/doc/tutorial/English/Environment_Configuration.md

triplecmike commented 2 weeks ago

Thank you so much. this is very helpful.