OpenCV 拼接 RGB 和深度(英特尔实感)

Posted

技术标签:

【中文标题】OpenCV 拼接 RGB 和深度(英特尔实感)【英文标题】:OpenCV Stitching RGB and Depth (Intel RealSense) 【发布时间】:2020-05-25 04:00:14 【问题描述】:

我有一个同时使用 realsense2 和 opencv2 库的 C++ 应用程序。我正在从两个 D415 相机中提取深度和 RGB 帧。我可以毫无问题地拼接 RGB 帧;但是,经过大量研究,我找不到任何有关如何将步骤从 RGB 帧缝合复制到深度帧的示例。有谁知道如何将拼接步骤从一个拼接作业(在我的情况下为 RGB)复制到另一个拼接作业(在我的情况下为深度)?

我在这里查看了 Stitcher 类参考文档:https://docs.opencv.org/master/d2/d8d/classcv_1_1Stitcher.html

如果有人以前这样做过并且可以提供一些指导,那就太好了。

这是我用来缝合(缩短)的工作代码:

// Start a streaming pipeline for each connected camera

for (auto && device : context.query_devices())



    string serial = device.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);

    pipeline pipeline(context);

    config config;

    config.enable_device(serial);

    config.enable_stream(RS2_STREAM_COLOR, 1280, 720, RS2_FORMAT_BGR8, 15);

    config.enable_stream(RS2_STREAM_DEPTH, 1280, 720);

    config.enable_stream(RS2_STREAM_INFRARED, 1);

    pipeline.start(config);

    pipelines.emplace_back(pipeline);

    colorizers[serial] = colorizer();





map<int, frame> render_frames;



while(true)



    vector<Mat> mats;

    vector<frame> new_frames;

    for (auto && pipeline : pipelines)

    

        frameset frameset = pipeline.wait_for_frames();

        if (frameset)

        

            mats.push_back(frame_to_mat(frameset.get_color_frame()));

        

    

    Mat stitchedImage;

    Ptr<Stitcher> stitcher = Stitcher::create(Stitcher::PANORAMA);

    Stitcher::Status stitcherStatus = stitcher->stitch(mats, stitchedImage);

    if (stitcherStatus == Stitcher::OK)

    

        imshow("Stitched Image", stitchedImage);
        auto k = waitKey(200);

     else 

        cout << "Error stitching image.\n";

    


谢谢!

【问题讨论】:

你想达到什么目的?我认为拼接深度图像没有多大意义,因为深度值是相对于相机位置的。例如。如果你向前移动canera,同一个物体的点会得到两个非常不同的深度值。也许你想要像 SLAM 这样的东西?看看“kinect fusion”方法。 @Micka - 感谢您的快速回复!这里的目标是我有两个英特尔实感摄像头 (D415),在这 ~70 度上的视角非常差。如果我将其中两个结合起来,我可以达到约 110 度(再多一点,OpenCV 不喜欢拼接图像)。我正在尝试拼接同时从相机拍摄的 RGB 图像,使用 haar 级联检测人脸,然后使用深度帧/图像检查检测到的人脸是否具有深度。最终目标将是不识别 2d 人脸图片的人脸检测(想想客厅墙上的照片,或显示在屏幕上的照片等) 啊好吧,这更有意义。不幸的是,我不知道您是否可以直接从 opencv 的拼接器类中提取匹配的关键点。在最坏的情况下,您可以更改 opencv 的代码(它是开源的)。 两个深度摄像头是否静态安装,所以从第一个到第二个摄像头的位置保持不变? @TeddybearCrisis - 是的,它们是静态安装的;但是,环境会发生变化。 IE。静态安装在带有树莓派的盒子中;但是,盒子会从一个地方移动到另一个地方。 【参考方案1】:

如果您忽略失真,那么拼接只是计算从一个图像原点到另一个图像原点的变换。从技术上讲,您已经拥有所需的一切。这是一种非常天真的方法。

在每个单独的相机内(在硬件规范中提供)有:

depth_origin -> rgb_origin
("->" represents a transform)

OpenCV 拼接器可以在两个 rgb 图像之间estimate a transform,这样你就有了

cam1_rgb_origin -> cam2_rgb_origin

所以你可以计算:

cam1_depth -> cam1_rgb -> cam2_rgb -> cam2_depth   

您的方法有点不寻常,但它可能足够有效,因为相机规格在 realsense 文档中提供,我认为每个传感器都很好地对齐。

虽然有点警告:

通常,两个摄像头永远不会完全对齐。因此,对于更精细的解决方案,我会避免使用通过图像拼接计算的变换。我宁愿校准静态安装上的相机以获得外部相机参数。这只是从相机坐标原点 1 到相机坐标原点 2 的 3D 变换。使用此变换,您将在包含两个相机点的统一坐标系中创建传感器数据的 3D 点云。最后,您可以从您选择的任何角度将此点云渲染为深度图像,并将 rgb 图像投影到其上,以使其可用于您想要使用的人脸检测。相机校准可能是一件非常痛苦的事情,尤其是当相机的视角没有太多相交时。因此,如果您的结果还不够,请仅采用这种精心设计的方法。

抱歉,由于时间原因,我无法详细说明。但我希望这能为您指明正确的方向。

【讨论】:

这正是我认为您在提出问题时所暗示的内容。在您询问它们是否静态安装并认为这可能是正确的方法后,我已经考虑过了。我没有考虑点云,这是一个很好的建议。我会用代码更新线程;但是,这是一个私人项目,所以我只想说这个建议对我有用,我有一个使用你概述的方法的工作原型。再次感谢!干杯! Goog 的问题是,realsense 摄像头已经提供了校正/未失真的图像。这使得“天真”的方法非常直接恕我直言。除非凸轮的视角转移太多,否则我会尝试一下。这与我通常做的事情有关(icy3d.com/demo)。祝项目顺利。【参考方案2】:

英特尔 SDK 提供单个摄像头的深度和 RGB 之间的旋转和平移矩阵。使用该矩阵,您可以对齐深度和 rgb 数据。

对于多摄像头,校准多个摄像头并不像我们想象的那么容易。英特尔建议使用“vicalib”软件,您可以尝试一次。

【讨论】:

以上是关于OpenCV 拼接 RGB 和深度(英特尔实感)的主要内容,如果未能解决你的问题,请参考以下文章

在 Unity 中获取英特尔实感深度流

使用 OpenCV 将感兴趣区域从 RGB 视频转换为深度视频

英特尔实感深度摄像头 D435i 噪音和土堆

英特尔实感 C# 将流录制到文件

如何使用 OpenCV-Python 从英特尔实感 D415 获取 IR1 和 IR2 摄像头图像?

使用 SharpSenses 和 RealSense 3d 相机时出现 NullReferenceException