Aurelius
Aurelius

Reputation: 11359

OpenCV estimateAffine3D breaks for coplanar points

I am trying to use OpenCV's estimateAffine3D() function to get the affine transformation between two sets of coplanar points in 3D. If I hold one variable constant, I find there is a constant error in the translation component of that variable.

My test code is:

std::vector<cv::Point3f> first, second;
std::vector<uchar> inliers;
cv::Mat aff(3,4,CV_64F);

for (int i = 0; i <6; i++)
{
    first.push_back(cv::Point3f(i,i%3,1));
    second.push_back(cv::Point3f(i,i%3,1));
}

int ret = cv::estimateAffine3D(first, second, aff, inliers);
std::cout << aff << std::endl;

The output I expect is:

[1 0 0 0]  
[0 1 0 0]  
[0 0 1 0]

Edit: My expectation is incorrect. The matrix does not decompose into [R|t] for the case of constant z-coordinates.

but what I get (with some rounding for readability) is:

[1 0 0 0]  
[0 1 0 0]  
[0 0 0.5 0.5]

Is there a way to fix this behavior? Is there a function which does the same on sets of 2D points?

Upvotes: 2

Views: 7696

Answers (2)

Shiyu
Shiyu

Reputation: 455

The key problem is: Your purpose is to estimate the rotation and translation between two sets of 3D points, but the OpenCV function estimateAffine3D() is not for that purpose. As its name suggests, this function is to compute the affine transformation between two sets of 3D points. When computing the affine transformation, the constraints on the rotation matrix is not considered. Of course, the result is not correct. To obtain the rotation and translation, you need to implement the SVD based algorithm.You may search "absolute orientation" in google. This is a classic and closed-form algorithm.

Upvotes: 0

Hammer
Hammer

Reputation: 10329

No matter how I run your code I get fine output. For example when I run it exactly as you posted it I get.

[1,0,0 ,0]
[0,1,0 ,0]
[0,0,.5,.5]

which is correct because the 4th element of a homogeneous coordinate is assumed to be 1. When I run it with 2 as the z value I get

[1,0,0 ,0]
[0,1,0 ,0]
[0,0,.8,.4]

which also works (.8*2+.4 = 2). Are you sure you didn't just read aff(2,2) wrong?

Upvotes: 2

Related Questions