我试图通过跟踪球体上的表面特征来跟踪球体的旋转。
TL; DR:我是否错误平均四元数?
让我们跳过特征检测和匹配,它只是来自OpenCV的ORB + FLANN。这为两个连续的帧提供了两组(匹配的)关键点。
我根据它们与球体中心1的距离将关键点放置在球体上,将关键点投影到3d中。这给了我球体坐标系中的关键点。
从匹配的关键点作为向量,我计算一组四元数,表示自上一帧(algorithm used)以来的旋转。
a = np.cross(v1,v2)
w = np.sqrt(np.linalg.norm(v1)**2 * np.linalg.norm(v2)**2) + np.dot(v1,v2)
return quaternion(w, a[0], a[1], a[2]).normalized()
所以在这一点上我的想法是所有这些四元数代表相同的旋转(加/减噪声)。所以在理论上我应该能够计算出我的四元数集的平均四元数,并且很好地了解了自上一帧(algorithm used)以来我的球体是如何移动的。
np.linalg.eig(np.mean(np.array([np.outer(q,q) for q in quats]), axis=0))[0]
事实是,这导致所有帧的单位四元数(或接近,如e ^ -06关闭):
quaternion(0.999999999865224, -4.24742027709118e-06, 1.4799762763963e-05, 5.69900765792268e-06)
(“天真”对所有四元数进行平均实际上产生的结果看起来可能与原始旋转相符,但我宁愿使用经过验证的方法)
所以,我有两个理论:
思考?
1我知道我必须处理相机投影,但为了概念验证,我选择忽略它。
你有什么问题?目前还不清楚你想要找到什么。
但是,不管它是什么,你的算法显然是错误的。球体上1点的移动不能唯一地定义球体旋转。
我的想法是所有这些四元数代表相同的旋转
他们不是。您可以使用公式从单个点的移动中查找四元数。该公式找到的旋转假定该点沿着一个大圆圈移动。
旋转球体时,只有赤道上的点(由旋转轴定义)沿大圆移动,其余点沿其他更有趣的曲线移动。
更新:据我所知,你有噪音,跟踪文物和其他恶作剧。一种方法可以是使用数值方法直接从点找到欧拉角(不是四元数,四元数需要归一化,即它们对求解器具有不需要的自由度)。也许CV的DownhillSolver
或ConjGradSolver
会为你效劳。可能有用的是运行两次,找到旋转,然后以最差的预测下降10-20%的点,然后再次在80-90%的好点上再次解决。
更新2见图片。 绿线是两点的实际运动,作为球体旋转的一部分。显然,它们围绕同一轴旋转,但不是沿着大圆旋转。红线是这些点对之间的大圆圈旋转,由您错误应用的公式找到。蓝色虚线是红色旋转的轴。我希望你现在明白为什么你不能应用这个公式。