Here are the three basic data structures for creating and applying a homography: CvMat* src_points; CvMat* dst_points; CvMat* homography; Here are the initial values I gave them: src_points = 0; // in the constructor dst_points = 0; homography = 0; Here is an excerpt of commented code that illustrates one way to use them: // first, see if the matrices exist // if they don't exist create them // the call to release src_points is cvReleaseMat( &src_points ); // since we will reuse these matrices, we will not release them // see if they're null (they are initialized to null, so this should happen at least once) if (src_points == 0) src_points = cvCreateMat( 4 /* rows */, 2 /* cols */, CV_32FC1 /* floating point, one channel */ ); if (dst_points == 0) dst_points = cvCreateMat( 4 /* rows */, 2 /* cols */, CV_32FC1 /* floating point, one channel */ ); // NOTE that both of the above matrices are simply collections of correspnding points ! // because number_of_columns == 2, we are providing _raw_ point coordinates (not homogeneous) // also, you're not limited to four pairs (though four are required) // this next matrix, on the other hand, does need to be 3x3 if (homography == 0) homography = cvCreateMat( 3 /* rows */, 3 /* cols */, CV_32FC1 /* floating point, one channel */ ); // now, fill in the points (we use hand-typed values, though an interface in which mouse-clicks // are used would be more general and convenient!) // the bounds-checking version of getting and setting elements are called // cvGetReal2D and cvSetReal2D (also available for arbitrary elements without the "Real") // However, the calls cvmSet and cvmGet are faster because they do not do bounds checking // and are in-line. So, if you know the bounds, they're probably the thing to use... cvmSet( src_points, 0, 0, 0.0 ); // row, col, value to place there cvmSet( src_points, 0, 1, 0.0 ); // point zero is (0,0) cvmSet( src_points, 1, 0, 100.0 ); // point one is (100,0) cvmSet( src_points, 1, 1, 0.0 ); cvmSet( src_points, 2, 0, 0.0 ); // point two is (0,100) cvmSet( src_points, 2, 1, 100.0 ); cvmSet( src_points, 3, 0, 100.0 ); // point three is (100,100) cvmSet( src_points, 3, 1, 100.0 ); double cornerValue = 99; cvmSet( dst_points, 0, 0, 0.0 ); // row, col, value to place there cvmSet( dst_points, 0, 1, 0.0 ); // point zero is (0,0) cvmSet( dst_points, 1, 0, 100.0 ); // point one is (100,0) cvmSet( dst_points, 1, 1, 0.0 ); cvmSet( dst_points, 2, 0, 0.0 ); // point two is (0,100) cvmSet( dst_points, 2, 1, 100.0 ); cvmSet( dst_points, 3, 0, cornerValue ); // point three is (cornerValue,cornerValue) cvmSet( dst_points, 3, 1, cornerValue ); // print a value just to show that we can grab one double grabbedCornerValue = cvmGet( dst_points, 3, 0 ); printf("grabbedCornerValue is %lf\n", grabbedCornerValue); // call the find homography function cvFindHomography( src_points, dst_points, homography ); // print out the result printf("This homography should be the identity 3x3 matrix:\n"); for (int row=0 ; row<3 ; ++row) { for (int col=0 ; col<3 ; ++col) { printf(" %10.6lf ", cvmGet( homography, row, col ) ); } printf("\n"); } printf("\n"); // now let's run the inputImage through the homography // interpolation options: CV_INTER_NN (nearest neighbors), CV_INTER_LINEAR (bilinear, used by default) // CV_INTER_AREA (using "pixel area relation"), and CV_INTER_CUBIC (bicubic) cvWarpPerspective( inputImage, outputImage, homography, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(128) /* not sure how to specify colors... */ );