0

我正在尝试使用一组未知参数来最小化 3d 空间中的方形标记集之间的差异。

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

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

观察到的 3d 标记来自计算机视觉标记检测算法。它给出了每帧中看到的标记的 id 以及每个标记的相机转换(使用 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(无差异)。
4

2 回答 2

1

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

diffY 和 diffZ 不应该是:

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

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

于 2012-05-23T19:06:25.037 回答
0

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

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

  • COBYLA2,支持非线性约束,但需要更多迭代。
  • BOBYQA,仅限于可变边界约束,但提供了相当有效的迭代方案。
于 2012-06-14T15:04:58.790 回答