![](/img/trans.png)
[英]BitBlt + UpdateLayeredWindow and CreateDIBSection in 16-bit desktop color depth
[英]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 时,它被损坏了。
请记住,
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.