cv::Mat和XnDepthPixel之间的转换*

Convertion Between cv::Mat and XnDepthPixel*

本文关键字:转换 之间 XnDepthPixel Mat cv      更新时间:2023-10-16

我正在使用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*数据,结果是完美的,使用之前编写的公式。谁能给我一个"提示"我的错误?

thanks in advance

编辑:我也遵循这个资源,但它不适合我,因为XnDepthPixel包含真实世界的数据在毫米

我觉得这里可能有问题:

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位。

只是作为一个补充,如果你已经用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
    }
}