0

我有一组从 0-5 索引的方形标记。这些标记由与其父级的偏移量和一组旋转 (x,y,z) 表示。父母是另一个标记(0-5)。例如,我可以让标记 0 作为根标记,1 是 0 的子标记,偏移量 (x:10,y:0,z:5) 和旋转 (x:0.5,y:0.1,z:0), 2 是 1 的孩子,3 是 0 的孩子,依此类推。

要从基本标记中找到标记的相对 3D 位置,您只需链接由偏移和旋转形成的变换矩阵。

该过程的第二步是从摄像机视图中检测这些标记。我使用类似于 ARToolkit 的 ALVAR 标记跟踪器完成了这项工作。我正在使用一个包装器,它允许我以 XNA 矩阵格式访问每个检测到的标记的相机变换矩阵(这是通过包装器从 OpenGL 格式更正的)。

我想测试检测到的标记模型与我定义的模型的匹配程度。为此,我选择一个检测到的标记作为“基础”标记,并从中重新投影出定义的标记模型。

使用 XNA 的代码是这样的:

首先,我们从 0(根)标记找到“基础”标记的相对变换:

Matrix globalTransformToPerform=Matrix.Identity;

//Find the markerIDTOBAse on
int mibo = 0;
foreach (Bone b in model.bones)
{
   foreach (Marker m in b.markers)
   {
       if (mibo != markerIDToBaseOn)
       {
           mibo++;
           continue;
        }
        else
        {
           //Chain Marker transform
           Matrix markerTransform =
                             Matrix.CreateRotationZ(m.z) *
                             Matrix.CreateRotationX(m.x) *
                             Matrix.CreateRotationY(m.y) *
                             Matrix.CreateTranslation(m.offset);

            //Add bone transform
            markerTransform *= Matrix.CreateRotationZ(MathHelper.ToRadians(b.z)) *
                             Matrix.CreateRotationX(MathHelper.ToRadians(b.x)) *
                             Matrix.CreateRotationY(MathHelper.ToRadians(b.y)) *
                             Matrix.CreateTranslation(b.Offset);

            //Chain parents transforms
            Bone parent = b.parent;
            while (parent != null)
            {
                 Matrix parentLocalTransform = Matrix.CreateRotationZ(MathHelper.ToRadians(parent.z)) *
                                               Matrix.CreateRotationX(MathHelper.ToRadians(parent.x)) *
                                               Matrix.CreateRotationY(MathHelper.ToRadians(parent.y)) *
                                               Matrix.CreateTranslation(parent.Offset);

                 markerTransform *= parentLocalTransform;

                 parent = parent.parent;
            }
                 globalTransformToPerform = markerTransform;
                 mibo++;
          }
       }
 }

现在,对于每个标记的每个角,我们根据“基础”标记在屏幕上找到它的预期 2D 投影位置。

 foreach (Bone b in model.bones)
 {
    foreach (Marker m in b.markers)
    {
        //foreach of the corners...
        for (int i = 0; i < 4; i++)
        {

            Matrix cornerTransform = Matrix.CreateTranslation(Global.cornerModel[i]);

            //Chain Marker transform
             Matrix markerTransform = cornerTransform *
                                      Matrix.CreateRotationZ(m.z) *
                                      Matrix.CreateRotationX(m.x) *
                                      Matrix.CreateRotationY(m.y) *
                                      Matrix.CreateTranslation(m.offset);

            //Add bone transform
            markerTransform *= Matrix.CreateRotationZ(MathHelper.ToRadians(b.z)) *
                               Matrix.CreateRotationX(MathHelper.ToRadians(b.x)) *
                               Matrix.CreateRotationY(MathHelper.ToRadians(b.y)) *
                               Matrix.CreateTranslation(b.Offset);

            //Chain parents transforms
            Bone parent = b.parent;
            while (parent != null)
            {
                  Matrix parentLocalTransform = Matrix.CreateRotationZ(MathHelper.ToRadians(parent.z))*        Matrix.CreateRotationX(MathHelper.ToRadians(parent.x))     *
                                                Matrix.CreateRotationY(MathHelper.ToRadians(parent.y)) *
                                                Matrix.CreateTranslation(parent.Offset);

                   markerTransform *= parentLocalTransform;

                   parent = parent.parent;
             }

             //Find 3D position
             Vector3 location = (markerTransform).Translation;

             //Now project
             Vector3 v = viewPort.Project(location * scalingFactor, projectionMatrix, Matrix.CreateLookAt(new Vector3(0, 0, 3), Vector3.Zero, Vector3.Up), worldTransform*globalTransformToPerform);
              Vector2 res = new Vector2(v.X, v.Y);

              //Store result
              cornersToRet.Add(res);
         }

      }
  }

问题是,标记没有按预期显示。我尝试过的事情:

  • 包装器工作正常,这已经过测试
  • 模型是正确的,我已经使用 XNA 将其绘制到屏幕上,并且符合预期。
  • 我使用与上述代码相同的转换将模型绘制到屏幕上。

这是我运行它时发生的情况:

绿色是标记跟踪器检测到的标记,投影到屏幕上。红色是基于“基础”标记的模型的标记角。

模型如下: 在此处输入图像描述

实验: 1. 0 是碱基标记,这个是有效的,因为从碱基的转换是相同的

在此处输入图像描述

  1. 1 是基础标记。这是不正确的。

任何解决此问题的帮助将不胜感激

在此处输入图像描述

4

1 回答 1

0

这是一个很长的镜头..但是根据我在您的解释中读到的内容,您首先检测到标记#1,然后检测到标记#2,依此类推...我假设如果您沿途未能识别标记,则使以前的标记也是如此。实际上纸 - >标记#1无法正确识别,因为下一个标记#2不在标记#1的右侧,因此两者都无效。正如我所说,这是一个很长的镜头,但是..您尝试将纸张顺时针旋转 90 度怎么样?

于 2012-06-04T04:59:43.587 回答