【问题标题】:Convertion Between cv::Mat and XnDepthPixel*cv::Mat 和深度像素之间的转换*
【发布时间】:2013-05-04 22:47:45
【问题描述】:

我正在使用 OpenNI 1.5.4.0 和 OpenCV 2.4.5,以及用于可视化目的的 Qt(仅限 RGB 图像)。 基本上,我从 Kinect 中检索深度和 rgb 帧并将它们存储在硬盘上,使用转换:

/* Depth conversion */

cv::Mat depth = cv::Mat(2, sizes, CV_16UC1, (void*) pDepthMap); //XnDepthPixel *pDepthMap 

/* RGB conversion */

///image is a QImage* , pImageMap is a XnUInt8*

for(int i = 0; i < height; ++i)
{
    for (unsigned y = 0; y < height; ++y)
    {
       uchar *imagePtr = (*image).scanLine(y);
       for (unsigned x=0; x < width; ++x)
       {
          imagePtr[0] = pImageMap[2];
          imagePtr[1] = pImageMap[1];
          imagePtr[2] = pImageMap[0];
          imagePtr[3] = 0xff;
          imagePtr+=4;
          pImageMap+=3;
       }
    }
}

现在,我想从硬盘加载这些图像,以便将 3D 点云计算为后处理计算。 我将深度图加载为:

depth_image = cv::imread(m_rgb_files.at(w).toStdString(), CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );

但应用公式:

depth = depth_image.at<int>(j,i);  //depth_image is stored as 16bit
p.z = (float)depth * 0.001f;    //converting from millimeters to meters
p.x = (float)(i - m_params.center_x) * depth * m_params.focal_length; //focal_length read using OpenNI function
p.y = (float)(j - m_params.center_y) * depth * m_params.focal_length;

得到的点云一团糟。

如果我直接使用本机 XnDepthPixel* 数据进行“在线”处理,结果是完美的,使用之前编写的公式。 谁能给我一个关于我的错的“提示”?

提前致谢

编辑:我也在关注这个resource,但它对我不起作用,因为 XnDepthPixel 包含以毫米为单位的真实世界数据

【问题讨论】:

  • 好吧对不起..我还是这个平台的新手

标签: c++ qt opencv image-processing openni


【解决方案1】:

我认为这里可能存在问题:

depth = depth_image.at<int>(j,i);  //depth_image is stored as 16bit

如果深度图像真的 16位的,它真的应该是:

depth = depth_image.at<short>(j,i);  //depth_image is stored as 16bit

因为int 是 32 位,而不是 16 位。

【讨论】:

  • 深度图实际上是10位+1位用于有效性检查,但它存储在一个16位的无符号整数结构中(称为XnDepthMap,是uint16_t的重命名)。我将尝试按照建议使用 。我对 uint16_t* 和 unsigned char* (不幸的是,它是 cv::Mat 的默认构造函数)之间的转换(保存步骤)有疑问,这可能会影响结果。感谢您的建议
  • depth = depth_image.at(j,i);成功了。非常感谢
【解决方案2】:

另外,如果您构建了支持 OpenNI 的 OpenCV,您可以将深度图像检索为 cv::Mat,您可以使用 cv::imwrite 轻松保存它 这是一个最小的例子:

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>

using namespace cv;
using namespace std;

int main(){
    VideoCapture capture;
    capture.open(CV_CAP_OPENNI);

    if( !capture.isOpened() ){
        cout << "Can not open a capture object." << endl;
        return -1;
    }
    cout << "ready" << endl;

    for(;;){
        Mat depthMap,depthShow;
        if( !capture.grab() ){
            cout << "Can not grab images." << endl;
            return -1;
        }else{
            if( capture.retrieve( depthMap, CV_CAP_OPENNI_DEPTH_MAP ) ){
                const float scaleFactor = 0.05f;
                depthMap.convertTo( depthShow, CV_8UC1, scaleFactor );
                imshow("depth",depthShow);
                if( waitKey( 30 ) == 115)    {//s to save
                    imwrite("your_depth_naming_convention_here.png",depthShow);
                }
            }
        }
        if( waitKey( 30 ) == 27 )    break;//esc to exit
    }

}

【讨论】:

  • 我没有直接使用 OpenCV 来检索深度图,因为我使用了多个 Kinect,并且它没有枚举其他设备,这就是我切换到 OpenNI 纯 API 的原因。无论如何,谢谢你的建议
  • OpenCV可以使用多个kinect,我之前试过this
  • 感谢您的提示,但到目前为止我已经尝试过了,但对我没有用。枚举设备失败(我有 rev. 1473,PointCloudLibrary 都无法检测到多个 kinect)。
  • 真可惜 :( 我怎样才能检查我有什么版本?我记得在 2 月的某个时候使用主下载链接中提供的存档从源代码构建 OpenCV 2.4.4。
  • 你应该在 Kinect 下检查或使用 lsusb -vv(超详细)
猜你喜欢
  • 2015-01-14
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 2016-08-16
  • 2020-02-09
  • 1970-01-01
相关资源
最近更新 更多