Kinect SDK:对齐深度和颜色帧
Kinect SDK: align depth and color frames
我正在使用Kinect传感器,我正在尝试对齐深度和颜色帧,以便我可以将它们保存为"适合"彼此的图像。我花了很多时间浏览msdn论坛和Kinect SDK的少量文档,但我一无所获。
基于这个答案:Kinect:从RGB坐标转换到深度坐标
我有以下函数,其中depthData
和colorData
是由NUI_LOCKED_RECT.pBits
获得的,mappedData
是包含新颜色帧的输出,映射到深度坐标:
bool mapColorFrameToDepthFrame(unsigned char *depthData, unsigned char* colorData, unsigned char* mappedData)
{
INuiCoordinateMapper* coordMapper;
// Get coordinate mapper
m_pSensor->NuiGetCoordinateMapper(&coordMapper);
NUI_DEPTH_IMAGE_POINT* depthPoints = new NUI_DEPTH_IMAGE_POINT[640 * 480];
HRESULT result = coordMapper->MapColorFrameToDepthFrame(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, 640 * 480, reinterpret_cast<NUI_DEPTH_IMAGE_PIXEL*>(depthData), 640 * 480, depthPoints);
if (FAILED(result))
{
return false;
}
int pos = 0;
int* colorRun = reinterpret_cast<int*>(colorData);
int* mappedRun = reinterpret_cast<int*>(mappedData);
// For each pixel of new color frame
for (int i = 0; i < 640 * 480; ++i)
{
// Find the corresponding pixel in original color frame from depthPoints
pos = (depthPoints[i].y * 640) + depthPoints[i].x;
// Set pixel value if it's within frame boundaries
if (pos < 640 * 480)
{
mappedRun[i] = colorRun[pos];
}
}
return true;
}
当运行这段代码时,我得到的是一个未改变的颜色帧,删除了(白色)所有像素,其中depthFrame没有信息
OpenNI框架有一个调用注册的选项。
IMAGE_REGISTRATION_DEPTH_TO_IMAGE -深度图像被转换为具有与RGB图像相同的明显有利位置。
OpenNI 2.0和Nite 2.0可以很好地捕获Kinect信息,并且有很多教程。
你可以看看这个:
Kinect with OpenNI
OpenNi在SimplerViewer中有一个合并深度和颜色的例子,也许你可以看看并尝试一下
这可能不是你所希望的快速答案,但是这个转换在openFrameworks的ofxKinectNui
插件中成功完成了(见这里)。
看起来ofxKinectNui
委托给这里定义的GetColorPixelCoordinatesFromDepthPixel
函数
我认为问题是你调用MapColorFrameToDepthFrame,当你实际上应该调用MapDepthFrameToColorFrame。
确凿的证据是这行代码:
mappedRun[i] = colorRun[pos];
从pos
读取并写入i
是反向的,因为pos = depthPoints[i]
表示与i
的颜色坐标对应的深度坐标。实际上,您需要遍历写入所有depth坐标,并在相应的color坐标处从输入颜色图像中读取。
我认为在你的代码中有不同的不正确的行。
首先,你传递给函数的是哪种深度图?
深度数据为每个值使用两个字节存储,这意味着您应该为深度数据使用正确类型的指针是 unsigned short。
第二点是,从我所理解的,你想映射深度帧到颜色帧,所以你有正确的功能从kinect sdk调用的是 MapDepthFrameToColorFrame 而不是MapColorFrameToDepthFrame
最后,该函数将返回一个点的映射,其中对于位置[i]的每个深度数据,您有该点的位置x和位置y映射。
为此,不需要colorData指针。
所以你的函数应该修改如下:
/** Method used to build a depth map aligned to color frame
@param [in] depthData : pointer to your data;
@param [out] mappedData : pointer to your aligned depth map;
@return true if is all ok : false whene something wrong
*/
bool DeviceManager::mapColorFrameToDepthFrame(unsigned short *depthData, unsigned short* mappedData){
INuiCoordinateMapper* coordMapper;
NUI_COLOR_IMAGE_POINT* colorPoints = new NUI_COLOR_IMAGE_POINT[640 * 480]; //color points
NUI_DEPTH_IMAGE_PIXEL* depthPoints = new NUI_DEPTH_IMAGE_PIXEL[640 * 480]; // depth pixel
/** BE sURE THAT YOU ARE WORKING WITH THE RIGHT HEIGHT AND WIDTH*/
unsigned long refWidth = 0;
unsigned long refHeight = 0;
NuiImageResolutionToSize( NUI_IMAGE_RESOLUTION_640x480, refWidth, refHeight );
int width = static_cast<int>( refWidth ); //get the image width in a right way
int height = static_cast<int>( refHeight ); //get the image height in a right way
m_pSensor>NuiGetCoordinateMapper(&coordMapper); // get the coord mapper
//Map your frame;
HRESULT result = coordMapper->MapDepthFrameToColorFrame( NUI_IMAGE_RESOLUTION_640x480, width * height, depthPoints, NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, width * height, colorPoints );
if (FAILED(result))
return false;
// apply map in terms of x and y (image coordinates);
for (int i = 0; i < width * height; i++)
if (colorPoints[i].x >0 && colorPoints[i].x < width && colorPoints[i].y>0 && colorPoints[i].y < height)
*(mappedData + colorPoints[i].x + colorPoints[i].y*width) = *(depthData + i );
// free your memory!!!
delete colorPoints;
delete depthPoints;
return true;
}
请确保您的mappedData已以正确的方式初始化,例如如下所示:
mappedData = (USHORT*)calloc(width*height, sizeof(ushort));
请记住,kinect sdk不提供颜色和深度数据之间的精确对齐功能。
如果您想要两个图像之间的精确对齐,您应该使用校准模型。在这种情况下,我建议您使用Kinect校准工具箱,基于Heikkilä校准模型。
你可以在以下链接中找到它:
http://www.ee.oulu.fi/dherrera/kinect。
首先,你必须校准你的设备。这意味着,你应该校准RGB和IR传感器,然后找到RGB和IR之间的转换。一旦你知道了这些信息,你就可以应用这个函数:
RGBPoint = RotationMatrix * DepthPoint + TranslationVector
查看OpenCV或ROS项目了解更多详细信息。
外部校准
内在校准
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 如何在内核C++中使用1920x1080x16M图形或类似的16M颜色?(VGA)
- 如何在24位SDL_Surface上设置像素的颜色
- OpenGL在启用深度测试时不会丢弃我的碎片
- 如何从SDL_Surface获取特定像素的颜色
- C++尝试深度复制唯一指针时出现内存访问冲突
- 如何使用OpenCV同时显示"深度"和"颜色"视频图像
- 从OpenGL应用程序中提取颜色/深度缓冲区
- 在 UWP 中使用C++录制 Kinect V2.0(颜色和深度)
- 在 OpenGL 中将深度映射到颜色
- libpng获取原始颜色通道深度
- SDL2 OpenGL 4.2上下文,具有0个颜色位和0个深度位
- 深度+颜色的3D投影
- 在OpenGL中启用深度测试后,我的整个屏幕是空白的(恢复为清晰的颜色)-为什么
- Kinect SDK:对齐深度和颜色帧
- RealSense R200在高颜色分辨率和低深度分辨率时崩溃
- 为什么在CToolBar中使用高深度颜色的禁用按钮只是灰色框
- 如何在多样本纹理中渲染颜色和深度
- MFC工具栏图标的颜色深度更高