繁体   English   中英

"16 位深度图像损坏"

[英]16-bit depth image getting corrupted

我正在使用 realsense D435 并获取 16 位深度数据并转换为 opencv 16 位 Mat 并且我正在使用 c++ 编写自定义队列,我正在推送所有帧并且当我从队列中弹出 16 位数据时已损坏。将帧推入队列时,我将其保存到磁盘中,而同时从队列中弹出帧时,我还将帧保存到磁盘中。因此,从那里我知道帧在弹出时已损坏。 我用 8 位数据尝试过的同样事情意味着在转换为 opencv mat 时我转换为 8 位 Mat 而不是 16 位 Mat 并且在弹出 8 位数据时。数据不会损坏。

代码:

rs2::frameset data = pipe.wait_for_frames(); 
data = align.process(data);         
rs2::frame depth = data.get_depth_frame();
rs2::frame color = data.get_color_frame();

cv::Mat depth_image;        
cv::Mat fin_depth_image(cv::Size(WIDTH,HEIGHT), CV_16UC1, (void*)depth.get_data(), cv::Mat::AUTO_STEP);
cv::Mat color_image(cv::Size(WIDTH,HEIGHT), CV_8UC3, (void*)color.get_data(), cv::Mat::AUTO_STEP);
fin_depth_image.convertTo(depth_image,CV_8UC1);

cv::split(color_image,channels);        
channels.push_back(depth_image);
cv::merge(channels,fin_rgbd_img);           

camera_queue.push(std::make_pair(fin_rgbd_img,fin_depth_image));

自定义队列代码:

inline void push(const T& elem) {
    {
        std::unique_lock<std::mutex> lock(_mutex);

        // wait for timeout while the queue is full
        _not_full.wait_for(lock,std::chrono::milliseconds(5));

        // If the queue is full, remove the old item and add the new item
        if (_queue.size() >= _capacity)
        {
            _queue.pop();
        }
        _queue.push(elem);
    }
    _not_empty.notify_all();
}

inline bool pop(T &elem) {
    bool status = false;
    {
        std::unique_lock<std::mutex> lock(_mutex);

        // wait for timeout while the queue is empty
        _not_empty.wait_for(lock,std::chrono::milliseconds(5));

        if (_queue.size() > 0)
        {
            elem = _queue.front();
            _queue.pop();
            status = true;
        }
    }
    _not_full.notify_one();
    return status;
}

所以从上面你可以看到我正在将 fin_rgbd_img,fin_depth_image 推入队列。 fin_rgbd_img 是 8 位 4 通道 Mat 而 fin_depth_image 是 16 位 Mat。 所以在推动的同时,我还通过 imwrite 函数保存了这个 16 位深度的 Mat,那时我有正确的图像。 在弹出这个 16 位 Mat 时,它被损坏了。

下面是推入队列时的 png 图像,我正在保存到磁盘,它是正确的,同时弹出填充 0 的完整黑色图像即将到来在此处输入图像描述

请记住, rs2::frame<\/code>和cv::Mat<\/code>基本上都是管理实际数据的智能指针的薄包装器。 当您使用

构造函数(或任何其他带有指向数据的指针的 cv::Mat ctor)您告诉 OpenCV 您将管理数据,因此它不进行分配。 一旦 rs2::frame depth<\/code>的最后一个副本超出范围,RealSense 库就会释放数据块,而您无法控制它会发生什么。

您可以尝试保留 RealSense rs2::frame<\/code>帧的副本,直到您完成处理,这会阻止 Realsense 库释放数据并且在内存和处理时间方面相对便宜。 您可以做的另一件事(以更多处理时间为代价)是使用cv::Mat::clone()<\/code>并让 OpenCV 管理自己的数据副本,如下所示:

最后一点:您可能不应该直接使用rs2::frame<\/code>类,因为它是 RealSense 帧的基类。 而是将rs2::depth_frame<\/code>用于深度图像,将rs2::video_frame<\/code>用于彩色或灰度图像。 原因是使用基类使得无法使用rs2::video_frame::get_height()<\/code>和rs2::video_frame::get_width()<\/code>之类的功能。 继承是这样的:

class frame ...
class video_frame : public frame ...
class depth_frame : public video_frame ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM