Kinect光标控制与虚拟XNA矩形 - '触摸板' - Y轴反转
问题描述:
我试图为MS Kinect实施一个实时战略控制方案。 到目前为止,我有一个光标,可以通过移动左手(或右手,取决于你的手)来移动。我有一个基于Open-NI的Kinect控制器,它为玩家动作设置了一个框架,并将腕,肘,肩和身体中心坐标传递给我的应用程序。 为了将这些手腕坐标投影到屏幕上,我设置了一个矩形,它位于玩家中心的左侧/右侧,只要手腕在矩形内移动,光标就会在屏幕上移动。 我的问题是,XNA-Rectangle以左上角为原点,即X轴指向右边,因为它“应该”,但Y轴指向下方,而Kinect的Y轴 - 坐标系指向上。这会导致光标在屏幕上向上移动,当我将手向下移动时,反之亦然。我无法用Kinect坐标系改变任何东西,所以是否可以'翻转'矩形的'坐标系',以便Y轴也指向?Kinect光标控制与虚拟XNA矩形 - '触摸板' - Y轴反转
下面是相关代码:
(自校准() - 方法:)
List<Vector3> joints = UDPlistener.getInstance().ParseCalibCoordinates(data);
//0 = Right Wrist 1 = Right Elbow 2 = Right Shoulder
//3 = Left Wrist 4 = Left Elbow 5 = Left Shoulder
//6 = Center
height = 762;
width = 1024;
switch (hand)
{
case 0:
cursorSpace = new Rectangle((int)(joints[6].X * 2) - 200, (int)(joints[6].Y * 2) + height, width, height);
break;
case 3:
cursorSpace = new Rectangle((int)(joints[6].X * 2) - 1200, (int)(joints[6].Y * 2) + height, width, height);
break;
}
public Point Cursor(String data)
{
List<Vector3> joints = UDPlistener.getInstance().ParsePlayCoordinates(data);
//0 = Right Wrist 1 = Left Wrist 2 = Center
double mhx = 0; //main hand x-coordinate
double mhy = 0; // main hand y-coordinate
switch (hand)
{
case 0:
mhx = joints[hand].X;
mhy = joints[hand].Y;
break;
case 3:
mhx = joints[hand-2].X;
mhy = joints[hand-2].Y;
break;
}
int x;
int y;
if (Math.Abs(mhx - mhxOld) < 1.0 || Math.Abs(mhy - mhyOld) < 1.0)
//To remove jittering of the cursor
{
x = (int) mhxOld * 2;
y = (int) mhyOld * 2;
}
else
{
x = (int) mhx * 2;
mhxOld = mhx;
y = (int) mhy * 2;
mhyOld = mhy;
}
Point cursor = new Point(0,0);
if (cursorSpace.Contains(x,y))
{
cursor = new Point(x - cursorSpace.X, y - CursorSpace.Y);
lastCursorPos = cursor;
return cursor;
}
对不起,文字的墙,我希望,我能说清楚了。
由于提前,
KK
答
我使用用于转换OpenNI坐标的扩展方法。以下示例将OpenNI坐标映射到左上角的640x480矩形中的XNA坐标,表示为Vector2对象。
public static Vector2 ToXnaCoordinates(this Point3D point)
{
return new Vector2(
point.X + 320,
(point.Y - 240) * -1);
}
翻转y坐标的魔力是* -1
部分。
如果您想要达到一个不同于640x480大小的矩形,则需要在转换后相应地缩放坐标。例如:
public static Vector2 ToScaledXnaCoordinates(this Point3D point, int rectSizeX, int rectSizeY)
{
return new Vector2(
(point.X + 320) * rectSizeX/640,
(point.Y - 240) * -rectSizeY/480);
}
答
我知道这是不是XNA,但我希望把这个在那里为那些WPF用户:)如果你正在使用类似的方法Channel 9's,只是有一个布尔值,以确定是否反转或不。例如:
private void ScalePosition(FrameworkElement element, Joint joint, bool inverted)
{
//convert the value to X/Y
Joint scaledJoint = joint.ScaleTo(967, 611);
//convert & scale (.3 = means 1/3 of joint distance)
//Joint scaledJoint = joint.ScaleTo(1280, 720, 1f, 1f);
if (!inverted)
{
Canvas.SetLeft(element, scaledJoint.Position.X);
Canvas.SetTop(element, scaledJoint.Position.Y);
}
if (inverted)
{
Canvas.SetLeft(element, scaledJoint.Position.X);
Canvas.SetBottom(element, scaledJoint.Position.Y);
}
}
希望这有助于WPF用户!
+1从来没有想到的* -1 ...尽可能简单,因为它:) – 2012-07-23 14:36:26
好吧,它的工作,非常感谢。但是另一个问题出现了。用我的方法,我有一个整洁的区域,向用户的光标指针移动,并使屏幕上的每个点都可以轻松到达,而不会拉伸或弯曲过多。我将你的方法应用到了我的'光标' - 方法的开关(手部) - 区块中,它的功能非常出色,但现在'传感器'区域恰好位于播放器的前方,并且降至略高于膝盖的水平。我尝试使用'if(cursorSpace.Contains)'的未修改的手部坐标,然后将'魔术'用作偏移,但是它没有按预期工作。有任何想法吗? – 2012-07-24 15:15:15
为了最大限度地减少手部移动,我建议调整+320和-240。此外,您可能需要将坐标(移位后)缩放到矩形的大小。基本上,你将不得不尝试改变+320,-240,640,480值。不幸的是,我无法提供理想的解决方案,因为它因案例而异。但是,不要忘记,随着目标区域大小的增加,准确度会降低。 – 2012-07-25 06:17:40