从单应矩阵计算比例、旋转和平移

18
我正在尝试计算视频的两个连续帧之间的比例、旋转和平移。基本上我匹配了关键点,然后使用OpenCV函数findHomography()来计算单应矩阵。
homography = findHomography(feature1 , feature2 , CV_RANSAC); //feature1和feature2是匹配的关键点 我的问题是:我如何使用此矩阵来计算比例、旋转和平移?
能否有人提供给我代码或说明如何做到这一点?

1
关键词是“单应性分解”。据我所知,您可以通过QR分解提取旋转,但最好还是谷歌一下... - Micka
1
也许这个链接可以帮到您:https://dev59.com/1W_Xa4cB1Zd3GeqP3qy0 - Micka
1
请提供更多上下文,以便我能够更好地理解您的请求。 - Micka
1
这是一个复杂的问题,但是这个答案解释得很好:https://dev59.com/zlvUa4cB1Zd3GeqPqy_2?rq=1 你应该尝试更深入地了解Homography矩阵的工作原理。通过这样做,你也会学习到它的优缺点。你还应该研究其他类型的变换,如仿射变换和刚性变换。如果它们能够解决你的问题,它们会更容易使用。 - Øystein W.
6个回答

7

2
我们是在讨论平面内的旋转还是三维旋转?问题似乎涉及到二维平面内的旋转,而答案则是关于三维旋转的。 - Vlad

2
正确的答案是使用单应性矩阵,因为它被定义为dst = H ⋅ src,并且探索它对特定点周围的小段的影响。

翻译

给定一个点,进行平移操作:

T = dst - (H ⋅ src)

旋转

给定两个点 p1 和 p2

p1 = H ⋅ p1

p2 = H ⋅ p2

现在只需计算向量 p1 p2 和 p1' p2' 之间的角度。

缩放

您可以使用相同的技巧,但现在只需比较长度:|p1 p2| 和 |p1' p2'|。

为了公平起见,使用另一条垂直于第一条线段的线段并平均结果。您会发现没有常数比例或平移因子。它们将取决于src位置。


2
给定单应性矩阵 H:
    |H_00, H_01, H_02|
H = |H_10, H_11, H_12|
    |H_20, H_21, H_22|

假设:

H_20 = H_21 = 0 并且通过归一化 H_22 = 1 来得到8个自由度。

沿x和y轴的平移是直接从H计算得出的:

tx = H_02
ty = H_12

在左上角的2x2子矩阵被分解以计算剪切、缩放和旋转。一种简单快速的分解方法在这里进行了解释。

注意:该方法假定矩阵可逆。


3D中的翻译无法完全恢复。 - Vlad
1
你在谈论仿射矩阵,它与单应矩阵不同。 - hillin
1
你是怎么假设第三行的第一和第二个元素为零的?在 cv::find_homography() 中,我没有得到两个连续帧的这样的值。 - Farid Alijani
我相信假设 H_20 = H_21 = 0H_22 = 1 意味着只有6个自由度。不确定是否确切地是仿射矩阵,但我认为它是仿射矩阵。 - Erotemic

1

由于我花了几天时间来创建我的单应性变换函数,所以我将把它放在这里,以使每个人都受益。

在这里,您可以看到主循环,在该循环中,每个输入位置都会乘以单应矩阵h。然后使用结果将像素从原始位置复制到目标位置。

    for (tempIn[0] = 0; tempIn[0] < stride; tempIn[0]++)
    {
        for (tempIn[1] = 0; tempIn[1] < rows; tempIn[1]++)
        {
            double w = h[6] * tempIn[0] + h[7] * tempIn[1] + 1; // very important!
            //H_20 = H_21 = 0 and normalized to H_22 = 1 to obtain 8 DOF. <-- this is wrong

            tempOut[0] = ((h[0] * tempIn[0]) + (h[1] * tempIn[1]) + h[2])/w;
            tempOut[1] =(( h[3] * tempIn[0]) +(h[4] * tempIn[1]) + h[5])/w;


            if (tempOut[1] < destSize && tempOut[0] < destSize && tempOut[0] >= 0 && tempOut[1] >= 0)
                dest_[destStride * tempOut[1] + tempOut[0]] = src_[stride * tempIn[1] + tempIn[0]];
        }
    }

在这样的过程之后,将生成一幅带有某种网格的图像。需要使用某种滤波器来去除该网格。在我的代码中,我使用了一个简单的线性滤波器。
注意:只有原始图像的中央部分真正需要用于生成正确的图像。可以安全地丢弃一些行和列。

0

0

对于估计由单应性引起的三维变换和旋转,存在多种方法。其中一种提供了分解单应性的闭合公式,但它们非常复杂。此外,解决方案从未是唯一的。

幸运的是,OpenCV 3已经实现了这种分解(decomposeHomographyMat)。给定一个单应性和一个正确缩放的内部矩阵,该函数提供了四组可能的旋转和平移。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接