找到两个标记之间的角度,用于数学优化

时间:2012-05-23 17:42:24

标签: c# math geometry computer-vision mathematical-optimization

我试图通过一组未知参数来最小化3d空间中方形标记集之间的差异。

我有一组这些方形标记的模型集(由3d位置和旋转表示),它应该在优化结束时与一组观察到的方形标记匹配。

我使用Levenberg–Marquardt来优化未知参数集,这些参数将改变模型3d标记的位置和旋转,直到它们与观察到的3d标记位置匹配(或多或少)。

观察到的3d标记来自计算机视觉标记检测算法。它给出了每个帧中看到的标记的id以及每个标记的相机的转换(using Coplanar posit)。每个“框架”只能在总标记集中看到少量标记,转换中也会出现不准确的情况。

我已经想过如何构建我的最小化函数,我想尝试比较相对旋转并最小化LM优化的每次迭代中旋转之间的差异。

本质:

        foreach (Marker m1 in markers)
        {
            foreach (Marker m2 in markers)
            {
                Vector3 eulerRotation = getRotation(m1, m2);
                ObservedMarker observed1 = getMatchingObserved(m1);
                ObservedMarker observed2 = getMatchingObserved(m2);
                Vector3 eulerRotationObserved = getRotation(observed1, observed2);

                double diffX = Math.Abs(eulerRotation.X - eulerRotationObserved.X);
                double diffY = Math.Abs(eulerRotation.Y - eulerRotationObserved.Y);
                double diffZ = Math.Abs(eulerRotation.Z - eulerRotationObserved.Z);
            }
        }

其中diffX,diffY和diffZ是要最小化的值。

我使用以下方法计算角度:

Vector3 axis = Vector3.Cross(getNormal(m1), getNormal(m2));
axis.Normalize();
double angle = Math.Acos(Vector3.Dot(getNormal(m1), getNormal(m2)));
Vector3 modelRotation = calculateEulerAngle(axis, angle);

getNormal(Marker m)计算方形标记所在平面的法线。

我确信我在这里做错了。将这一切全部投入LM优化器(我正在使用ALGLib)似乎没有做任何事情,它经历了1次迭代并完成而不更改任何未知参数(最初全部为0)。

我认为我试图最小化的功能出了问题。似乎有时计算的角度(第3行)返回NaN(我当前设置此情况以返回diffX,diffY,diffZ为0)。比较上面的欧拉角是否有效?

非常感谢任何帮助。

更多信息:

  • 程序是用C#编写的,我也在使用XNA。
  • 模型标记由3D坐标中的四个角来表示
  • 所有模型标记都在相同的坐标空间中。
  • 观察到的标记是从摄像机坐标空间中的摄像机位置翻译的四个角落
  • 如果m1和m2标记是相同的标记ID,或者如果未观察到m1或m2,我将所有差异设置为0(无差异)。

2 个答案:

答案 0 :(得分:1)

起初我认为这可能是一个错字,但后来我意识到这可能是一个错误,过去曾是我自己的类似病例的受害者。

不应该是diffY和diffZ:

double diffY = Math.Abs(eulerRotation.Y - eulerRotationObserved.Y);
double diffZ = Math.Abs(eulerRotation.Z - eulerRotationObserved.Z);

我没有足够的声誉将此作为评论发布,因此将其作为答案发布!

答案 1 :(得分:0)

运气好吗?假设您希望最小化所有标记组合上所有差异的“总和”,这是正确的吗?我想如果你想使用LM,你不应该使用Math.Abs

另一种方法是手动制定目标函数并使用另一个优化器。我最近将两个非线性优化器移植到C#,甚至不需要你计算衍生物:

  • COBYLA2,支持非线性约束,但需要更多迭代。
  • BOBYQA,仅限于变量边界约束,但提供了相当高效的迭代方案。