如何在opencv中获取getPerspectiveTransform的比例因子?
Posted
技术标签:
【中文标题】如何在opencv中获取getPerspectiveTransform的比例因子?【英文标题】:How to get the scale factor of getPerspectiveTransform in opencv? 【发布时间】:2015-12-21 04:49:15 【问题描述】:我有图像 A,我想得到图像 A 的鸟瞰图。所以我使用 getPerspectiveTransform 方法来获取变换矩阵。输出结果是 3x3 矩阵。看我的代码。就我而言,我想知道 3x3 矩阵的比例因子。我查看了 opencv 文档,但找不到转换矩阵的详细信息,也不知道如何获得比例。我也读过一些论文,论文说我们可以从 a11、a12、a21、a22 获得缩放、剪切和旋转。见图片。那么我怎样才能得到比例因子。你能给我一些建议吗?你能解释一下 getPerspectiveTransform 输出矩阵吗?谢谢!
Points[0] = Point2f(..., ...);
Points[1] = Point2f(..., ...);
Points[2] = Point2f(..., ...);
Points[3] = Point2f(..., ...);
dst[0] = Point2f(..., ...);
dst[1] = Point2f(..., ...);
dst[2] = Point2f(..., ...);
dst[3] = Point2f(..., ...);
Mat trans = getPerspectiveTransform(gpsPoints, dst);//I want to know the scale of trans
warpPerspective(A, B, trans, img.size());
当我改变相机位置时,梯形大小和位置会改变。现在我们把它设置成一个矩形,矩形的宽度/高度是已知的。但我认为不同高度的相机应该改变矩形大小。因为如果我们设置成相同大小的矩形,矩形可能有不同的细节。这就是为什么我想从 3x3 变换矩阵中知道比例。例如,梯形 1 和梯形 2 具有从尺度 s1 和 s2 的变换。所以我们可以设置 rectangle1(width,height) = s2/s1 * rectangle2(width,height)。
【问题讨论】:
了解单应性分解。我不确定它是否可以解决。正如您所读到的,缩放、旋转和剪切使用矩阵的重叠部分。 我对射影几何不是很熟悉。如果我对规模不完全了解,您可能会发现Direct Linear Transform 很有用。 :) 我记得...由于 Q 是正交矩阵,它应该是 3x3 单应性的旋转部分。所以你可以继续使用R矩阵,它是上三角矩阵,包含scaleX、scaleY和shear参数。 但这可能只适用于没有透视元素的仿射单应性...... 【参考方案1】:好的,给你:
H is the homography
H = T*R*S*L with
T = [1,0,tx; 0,1,ty; 0,0,1]
R = [cos(a),sin(a),0; -sin(a),cos(a),0; 0,0,1]
S = [sx,shear,0; 0,sy,0; 0,0,1]
L = [1,0,0; 0,1,0; lx,ly,1]
where tx/ty is translation; a is rotation angle; sx/sy is scale; shear is shearing factor; lx/ly are perspective foreshortening parameters.
如果我理解正确,您想计算 sx 和 sy。
现在如果 lx 和 ly 都是 0,那么计算 sx 和 sy 就很容易了。它将通过 QR 分解来分解 H 的左上部分,得到 Q*R,其中 Q 是正交矩阵(= 旋转矩阵),R 是上三角矩阵([sx, shear; 0,sy]
)。
h1 h2 h3
h4 h5 h6
0 0 1
=> Q*R = [h1,h2; h4,h5]
但是 lx 和 ly 破坏了简单的方法。所以你必须找出矩阵的左上部分在没有 lx 和 ly 影响的情况下是什么样子的。
如果你的整个单应性是:
h1 h2 h3
h4 h5 h6
h7 h8 1
那么你将拥有:
Q*R =
h1-(h7*h3) h2-(h8*h3)
h4-(h7*h6) h5-(h8*h6)
因此,如果您从该矩阵计算 Q 和 R,则可以轻松计算旋转、缩放和剪切。
我已经用一个小型 C++ 程序对此进行了测试:
double scaleX = (rand()%200) / 100.0;
double scaleY = (rand()%200) / 100.0;
double shear = (rand()%100) / 100.0;
double rotation = CV_PI*(rand()%360)/180.0;
double transX = rand()%100 - 50;
double transY = rand()%100 - 50;
double perspectiveX = (rand()%100) / 1000.0;
double perspectiveY = (rand()%100) / 1000.0;
std::cout << "scale: " << "(" << scaleX << "," << scaleY << ")" << "\n";
std::cout << "shear: " << shear << "\n";
std::cout << "rotation: " << rotation*180/CV_PI << " degrees" << "\n";
std::cout << "translation: " << "(" << transX << "," << transY << ")" << std::endl;
cv::Mat ScaleShearMat = (cv::Mat_<double>(3,3) << scaleX, shear, 0, 0, scaleY, 0, 0, 0, 1);
cv::Mat RotationMat = (cv::Mat_<double>(3,3) << cos(rotation), sin(rotation), 0, -sin(rotation), cos(rotation), 0, 0, 0, 1);
cv::Mat TranslationMat = (cv::Mat_<double>(3,3) << 1, 0, transX, 0, 1, transY, 0, 0, 1);
cv::Mat PerspectiveMat = (cv::Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, perspectiveX, perspectiveY, 1);
cv::Mat HomographyMatWithoutPerspective = TranslationMat * RotationMat * ScaleShearMat;
cv::Mat HomographyMat = HomographyMatWithoutPerspective * PerspectiveMat;
std::cout << "Homography:\n" << HomographyMat << std::endl;
cv::Mat DecomposedRotaScaleShear(2,2,CV_64FC1);
DecomposedRotaScaleShear.at<double>(0,0) = HomographyMat.at<double>(0,0) - (HomographyMat.at<double>(2,0)*HomographyMat.at<double>(0,2));
DecomposedRotaScaleShear.at<double>(0,1) = HomographyMat.at<double>(0,1) - (HomographyMat.at<double>(2,1)*HomographyMat.at<double>(0,2));
DecomposedRotaScaleShear.at<double>(1,0) = HomographyMat.at<double>(1,0) - (HomographyMat.at<double>(2,0)*HomographyMat.at<double>(1,2));
DecomposedRotaScaleShear.at<double>(1,1) = HomographyMat.at<double>(1,1) - (HomographyMat.at<double>(2,1)*HomographyMat.at<double>(1,2));
std::cout << "Decomposed submat: \n" << DecomposedRotaScaleShear << std::endl;
现在可以使用http://www.bluebit.gr/matrix-calculator/的QR矩阵分解来测试结果
首先,您可以尝试将 perspectiveX 和 perspectiveY 设置为零。您会看到可以使用矩阵的左上部分分解为旋转角度、剪切和比例的输入值。 但是如果你不将perspectiveX和perspectiveX设置为零,你可以使用“DecomposedRotaScaleShear”并将其分解为QR。
你会得到一个结果页面
Q:
a a
-a a
在这里您可以计算acos(a)
以获得角度
R:
sx shear
0 sy
这里可以直接读取 sx 和 sy。
希望这会有所帮助,我希望没有错误;)
【讨论】:
非常感谢!我从你的评论中学到了很多。我也在这里问问题,answers.opencv.org/question/80040/…有人说“图像的不同部分有不同的比例因子”。我没有不明白意思。但是你说比例是 sx/sy,所以在你的回答中,不同的部分有相同的比例,对吧?另外,我想知道我现在的想法是否正确。我想获得比例,因为我不想将不同的比例设置为相同的比例。详情请参阅我的更新。你能给我建议吗? “规模”一词含糊不清。如果您想知道单应性的比例因子(例如拒绝具有“非法”参数的单应性),您需要的是 sx qnd sy。如果您想知道特定转换对象/区域的像素大小/区域,您应该对其进行转换并针对该特定情况进行计算。你想达到什么目标?可以举一个具体的例子你想计算什么? 我不明白你的任务。你有左边梯形的图像,你知道右边的真实矩形大小吗?或者你想计算/近似右边的真实矩形大小?请创建一个示例来显示给定的内容以及您要计算的内容! 是的,我知道图像中高度:宽度(2:3)的矩形比例。问题是我想根据变换矩阵比例设置矩形大小。您可以看到左侧,有两个梯形。一个大一个小,如果我将它们转换为右侧矩形。大的还可以,但小的……你可以看到它放大了近 10 倍。我觉得不好。它应该转换成一个小尺寸的矩形。所以我想使用规模来做到这一点。 单应性是从左到右计算,还是从左到左计算?我仍然不清楚。“我想设置矩形大小”是什么意思? “将它们转换为右侧三角形”是什么意思?如果您的意思是扭曲图像,为什么从小开始扭曲是个问题?以上是关于如何在opencv中获取getPerspectiveTransform的比例因子?的主要内容,如果未能解决你的问题,请参考以下文章