Kinect深度图像

9
在我的应用程序中,我获取到了类似于深度基础示例中检索到的深度帧。但是我不明白为什么图像中会有离散的级别?我不知道如何称呼这些深度值的突然变化。显然我的右手一半是全黑的,而我的左手似乎分成了3个这样的级别。这是什么,我该如何去除它?

Kinect Depth Basics Sample

当我运行KinectExplorer示例应用程序时,我会得到以下深度图像。这是我想从原始深度数据生成的深度图像。

Kinect Explorer

我正在使用微软Kinect SDK(v1.6)的NuiApi和OpenCV。我有以下代码:
BYTE *pBuffer = (BYTE*)depthLockedRect.pBits; //pointer to data having 8-bit jump
USHORT *depthBuffer = (USHORT*) pBuffer; //pointer to data having 16-bit jump
int cn = 4;
this->depthFinal = cv::Mat::zeros(depthHeight,depthWidth,CV_8UC4); //8bit 4 channel
for(int i=0;i<this->depthFinal.rows;i++){
   for(int j=0;j<this->depthFinal.cols;j++){
      USHORT realdepth = ((*depthBuffer)&0x0fff); //Taking 12LSBs for depth
      BYTE intensity = (BYTE)((255*realdepth)/0x0fff); //Scaling to 255 scale grayscale
      this->depthFinal.data[i*this->depthFinal.cols*cn + j*cn + 0] = intensity;
      this->depthFinal.data[i*this->depthFinal.cols*cn + j*cn + 1] = intensity;
      this->depthFinal.data[i*this->depthFinal.cols*cn + j*cn + 2] = intensity;
      depthBuffer++;
   }
}

请仔细检查您的图片,它们没有显示出来。 - Nicholas Pappas
更改了图像的URL。请再次检查。 - thinkquester
“cn”是什么,为什么必须是“4”而不是“3”?另外,看到你实际输出图像的位置也很好。 - Tim
cn是通道数,为了我的目的它必须是4个通道的BGRA。 - thinkquester
@thinkquester,你应该看看我的答案——它提供了解决你问题的方案。 - memyself
4个回答

7

您看到的条纹是由于深度值的wrapping(即%256操作)造成的。不要使用模运算符(%256),因为这会导致出现条纹,而是将深度值重新映射到整个范围内,例如:

BYTE intensity = depth == 0 || depth > 4095 ? 0 : 255 - (BYTE)(((float)depth / 4095.0f) * 255.0f);

如果你的最大深度为2048,则用2047替换4095。

更多指针:

  1. Kinect可能返回11位值(0-2047),但您仅使用8位(0-255)。
  2. 新的Kinect版本似乎返回12位值(0-4096)
  3. 在Kinect Explorer源代码中,有一个名为DepthColorizer.cs的文件,其中大部分魔力似乎发生了。 我相信这段代码使kinect explorer中的深度值如此平滑 - 但我可能是错的。

如果您使用较小的值作为模数来包装深度值,那么带状区域是否会更加分散? - Ren P

1
在我处理一个涉及深度图可视化的项目时,我遇到了同样的问题。然而,我使用了OpenNI SDK和OpenCV,而不是Kinect SDK库。问题是一样的,因此解决方案对您也会像对我一样有效。
如前面回答您问题的答案所述,Kinect深度图是11位(0-2047)。而在示例中,使用的是8位数据类型。
我在我的代码中所做的是将深度图获取到一个16位Mat中,然后通过使用convertTo函数的缩放选项将其转换为8位uchar Mat。
首先,我初始化了一个Mat来获取深度数据。
Mat depthMat16UC1(XN_VGA_Y_RES, XN_VGA_X_RES, CV_16UC1);

这里的XN_VGA_Y_RES,XN_VGA_X_RES定义了获取深度图的分辨率。

我编写此代码的位置如下:

depthMat16UC1.data = ((uchar*)depthMD.Data());
depthMat16UC1.convertTo(depthMat8UC1, CV_8U, 0.05f); 
imshow("Depth Image", depthMat8UC1);

depthMD 是包含从Kinect传感器检索到的数据的元数据。

希望这能在某种程度上对您有所帮助。


0
Kinect v2 可以看到 8 米深度,但超过 4.5 米的精度会降低。 它从大约 0.4 米开始。 因此,需要将数字 8000 表示为一种颜色。 一种方法是使用 RGB 颜色作为数字。 然后,您可以在像素中存储类似于 255x255x255 的数字。 如果您有不同的颜色格式,则会有所不同。 将 8000 存储在最大的 255x255x255 数字中将导致一定量的 R+G+B,从而产生这种带状效果。
但是,您当然可以将 8000 分成几部分或减去一个数字,或者删除超出某个值的部分。

0

深度图像数据的可视化具有离散级别,这些级别是粗略的(例如您代码示例中的0到255),但实际的深度图像数据是介于0和2047之间的数字。当然仍然是离散的,但不像所选颜色那样粗糙地描绘它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接