我正在开发Kinect Point Cloud Application vi kinect SDK 1.5。到目前为止,我能够将kinect深度设置为真实世界坐标并获得点云。为了达到这个目的,我使用Matthew Fisher的代码将kinect深度传感器相机校准到2d rgb帧,该代码在以下链接中共享(http:/ /graphics.stanford.edu/~mdfisher/Kinect.html)。我在C#上修改了kinect sdk的代码。 (深度以毫米为单位):
Hashtable preparePointCloud(short[] rawDepthData)
{//simple holds the 3d point of 2d rgb pixels Y*640+X coordinates
//for instance: 3D point location of x:100 y:50 (in 2d coordinates) is restored in key: 640*50 + 100 in hashtable
Hashtable VectorList = new Hashtable();
int x = 0;
int y = 0;
//rawdepthData holds y*640+x coordinates depth in mm that comes from depth frame. So by only looking the the key of hashtable color of the 3D point easly can be found.
for (int i = 0; i < rawDepthData.Length; i++)
{
int z = rawDepthData[i];
//int z = rawDepthData[y*640+x];
if (z > 1)//don't add the unknown values "-1"
{
Vector3 temp = DepthToWorld(x_, y_, z);
Vector2 color = WorldToColor(ref temp);
int colorindex = (int)((color.Y) * 640 + (color.X));
if (VectorList[colorindex] == null)
{
VectorList.Add(colorindex, temp);
}
}
x++;
if (x == 640)
{
x = 0;
y++;
if (y == 480)
break;
}
}
return VectorList;
}
Vector3 DepthToWorld(int x, int y, int depthValue)
{
Vector3 result;
double depth = (double)(depthValue)/1000; //mm to meter
result.X = (float)((x - cx_d) * depth * fx_d);
result.Y = (float)((y - cy_d) * depth * fy_d);
result.Z = (float)depth;
return result;
}
Vector2 WorldToColor(ref Vector3 pt)
{
OpenTK.Vector4 transformedPos_ = OpenTK.Vector4.Transform(new OpenTK.Vector4(pt,1.0f), depthCalibrationTransformationMatrix);
Vector3 transformedPos = transformedPos_.Xyz;
float invZ = 1.0f / transformedPos.Z;
Vector2 result = new Vector2();
double xValue = ((transformedPos.X * fx_rgb * invZ) + cx_rgb);
result.X = (float)Math.Round(xValue, 0, System.MidpointRounding.AwayFromZero);
double yValue = ((transformedPos.Y * fy_rgb * invZ) + cy_rgb);
result.Y = (float)Math.Round(yValue, 0, System.MidpointRounding.AwayFromZero);
colorrecord.Add(result);
return result;
}
同样找到点云准备进度如下:
foreach (int rgbCoor in previousDepthListWithKeysTheseAreEqualTo_Y_Times640Plus_X.Keys)
{
PointCloud.rigidPointCloudLocationList.Add((Vector3) previousDepthListWithKeysTheseAreEqualTo_Y_Times640Plus_X[rgbCoor]);
//add the point coorinatis to the point cloud
//obtain the color
Vector3 point = (Vector3)previousDepthListWithKeysTheseAreEqualTo_Y_Times640Plus_X[rgbCoor];
Vector2 coor = WorldToColor(ref point);//in order to check Am I looking the correct coordinates
int indexCoor = 640 * (int)coor.Y + (int)coor.X;
Color color_ = Color.FromArgb(previousRawColorData[rgbCoor*4], previousRawColorData[rgbCoor*4 + 1], previousRawColorData[rgbCoor*4 + 2]);
PointCloud.rigidPointCloudColorList.Add(color_.ToArgb());
//now add the color And the color and 3d locaiton info will be on the same List index (double checked)
}
总结我的校准进度有问题。颜色和点云不匹配。有些开发人员使用Fisher的方法进行kinect校准没有问题。或者我错过了一些东西。我的实验中的一些screeenshots列出如下:
这对你来说是个类似的问题吗?因为我没有领导。
最后,我想问一个关于点云视图的问题。点云显示像网格表面的点(参见上面的最后一张图)。这是正常的吗?
提前致谢。
更新:有没有人知道这段代码是什么?:
result.x = Utility :: Bound(Math :: Round((transformedPos.x * fx_rgb * invZ)+ cx_rgb),0,639);
result.y = Utility :: Bound(Math :: Round((transformedPos.y * fy_rgb * invZ)+ cy_rgb),0,479);
我找不到任何关于“Utility :: Bound()”的解释?