gpt4 book ai didi

c++ - 我可以简单地添加仿射或透视(单应性)变换矩阵吗?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:34:14 34 4
gpt4 key购买 nike

众所周知,在 OpenCV 中,我可以在 2 个图像之间进行仿射或透视变换:

然后我可以这样做:

  • 仿射变换 - 通过使用 warpAffine(img_src, img_dst, M)
  • 透视变换 - 通过使用 warpPerspective(img_src, img_dst, H)

但是如果我有 3 张或更 multimap 片,并且我已经找到了:

  • 仿射:M1(img1 -> img2),M2(img2 -> img3)
  • 透视:H1(img1 -> img2),H2(img2 -> img3)

那么我可以通过简单地添加两个矩阵来得到转换矩阵 (img1 -> img3) 吗?

  • 仿射变换:M3 = M1 + M2;
  • 透视变换:H3 = H1 + H2;

或者我应该为此使用哪个函数?

最佳答案

不,您需要相乘矩阵才能获得级联效果。我不会深入研究数学,但对坐标应用变换是执行矩阵乘法的问题。如果你想知道为什么会这样,我建议你引用这个 good Wikipedia article on cascading matrix transformations .给定一个坐标 X 和一个变换矩阵 M,您可以通过以下方式获得输出坐标 Y:

Y = M*X

这里我使用* 来指代矩阵 乘法,而不是逐元素乘法。您拥有的是一对转换矩阵,从 img1img2 然后从 img2img3。你需要做两次手术。所以要从 img1img2 其中 X 属于 img1 的坐标空间,我们有(假设我们'正在使用仿射矩阵):

Y1 = M1*X

接下来,要从 img2img3,我们有:

Y2 = M2*Y1 --> Y2 = M2*M1*X --> Y2 = M3*X --> M3 = M2*M1

因此,要获得所需的链式效应,您需要创建一个新矩阵,使 M2 乘以 M1。与 H2H1 相同。

因此定义一个新的矩阵:

cv::Mat M3 = M2*M1;

与投影矩阵类似,您可以:

cv::Mat H3 = H2*H1;

但是,estimateRigidTransform(在您的情况下输出为 M)为您提供了一个 2 x 3 矩阵。一个技巧是扩充这个矩阵,使它变成 3 x 3,我们添加一个额外的行,其中除了最后一个元素全为 0 ,它被设置为 1。因此,你将拥有最后一行变成 [0 0 1]。您可以对两个矩阵执行此操作,将它们相乘,然后仅将前两行提取到一个新矩阵中以通过管道传输到 warpAffine 中。因此,做这样的事情:

// Create padded matrix for M1
cv::Mat M1new = cv::Mat(3,3,M1.type());
M1new.at<double>(0,0) = M1.at<double>(0,0);
M1new.at<double>(0,1) = M1.at<double>(0,1);
M1new.at<double>(0,2) = M1.at<double>(0,2);

M1new.at<double>(1,0) = M1.at<double>(1,0);
M1new.at<double>(1,1) = M1.at<double>(1,1);
M1new.at<double>(1,2) = M1.at<double>(1,2);

M1new.at<double>(2,0) = 0.0;
M1new.at<double>(2,1) = 0.0;
M1new.at<double>(2,2) = 1.0;

// Create padded matrix for M2
cv::Mat M2new = cv::Mat(3,3,M2.type());
M2new.at<double>(0,0) = M2.at<double>(0,0);
M2new.at<double>(0,1) = M2.at<double>(0,1);
M2new.at<double>(0,2) = M2.at<double>(0,2);

M2new.at<double>(1,0) = M2.at<double>(1,0);
M2new.at<double>(1,1) = M2.at<double>(1,1);
M2new.at<double>(1,2) = M2.at<double>(1,2);

M2new.at<double>(2,0) = 0.0;
M2new.at<double>(2,1) = 0.0;
M2new.at<double>(2,2) = 1.0;

// Multiply the two matrices together
cv::Mat M3temp = M2new*M1new;

// Extract out relevant rows and place into M3
cv::Mat M3 = cv::Mat(2, 3, M3temp.type());
M3.at<double>(0,0) = M3temp.at<double>(0,0);
M3.at<double>(0,1) = M3temp.at<double>(0,1);
M3.at<double>(0,2) = M3temp.at<double>(0,2);

M3.at<double>(1,0) = M3temp.at<double>(1,0);
M3.at<double>(1,1) = M3temp.at<double>(1,1);
M3.at<double>(1,2) = M3temp.at<double>(1,2);

处理cv::Mat* 运算符时,it is overloaded to specifically perform matrix multiplication .

然后您可以将 M3H3 分别用于 warpAffinewarpPerspective


希望这对您有所帮助!

关于c++ - 我可以简单地添加仿射或透视(单应性)变换矩阵吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29749344/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com