简体   繁体   中英

How to get the scale factor of getPerspectiveTransform in opencv?

I have image A and i want to get the bird-eye's view of image A. So I used getPerspectiveTransform method to get the transform matrix. The output result is 3x3 matrix. See my code. In my case i want to know the scale factor of the 3x3 matrix. I have looked the opencv document, but i cannot find detail of the transform matrix and i don't know how to get the scale. Also i have read some paper, the paper said we can get scaling, shearing and ratotion from a11, a12, a21, a22. See the pic. So how can i get the scale factor. Can you give me some advice? And can you explain the getPerspectiveTransform output matrix?Thank you!

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());

在此处输入图片说明

在此处输入图片说明

When i change the camara position, the trapezium size and position will change. Now we set it into a rectangle and rectangle width/height was known. But i think camera in different height the rectangle size should have been changed.Because if we set into same size rectangle, the rectangle may have different detal. That's why i want to know scale from 3x3 transfrom matrix. For example, trapezium1 and trapezium2 have transfrom scale s1 and s2. So we can set rectangle1(width,height) = s2/s1 * rectangle2(width,height).

Ok, here you go:

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.

You want to compute sx and sy if I understood right. Now If lx and ly are both 0 it would be easy to compute sx and sy. It would be to decompose the upper left part of H by QR decomposition resulting in Q*R where Q is an orthogonal matrix (= rotation matrix) and R is an upper triangle matrix ( [sx, shear; 0,sy] ).

h1 h2 h3
h4 h5 h6
0  0  1

=> Q*R = [h1,h2; h4,h5]

But lx and ly destroy the easy way. So you have to find out how the upper left part of the matrix would look like without the influence of lx and ly.

If your whole homography is:

h1 h2 h3
h4 h5 h6
h7 h8 1

then you'll have:

Q*R = 
h1-(h7*h3)   h2-(h8*h3)
h4-(h7*h6)   h5-(h8*h6)

So if you compute Q and R from this matrix, you can compute rotation, scale and shear easily.

I've tested this with a small C++ program:

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;

Now you can test the result by using the QR matrix decomposition of http://www.bluebit.gr/matrix-calculator/

First you can try to set perspectiveX and perspectiveY to zero. You'll see that you can use the upper left part of the matrix to decompose to the input values of rotation angle, shear and scale. But if you don't set perspectiveX and perspectiveX to zero, you can use the "DecomposedRotaScaleShear" and decompose it to QR.

You'll get a result page with

Q:

 a a
-a a

here you can compute acos(a) to get the angle

R:

sx shear
0  sy

here you can read sx and sy directly.

Hope this helps and I hope there is no error ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM