Recommended way to compose rotations - c++

I have 2 rotations represented as yaw, pitch, roll (Tait-Brian intrinsic right-handed). What is the recommended way to construct a single rotation that is equivalent to both of them?
EDIT: if I understand correctly from the answers, I must first convert yaw, pitch, roll to either matrix or quaternion, compose them and then transform the result back to yaw, pitch, roll representation.
Also, my first priority is simplicity, then numerical stability and efficiency.
Thanks :)

As a general answer, if you make a rotation matrix for each of the two rotations, you can then make a single matrix which is the product of the two (order is important!) to represent the effect of applying both rotations.
It is possible to conceive of instances where "gimbal lock" could make this numerically unstable for certain angles (typically involving angles very close to 90 degrees).
It is faster and more stable to use quaternions. You can see a nice treatment at http://www.genesis3d.com/~kdtop/Quaternions-UsingToRepresentRotation.htm - in summary, every rotation can be represented by a quaternion and multiple rotations are just represented by the product of the quaternions. They tend to have better stability properties.
Formulas for doing this can be found at http://en.m.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
UPDATE using the formulas provided at http://planning.cs.uiuc.edu/node102.html , you can adapt the following code to do a sequence of rotations. While the code is written in (and compiles as ) C++, I am not taking advantage of certain built in C++ types and methods that might make this code more elegant - showing my C roots here. The point is really to show how the rotation equations work, and how you can concatenate multiple rotations.
The two key functions are calcRot which computes the rotation matrix for given yaw, pitch and roll; and mMult which multiplies two matrices together. When you have two successive rotations, the product of their rotation matrices is the "composite" rotation - you do have to watch out for the order in which you do things. The example that I used shows this. First I rotate a vector by two separate rotations; then I compute a single matrix that combines both rotations and get the same result; finally I reverse the order of the rotations, and get a different result. All of which should help you solve your problem.
Make sure that the conventions I used make sense for you.
#include <iostream>
#include <cmath>
#define PI (2.0*acos(0.0))
//#define DEBUG
void calcRot(double ypr[3], double M[3][3]) {
// extrinsic rotations: using the world frame of reference
// ypr: yaw, pitch, roll in radians
double cy, sy, cp, sp, cr, sr;
// compute sin and cos of each just once:
cy = cos(ypr[0]);
sy = sin(ypr[0]);
cp = cos(ypr[1]);
sp = sin(ypr[1]);
cr = cos(ypr[2]);
sr = sin(ypr[2]);
// compute this rotation matrix:
// source: http://planning.cs.uiuc.edu/node102.html
M[0][0] = cy*cp;
M[0][1] = cy*sp*sr - sy*cr;
M[0][2] = cy*sp*cr + sy*sr;
M[1][0] = sy*cp;
M[1][1] = sy*sp*sr + cy*cr;
M[1][2] = sy*sp*sr - cy*sr;
M[2][0] = -sp;
M[2][1] = cp*sr;
M[2][2] = cp*cr;
}
void mMult(double M[3][3], double R[3][3]) {
// multiply M * R, returning result in M
double T[3][3] = {0};
for(int ii = 0; ii < 3; ii++) {
for(int jj = 0; jj < 3; jj++) {
for(int kk = 0; kk < 3; kk++ ) {
T[ii][jj] += M[ii][kk] * R[kk][jj];
}
}
}
// copy the result:
for(int ii = 0; ii < 3; ii++) {
for(int jj = 0; jj < 3; jj++ ) {
M[ii][jj] = T[ii][jj];
}
}
}
void printRotMat(double M[3][3]) {
// print 3x3 matrix - for debug purposes
#ifdef DEBUG
std::cout << "rotation matrix is: " << std::endl;
for(int ii = 0; ii < 3; ii++) {
for(int jj = 0; jj < 3; jj++ ) {
std::cout << M[ii][jj] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
#endif
}
void applyRot(double before[3], double after[3], double M[3][3]) {
// apply rotation matrix M to vector 'before'
// returning result in vector 'after'
double sumBefore = 0, sumAfter = 0;
std::cout << "Result of rotation:" << std::endl;
for(int ii = 0; ii < 3; ii++) {
std::cout << before[ii] << " -> ";
sumBefore += before[ii] * before[ii];
after[ii] = 0;
for( int jj = 0; jj < 3; jj++) {
after[ii] += M[ii][jj]*before[jj];
}
sumAfter += after[ii] * after[ii];
std::cout << after[ii] << std::endl;
}
std::cout << std::endl;
#ifdef DEBUG
std::cout << "length before: " << sqrt(sumBefore) << "; after: " << sqrt(sumAfter) << std::endl;
#endif
}
int main(void) {
double r1[3] = {0, 0, PI/2}; // order: yaw, pitch, roll
double r2[3] = {0, PI/2, 0};
double initPoint[3] = {3,4,5}; // initial point before rotation
double rotPoint[3], rotPoint2[3];
// initialize rotation matrix to I
double R[3][3];
double R2[3][3];
// compute first rotation matrix in-place:
calcRot(r1, R);
printRotMat(R);
applyRot(initPoint, rotPoint, R);
// apply second rotation on top of first:
calcRot(r2, R2);
std::cout << std::endl << "second rotation matrix: " << std::endl;
printRotMat(R2);
// applying second matrix to result of first rotation:
std::cout << std::endl << "applying just the second matrix to result of first: " << std::endl;
applyRot(rotPoint, rotPoint2, R2);
mMult(R2, R);
std::cout << "after multiplication: " << std::endl;
printRotMat(R2);
std::cout << "Applying the combined matrix to the intial vector: " << std::endl;
applyRot(initPoint, rotPoint2, R2);
// now in the opposite order:
double S[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
calcRot(r2, S);
printRotMat(S);
calcRot(r1, R2);
mMult(R2, S);
std::cout << "applying rotation in the opposite order: " << std::endl;
printRotMat(R2);
applyRot(initPoint, rotPoint, R2);
}
Output (with #DEBUG not defined - commented out):
Result of rotation:
3 -> 3
4 -> -5
5 -> 4
second rotation matrix:
applying just the second matrix to result of first:
Result of rotation:
3 -> 4
-5 -> -5
4 -> -3
after multiplication:
Applying the combined matrix to the intial vector:
Result of rotation:
3 -> 4
4 -> -5
5 -> -3
Note that these last two give the same result, showing that you can combine rotation matrices.
applying rotation in the opposite order:
Result of rotation:
3 -> 5
4 -> 3
5 -> 4
Now the result is different - the order is important.

If you are familiar with matrix operations, you may try Rodrigues' rotation formula. If you are familiar with quaternions, you may try the P' = q*P*q' approach.
Quaterion math is a bit more complicated to grasp, but code is simpler and faster.

Related

Why doesn't my Gradient descent algorithm converge? (For Logistic Regression)

I have an assignment which says to implement logistic regression in c++ using gradient descent. Part of the assignment is to make the gradient descent stop when the magnitude of the gradient is below 10e-07.
I have to minimize: //chart.googleapis.com/chart?cht=tx&chl=L(w)%20%3D%20%5Cfrac%7B1%7D%7BN%7D%5Csum%20log(1%20%2B%20exp(-y_%7Bi%7Dw%5E%7BT%7Dx_%7Bi%7D))
However my gradient descent keeps stopping due to max iterations surpassed. I have tried with various max iteration thresholds, and they all max out. I think there is something wrong with my code, since logistic regression is supposedly an easy task for gradient descent due to the concave nature of its cost function, the gradient descent should easily find the minium.
I am using the armadillo library for matrices and vectors.
#include "armadillo.hpp"
using namespace arma;
double Log_Likelihood(Mat<double>& x, Mat<int>& y, Mat<double>& w)
{
Mat<double> L;
double L_sum = 0;
for (int i = 0; i < x.n_rows; i++)
{
L = log(1 + exp(-y[i] * w * x.row(i).t() ));
L_sum += as_scalar(L);
}
return L_sum / x.n_rows;
}
Mat<double> Gradient(Mat<double>& x, Mat<int>& y, Mat<double>& w)
{
Mat<double> grad(1, x.n_cols);
for (int i = 0; i < x.n_rows; i++)
{
grad = grad + (y[i] * (1 / (1 + exp(y[i] * w * x.row(i).t()))) * x.row(i));
}
return -grad / x.n_rows;
}
void fit(Mat<double>& x, Mat<int>& y, double alpha = 0.05, double threshold = pow(10, -7), int maxiter = 10000)
{
w.set_size(1, x.n_cols);
w = x.row(0);
int iter = 0;
double log_like = 0;
while (true)
{
log_like = Log_Likelihood(x, y, w);
if (iter % 1000 == 0)
{
std::cout << "Iter: " << iter << " -Log likelihood = " << log_like << " ||dL/dw|| = " << norm( Gradient(x, y, w), 2) << std::endl;
}
iter++;
if ( norm( Gradient(x, y, w), 2) < threshold)
{
std::cout << "Magnitude of gradient below threshold." << std::endl;
break;
}
if (iter == maxiter)
{
std::cout << "Max iterations surpassed." << std::endl;
break;
}
w = w - (alpha * Gradient(x, y, w));
}
}
I want the gradient descent to stop because the magnitude of the gradient falls below 10e-07.
My labels are {1, -1}.
Verify that your loglikelihood is increasing towards convergence by recording or plotting the values at every iteration, and also check that the norm of the gradient is going towards 0. You should be doing gradient ascent, so add the gradient instead of subtracting it. If the norm of the gradient consistently increases it means you are not going in a direction towards the optimum. If on the other hand, the norm of the gradient "jumps around" but doesn't go to 0, then you should reduce your stepsize/learning rate alpha and try again.
Plotting and analyzing these values will be helpful to debug and analyze your algorithm.

Calculating 3D cartesian coordinates inside a cone

So what I am essentially trying to do here is arranging the 3D cartesian coordinates of points inside an inverted cone (radius decreases with height). The basic approach I have taken here is to have an integrally reducing height, h, and plotting points (x,y) that fall within a circle formed at height h. Since the radius of this circle is variable, I am using a simple similarity condition to determine that at every iteration. The initial height I have taken is 1000, the radius ought to initially be 3500. Also, these circles as centred at (0,0) [the z-axis passes through the vertex of the cone, and is perpendicular to the base]. Code isn't running properly, showing me an exit status of -1. Can anyone help me figure out if my implementation is off due to some size errors or something?
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
int main(){
float top[1010][9000][3];
ll i = 0;
for(ll h = 999; h >=0; h--){
float r=(h+1)*(3.5);
for (ll x = floor(r) * (-1); x <= floor(r); x++){
for (ll y = floor(r) *(-1); y <= floor(r); y++){
if(pow(x,2) + pow(y,2) <= pow(floor(r),2)){
top[h][i][0] = x;
top[h][i][1] = y;
top[h][i][2] = 9.8;
i++;
}
}
}
i=0;
}
cout << "done";
for (ll m = 0; m < 1000; m++){
for(ll n = 0; n < 7000; n++){
if(top[m][n][2] == 9.8){
cout << top[m][n][0] << top[m][n][1];
}
}
}
}
You don't need to declare ll as long long int. The indexes you are using will fit inside of int.
Here's your problem: Change the code to this to see what's going on:
for(ll h = 999; h >=0; h--){
float r=(h+1)*(3.5);
for (ll x = floor(r) * (-1); x <= floor(r); x++){
for (ll y = floor(r) *(-1); y <= floor(r); y++){
if(pow(x,2) + pow(y,2) <= pow(floor(r),2)){
/* top[h][i][0] = x;
top[h][i][1] = y;
top[h][i][2] = 9.8; //*/
i++; // this gets really big
}
}
}
cout << "max i: " << i << endl;
i=0;
}
i gets really big and is indexing into a dimension that is only 9000.
Criticism of the code...
It looks like you are scanning the entire x,y,z block and 'testing' if the point is inside. If yes, saving the x,y coordinate of the point along with 9.8 (some field value?).
Perhaps you could forgo the float buffer and just print the {x,y} coordinates directly to see how your code works before attempting to save the output. redirect the output to a file and inspect.
cout << "{" << x << "," << y <<"}," << (i % 5 == 0 ? "\n" : " ");
Also, read up on why comparing floats with == doesn't work.

Gram-Schmidt Orthogonalization incorrect implementation

I'm in the process of building a free open source OpenGL3-based 3D game engine (it's not a school assignment, rather it's for personal skill development and to give something back to the open source community). I've reached the stage where I need to learn lots of related math, so I'm reading a great textbook called "Mathematics for 3D Game Programming and Computer Graphics, 3rd Edition".
I've hit a snag early on trying to do the book's exercises though, as my attempt at implementing the "Gram-Schmidt Orthogonalization algorithm" in C++ is outputting a wrong answer. I'm no math expert (although I'm trying to get better), and I have very limited experience looking at a math algorithm and translating it into code (limited to some stuff I learned from Udacity.com). Anyway, it would really help if someone could look at my incorrect code and give me a hint or a solution.
Here it is:
/*
The Gram-Schmidt Orthogonalization algorithm is as follows:
Given a set of n linearly independent vectors Beta = {e_1, e_2, ..., e_n},
the algorithm produces a set Beta' = {e_1', e_2', ..., e_n'} such that
dot(e_i', e_j') = 0 whenever i != j.
A. Set e_1' = e_1
B. Begin with the index i = 2 and k = 1
C. Subtract the projection of e, onto the vectors e_1', e_2', ..., e_(i-1)'
from e_i, and store the result in e_i', That is,
dot(e_i, e_k')
e_i' = e_i - sum_over(-------------- e_k')
e_k'^2
D. If i < n, increment i and loop back to step C.
*/
#include <iostream>
#include <glm/glm.hpp>
glm::vec3 sum_over_e(glm::vec3* e, glm::vec3* e_prime, int& i)
{
int k = 0;
glm::vec3 result;
while (k < i-2)
{
glm::vec3 e_prime_k_squared(pow(e_prime[k].x, 2), pow(e_prime[k].y, 2), pow(e_prime[k].z, 2));
result += (glm::dot(e[i], e_prime[k]) / e_prime_k_squared) * e_prime[k];
k++;
}
return result;
}
int main(int argc, char** argv)
{
int n = 2; // number of vectors we're working with
glm::vec3 e[] = {
glm::vec3(sqrt(2)/2, sqrt(2)/2, 0),
glm::vec3(-1, 1, -1),
glm::vec3(0, -2, -2)
};
glm::vec3 e_prime[n];
e_prime[0] = e[0]; // step A
int i = 0; // step B
do // step C
{
e_prime[i] = e[i] - sum_over_e(e, e_prime, i);
i++; // step D
} while (i-1 < n);
for (int loop_count = 0; loop_count <= n; loop_count++)
{
std::cout << "Vector e_prime_" << loop_count+1 << ": < "
<< e_prime[loop_count].x << ", "
<< e_prime[loop_count].y << ", "
<< e_prime[loop_count].z << " >" << std::endl;
}
return 0;
}
This code outputs:
Vector e_prime_1: < 0.707107, 0.707107, 0 >
Vector e_prime_2: < -1, 1, -1 >
Vector e_prime_3: < 0, -2, -2 >
but the correct answer is supposed to be:
Vector e_prime_1: < 0.707107, 0.707107, 0 >
Vector e_prime_2: < -1, 1, -1 >
Vector e_prime_3: < 1, -1, -2 >
Edit: Here's the code that produces the correct answer:
#include <iostream>
#include <glm/glm.hpp>
glm::vec3 sum_over_e(glm::vec3* e, glm::vec3* e_prime, int& i)
{
int k = 0;
glm::vec3 result;
while (k < i-1)
{
float e_prime_k_squared = glm::dot(e_prime[k], e_prime[k]);
result += ((glm::dot(e[i], e_prime[k]) / e_prime_k_squared) * e_prime[k]);
k++;
}
return result;
}
int main(int argc, char** argv)
{
int n = 3; // number of vectors we're working with
glm::vec3 e[] = {
glm::vec3(sqrt(2)/2, sqrt(2)/2, 0),
glm::vec3(-1, 1, -1),
glm::vec3(0, -2, -2)
};
glm::vec3 e_prime[n];
e_prime[0] = e[0]; // step A
int i = 0; // step B
do // step C
{
e_prime[i] = e[i] - sum_over_e(e, e_prime, i);
i++; // step D
} while (i < n);
for (int loop_count = 0; loop_count < n; loop_count++)
{
std::cout << "Vector e_prime_" << loop_count+1 << ": < "
<< e_prime[loop_count].x << ", "
<< e_prime[loop_count].y << ", "
<< e_prime[loop_count].z << " >" << std::endl;
}
return 0;
}
The problem is probably in the way you define e_k'^2. As far as vector math goes, the square of a vector is usually taken to be the square of its norm. Therefore,
double e_prime_k_squared = glm::dot(e_prime_k, e_prime_k);
Moreover, dividing by a vector is undefined (I wonder why GLM allows it?), so if e_k'^2 is a vector, the whole thing is undefined.

How to iterate through a rotated grid

I would like to be able to iterate through the grid elements with a set step size. The fun part of this problem is that the grid will be rotated. I have developed an algorithm to do this and it is successful for some cases. The image below specifies the problem:
The conditions of the problem are that a grid spacing will be provided that is a factor of the grid length and width (As a side note the grid can be rectangular). The Algorithm must iterate through the grid and print out where it is. Here is some code and an example of it working:
int main() {
vector< vector<double> > bound;
vector<double> point;
point.push_back(0);
point.push_back(4);
bound.push_back(point);
point[0] = 6; point[1] = 10;
bound.push_back(point);
point[0] = 4; point[1] = 0;
bound.push_back(point);
point[0] = 10; point[1] = 6;
bound.push_back(point);
double d = 0.5;
double x, y;
int countx = 0, county = 0;
for (double i = bound[0][0]; i < bound[2][0]; i+=d) {
//std::cout << "I: " << i << std::endl;
for (double j = bound[0][1]; j < bound[1][1]; j+=d) {
//std::cout << "J: " << j << std::endl;
x = i+d+(double)county*d;
y = j-(double)countx*d;
++county;
std::cout << "i, j, x and y: " << i << "\t" << j << "\t" << x << "\t" << y << std::endl;
}
std::cout << "new Row--------------------\n";
++countx;
county = 0;
}
}
The code above works and prints correctly the grid elements, ie:
x and y: 4, 0.5
x and y: 4.5, 1
etc.
However when trying a rectangle with bounds:
[(0.5, 6), (3, 8.5), (5.5, 1), (8, 3.5)]
and a step size (d) of 1
It iterates to outside the rectangle bounds. I can see why this is happening, the iterator condition in the for loop will not contain it because of the extra +d.
My question is, is there a better way to approach this problem and how would i go about it?
Does anyone know if this has been implemented before and has some source code?
Cheers for the help.
Ben
The Way I ended up going about it was to calculate the length and width of the rectangle by Pythagoras rule on two of the sides. I then made a grid on a virtual rectangle which is aligned with its bottom corner at the origin. Then by using a pre-developed library for matrix rotations and translations, I transformed the points individually by translating them to by the displacement to the bottom left corner and rotating them to the calculated angle of the rectangle.
This is similar to the above solution but uses a full transformation matrix. The answer ended up being simpler then I thought it would be.
Thanks for the help.

Camera motion compensation

I am using openCV to implementing camera motion compensation for an application. I know I need to calculate the optical flow and then find the fundamental matrix between two frames to transform the image.
Here is what I have done so far:
void VideoStabilization::stabilize(Image *image) {
if (image->getWidth() != width || image->getHeight() != height) reset(image->getWidth(), image->getHeight());
IplImage *currImage = toCVImage(image);
IplImage *currImageGray = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
cvCvtColor(currImage, currImageGray, CV_BGRA2GRAY);
if (baseImage) {
CvPoint2D32f currFeatures[MAX_CORNERS];
char featuresFound[MAX_CORNERS];
opticalFlow(currImageGray, currFeatures, featuresFound);
IplImage *result = transformImage(currImage, currFeatures, featuresFound);
if (result) {
updateImage(image, result);
cvReleaseImage(&result);
}
}
cvReleaseImage(&currImage);
if (baseImage) cvReleaseImage(&baseImage);
baseImage = currImageGray;
updateGoodFeatures();
}
void VideoStabilization::updateGoodFeatures() {
const double QUALITY_LEVEL = 0.05;
const double MIN_DISTANCE = 5.0;
baseFeaturesCount = MAX_CORNERS;
cvGoodFeaturesToTrack(baseImage, eigImage,
tempImage, baseFeatures, &baseFeaturesCount, QUALITY_LEVEL, MIN_DISTANCE);
cvFindCornerSubPix(baseImage, baseFeatures, baseFeaturesCount,
cvSize(10, 10), cvSize(-1,-1), TERM_CRITERIA);
}
void VideoStabilization::opticalFlow(IplImage *currImage, CvPoint2D32f *currFeatures, char *featuresFound) {
const unsigned int WIN_SIZE = 15;
const unsigned int PYR_LEVEL = 5;
cvCalcOpticalFlowPyrLK(baseImage, currImage,
NULL, NULL,
baseFeatures,
currFeatures,
baseFeaturesCount,
cvSize(WIN_SIZE, WIN_SIZE),
PYR_LEVEL,
featuresFound,
NULL,
TERM_CRITERIA,
0);
}
IplImage *VideoStabilization::transformImage(IplImage *image, CvPoint2D32f *features, char *featuresFound) const {
unsigned int featuresFoundCount = 0;
for (unsigned int i = 0; i < MAX_CORNERS; ++i) {
if (featuresFound[i]) ++featuresFoundCount;
}
if (featuresFoundCount < 8) {
std::cout << "Not enough features found." << std::endl;
return NULL;
}
CvMat *points1 = cvCreateMat(2, featuresFoundCount, CV_32F);
CvMat *points2 = cvCreateMat(2, featuresFoundCount, CV_32F);
CvMat *fundamentalMatrix = cvCreateMat(3, 3, CV_32F);
unsigned int pos = 0;
for (unsigned int i = 0; i < featuresFoundCount; ++i) {
while (!featuresFound[pos]) ++pos;
cvSetReal2D(points1, 0, i, baseFeatures[pos].x);
cvSetReal2D(points1, 1, i, baseFeatures[pos].y);
cvSetReal2D(points2, 0, i, features[pos].x);
cvSetReal2D(points2, 1, i, features[pos].y);
++pos;
}
int fmCount = cvFindFundamentalMat(points1, points2, fundamentalMatrix, CV_FM_RANSAC, 1.0, 0.99);
if (fmCount < 1) {
std::cout << "Fundamental matrix not found." << std::endl;
return NULL;
}
std::cout << fundamentalMatrix->data.fl[0] << " " << fundamentalMatrix->data.fl[1] << " " << fundamentalMatrix->data.fl[2] << "\n";
std::cout << fundamentalMatrix->data.fl[3] << " " << fundamentalMatrix->data.fl[4] << " " << fundamentalMatrix->data.fl[5] << "\n";
std::cout << fundamentalMatrix->data.fl[6] << " " << fundamentalMatrix->data.fl[7] << " " << fundamentalMatrix->data.fl[8] << "\n";
cvReleaseMat(&points1);
cvReleaseMat(&points2);
IplImage *result = transformImage(image, *fundamentalMatrix);
cvReleaseMat(&fundamentalMatrix);
return result;
}
MAX_CORNERS is 100 and it usually find around 70-90 features.
With this code, I get a weird fundamental matrix, like:
-0.000190809 -0.00114947 1.2487
0.00127824 6.57727e-05 0.326055
-1.22443 -0.338243 1
Since I just hold the camera with my hand and try not to shake it (and there werent any objects moving), I expected the matrix to be close to identity. What am I doing wrong?
Also, I'm not sure what to use to transform the image. cvWarpAffine need a 2x3 matrix, should I discard the last row or use another function?
What you're looking for is not the fundamental matrix but rather an affine or perspective transform.
The fundamental matrix describes the relation of two cameras having significantly different viewpoints. It is calculated such that if you have two points x (on one image) and x' (on another) that are projections of the same point in space, then x F x' (the product) is zero. If x and x' are nearly identical... then the only solution is to make F nearly zero (and practically useless). That's why you've got what you have.
The matrix that should indeed be near identity is a transformation A that transforms the points x to x'= A x (the old image into the new one). Depending on what types of transformations you want to include (affine or perspective), you could (theoretically) use the functions cvGetAffineTransform or cvGetPerspectiveTransform to calculate the transform. For that, you would need 3 or 4 point pairs, respectively.
However, the best choice (I think) is cvFindHomograpy. It estimates a perspective transform based on all of the point pairs available, using outlier filtering algorithms (RANSAC, for example), giving you a 3x3 matrix.
Then you can use cvWarpPerspective to transform the images themselves.