findHomography, getPerspectiveTransform, & getAffineTransform

前端 未结 5 937
情话喂你
情话喂你 2020-12-23 11:35

This question is on the OpenCV functions findHomography, getPerspectiveTransform & getAffineTransform

  1. What is the

5条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-23 12:19

    There is an easy solution for the finding the Affine transform for the system of over-determined equations.

    1. Note that in general an Affine transform finds a solution to the over-determined system of linear equations Ax=B by using a pseudo-inverse or a similar technique, so

    x = (A At )-1 At B

    Moreover, this is handled in the core openCV functionality by a simple call to solve(A, B, X).

    1. Familiarize yourself with the code of Affine transform in opencv/modules/imgproc/src/imgwarp.cpp: it really does just two things:

      a. rearranges inputs to create a system Ax=B;

      b. then calls solve(A, B, X);

    NOTE: ignore the function comments in the openCV code - they are confusing and don’t reflect the actual ordering of the elements in the matrices. If you are solving [u, v]’= Affine * [x, y, 1] the rearrangement is:

             x1 y1 1 0  0  1
             0  0  0 x1 y1 1
             x2 y2 1 0  0  1
        A =  0  0  0 x2 y2 1
             x3 y3 1 0  0  1
             0  0  0 x3 y3 1
    
        X = [Affine11, Affine12, Affine13, Affine21, Affine22, Affine23]’
    
             u1 v1
        B =  u2 v2
             u3 v3 
    

    All you need to do is to add more points. To make Solve(A, B, X) work on over-determined system add DECOMP_SVD parameter. To see the powerpoint slides on the topic, use this link. If you’d like to learn more about the pseudo-inverse in the context of computer vision, the best source is: ComputerVision, see chapter 15 and appendix C.

    If you are still unsure how to add more points see my code below:

    // extension for n points;
    cv::Mat getAffineTransformOverdetermined( const Point2f src[], const Point2f dst[], int n )
    {
        Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data); // output
        double* a = (double*)malloc(12*n*sizeof(double));
        double* b = (double*)malloc(2*n*sizeof(double));
        Mat A(2*n, 6, CV_64F, a), B(2*n, 1, CV_64F, b); // input
    
        for( int i = 0; i < n; i++ )
        {
            int j = i*12;   // 2 equations (in x, y) with 6 members: skip 12 elements
            int k = i*12+6; // second equation: skip extra 6 elements
            a[j] = a[k+3] = src[i].x;
            a[j+1] = a[k+4] = src[i].y;
            a[j+2] = a[k+5] = 1;
            a[j+3] = a[j+4] = a[j+5] = 0;
            a[k] = a[k+1] = a[k+2] = 0;
            b[i*2] = dst[i].x;
            b[i*2+1] = dst[i].y;
        }
    
        solve( A, B, X, DECOMP_SVD );
        delete a;
        delete b;
        return M;
    }
    
    // call original transform
    vector src(3);
    vector dst(3);
    src[0] = Point2f(0.0, 0.0);src[1] = Point2f(1.0, 0.0);src[2] = Point2f(0.0, 1.0);
    dst[0] = Point2f(0.0, 0.0);dst[1] = Point2f(1.0, 0.0);dst[2] = Point2f(0.0, 1.0);
    Mat M = getAffineTransform(Mat(src), Mat(dst));
    cout<

提交回复
热议问题