flor1an
flor1an

Reputation: 980

Transform image via a given matrix using OpenCv

what I'm trying to do is transforming an image using an (Matlab) transformation matrix. It is the following 2D transformation matrix with a 3x3 dimension:

aaa   bbb   0
ccc   ddd   0
eee   fff   1

I found a pretty good explanation here: how to transform an image with a transformation Matrix in OpenCv? but I'm not able to fill the 3x3 matrix (and apply it to the image). This is my code:

cv::Mat t(3,3,CV_64F,cvScalar(0.0));

t.at<double>(0, 0) = aaa;
t.at<double>(1, 0) = bbb;
t.at<double>(2, 0) = 0;

t.at<double>(0, 1) = ccc;
t.at<double>(1, 1) = ddd;
t.at<double>(2, 1) = 0;

t.at<double>(0, 2) = eee;
t.at<double>(1, 2) = fff;
t.at<double>(2, 2) = 1;  

cv::Mat dest;
cv::Size size(imageToTransform.cols,imageToTransform.rows);
warpAffine(imageToTransform, outputImage, t, size, INTER_LINEAR, BORDER_CONSTANT);

imshow("outputImage", outputImage);

Causes the following error:

OpenCV Error: Assertion failed ((M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3)

Any idea whats wrong here?

Upvotes: 1

Views: 1702

Answers (1)

api55
api55

Reputation: 11420

The transformation matrix used in warp affine is an affine transformation matrix, which representation is as follows:

a11 a12 b1
a21 a22 b2
0   0   1

this means it is a 3x3 matrix indeed. However OpenCV doesn't care about the last row, since it will always be the same (look at the link before). Then, you can eliminate this row and have the input needed (2x3):

a11 a12 b1
a21 a22 b2

In getAffineTransform you can see why they want it like that (to have an homgeneous point mapped to the new 2d point and have it already in 2d and avoid extra multiplications).

You have a matrix of the type:

aaa   bbb   0
ccc   ddd   0
eee   fff   1

This seems to be transpose somehow? since I do not know how did you generate the matrix, I can't tell for sure. Maybe you have transpose it and then assign it to opencv (or do it directly). The funny part is that (intentionally or otherwise) you had it in your c++ code the matrix transpose. Remember that OpenCV notation is usually (rows, columns) in most of the cases.

Your code should look like:

cv::Mat t(2,3,CV_64F,cvScalar(0.0));

t.at<double>(0, 0) = aaa;
t.at<double>(1, 0) = bbb;

t.at<double>(0, 1) = ccc;
t.at<double>(1, 1) = ddd;

t.at<double>(0, 2) = eee;
t.at<double>(1, 2) = fff;

cv::Mat dest;
cv::Size size(imageToTransform.cols,imageToTransform.rows);
warpAffine(imageToTransform, outputImage, t, size, INTER_LINEAR, BORDER_CONSTANT);

imshow("outputImage", outputImage);

I hope this helps you with the problem.

Upvotes: 3

Related Questions