从Homography矩阵计算尺度,旋转和平移

时间:2014-09-04 06:16:48

标签: c++ opencv video matrix homography

我正在尝试计算视频的两个连续帧之间的缩放,旋转和平移。所以基本上我匹配了关键点,然后使用opencv函数findHomography()来计算单应矩阵 homography = findHomography(feature1 , feature2 , CV_RANSAC); //feature1 and feature2 are matched keypoints

我的问题是:如何使用此矩阵计算比例,旋转和平移? 任何人都可以向我提供有关如何操作的代码或解释吗?

6 个答案:

答案 0 :(得分:5)

答案 1 :(得分:0)

为了估计由单应性引起的树维变换和旋转,存在多种方法。 One of them提供了用于分解单应性的封闭公式,但它们非常复杂。此外,解决方案永远不是唯一的。

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

答案 2 :(得分:0)

假设第三行的第一个和第二个单元格为0。

矩阵的第三列包含X中的平移,Y和1中的平移。

对于单应矩阵的剩余左上2x2部分(包含剪切,缩放和旋转),可以按照不同的方法进行分解。这里解释了一个简单快捷的方法(此方法假设可逆矩阵):https://math.stackexchange.com/questions/78137/decomposition-of-a-nonsquare-affine-matrix

答案 3 :(得分:0)

正确的答案是使用Homography,因为它定义为dst = H. src并探索它对特定点周围的小段的作用。 对于翻译,只需选择一个点: 翻译= dst-H .src 对于旋转探索两个点p1和p2。 p1'= H. p1,p2'= H. P2。现在只计算向量p1 p2和p1'p2'之间的角度。 对于比例,你可以使用相同的技巧,但现在只需比较长度 | p1 p2 |和| p1'p2'|。为了票价使用与第一个正交的另一个段并对结果求平均值。您将看到没有恒定的比例因子或翻译因子。它们将取决于src的位置。

答案 4 :(得分:0)

问题似乎是关于2D参数。 Homography矩阵捕获透视失真。如果应用程序没有创建太多的透视变形,则可以使用仿射变换矩阵(仅使用缩放,旋转,平移和不剪切/翻转)来逼近真实世界变换。以下链接将提供关于将仿射变换分解为不同参数的想法。

https://math.stackexchange.com/questions/612006/decomposing-an-affine-transformation

答案 5 :(得分:0)

由于我不得不花几天的时间来创建我的单应变换功能,所以我打算把它放在这里以使所有人受益。

在这里您可以看到主回路,其中每个输入位置乘以单应性矩阵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]];
        }
    }

经过这样的处理,将产生带有某种网格的图像。需要某种过滤器才能移除网格。在我的代码中,我使用了一个简单的线性滤波器。

注意:真正需要原始图像的中心部分才能生成正确的图像。某些行和列可以安全地丢弃。