我有一个C++项目,我正在使用OpenCV和Libfreenect。我不想包含像OpenNI那样大而沉重的东西,并在此过程中创建OpenCV安装依赖关系。我想使用提供的校准信息here来保持不偏振,并对齐RGB和深度图像。如何在OpenCV中对齐Kinect的RGB和深度图像?
基于相机矩阵和失真系数单独对图像进行单独失真很简单。但是现在我对如何使用校正和投影矩阵来对齐RGB和深度图像感到困惑,所以它们从相同的角度基本上向我展示了相同的东西。在搜索了很长一段时间之后,我无法确定它应该如何与OpenCV一起工作。这是一个模糊的估计,reprojectImageTo3D()和warpPerspective()可能会被使用,但我不知道如何。
我该如何解决这个问题?我正在使用旧的XBOX360 Kinect(具有0-2047原始视差值范围)。
UPDATE
下面是部分代码,到目前为止,我已经写了:
// I use callback functions to get RGB (CV_8UC3) and depth (CV_16UC1)
// I undistort them and call the following method
void AlignImages(cv::Mat& pRGB, cv::Mat& pDepth) {
rotationMat = (cv::Mat_<double_t>(3,3) << 9.9984628826577793e-01, 1.2635359098409581e-03, -1.7487233004436643e-02, -1.4779096108364480e-03, 9.9992385683542895e-01, -1.2251380107679535e-02, 1.7470421412464927e-02, 1.2275341476520762e-02, 9.9977202419716948e-01);
translationMat = (cv::Mat_<double_t>(3,1) << 1.9985242312092553e-02, -7.4423738761617583e-04, -1.0916736334336222e-02);
// make a copy in float to convert raw depth data to physical distance
cv::Mat tempDst;
pDepth.convertTo(tempDst, CV_32F);
// create a 3 channel image of precision double for the 3D points
cv::Mat tempDst3D = cv::Mat(cv::Size(640, 480), CV_64FC3, double(0));
float_t* tempDstData = (float_t*)tempDst.data;
double_t* tempDst3DData = (double_t*)tempDst3D.data;
size_t pixelSize = tempDst.step/sizeof(float_t);
size_t pixel3DSize = tempDst3D.step/sizeof(double_t);
for (int row=0; row < tempDst.rows; row++) {
for (int col=0; col < tempDst.cols; col++) {
// convert raw depth values to physical distance (in metres)
float_t& pixel = tempDstData[pixelSize * row + col];
pixel = 0.1236 * tanf(pixel/2842.5 + 1.1863);
// reproject physical distance values to 3D space
double_t& pixel3D_X = tempDst3DData[pixel3DSize * row + col];
double_t& pixel3D_Y = tempDst3DData[pixel3DSize * row + col +1];
double_t& pixel3D_Z = tempDst3DData[pixel3DSize * row + col + 2];
pixel3D_X = (row - 3.3930780975300314e+02) * pixel/5.9421434211923247e+02;
pixel3D_Y = (col - 2.4273913761751615e+02) * pixel/5.9104053696870778e+02;
pixel3D_Z = pixel;
}
}
tempDst3D = rotationMat * tempDst3D + translationMat;
}
我已经直接使用,而不是将它们分配给变量的数字,但是这不应该是一个理解逻辑的问题。在这一点上,我应该做到以下几点:
P2D_rgb.x = (P3D'.x * fx_rgb/P3D'.z) + cx_rgb
P2D_rgb.y = (P3D'.y * fy_rgb/P3D'.z) + cy_rgb
但我不明白我是怎么做到的,完全是。也许我完全走错了方向。但我找不到任何这样做的例子。
可以使用openni代替openkinect/libfreenect? –
我想你在访问'tempDst3DData'缓冲区中的数据时遇到了问题。它应该是'tempDst3DData [3 * pixel3DSize * row + 3 * col + channel]'。关于您更新的问题,我会编辑我的答案以尝试更清楚。 – AldurDisciple
另外,我想你在'pixel3D_X'和'pixel3D_Y'表达式中混合了'row'和'col'。 – AldurDisciple