topical media & game development
basic-visual-04-warping.c
? /
basic-visual-04-warping.c
// ------------------------------------------------------------------------
// This program is complementary material for the book:
//
// Frank Nielsen
//
// Visual Computing: Geometry, Graphics, and Vision
//
// ISBN: 1-58450-427-7
//
// Charles River Media, Inc.
//
//
// All programs are available at www.charlesriver.com/visualcomputing/
//
// You may use this program for ACADEMIC and PERSONAL purposes ONLY.
//
//
// The use of this program in a commercial product requires EXPLICITLY
// written permission from the author. The author is NOT responsible or
// liable for damage or loss that may be caused by the use of this program.
//
// Copyright (c) 2005. Frank Nielsen. All rights reserved.
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// File: warping.cpp
//
// Description: forward and backward image warping
// ------------------------------------------------------------------------
include <stdafx.h>
include <fstream>
include <math.h>
using namespace std;
void SaveImagePPM(unsigned char * data, int w, int h, char * file);
unsigned char * LoadImagePPM(char *ifile, int &w, int &h);
char filenameinput[]="imagewarping.ppm";
char filenameforward[]="forwardwarping.ppm";
char filenamebackward[]="backwardwarping.ppm";
class Matrix{
public:
double array[3][3];
};
void inline MatrixPoint(Matrix H,double x,double y, double &xm, double &ym)
{
double xx,yy,zz;
xx=H.array[0][0]*x+H.array[0][1]*y+H.array[0][2];
yy=H.array[1][0]*x+H.array[1][1]*y+H.array[1][2];
zz=H.array[2][0]*x+H.array[2][1]*y+H.array[2][2];
xm=xx/zz;ym=yy/zz;
}
void InverseMatrix(Matrix M, Matrix &Minv)
{
double t4 = M.array[0][0] * M.array[1][1];
double t6 = M.array[0][0] * M.array[1][2];
double t8 = M.array[0][1] * M.array[1][0];
double t10 = M.array[0][2] * M.array[1][0];
double t12 = M.array[0][1] * M.array[2][0];
double t14 = M.array[0][2] * M.array[2][0];
double t17 = 1.0 / ( t4 * M.array[2][2] - t6 * M.array[2][1] - t8 * M.array[2][2] +
t10 * M.array[2][1] + t12 * M.array[1][2] - t14 * M.array[1][1]);
Minv.array[0][0] = (M.array[1][1] * M.array[2][2] - M.array[1][2] * M.array[2][1]) * t17;
Minv.array[0][1] = -(M.array[0][1] * M.array[2][2] - M.array[0][2] * M.array[2][1]) * t17;
Minv.array[0][2] = (M.array[0][1] * M.array[1][2] - M.array[0][2] * M.array[1][1]) * t17;
Minv.array[1][0] = -(M.array[1][0] * M.array[2][2] - M.array[1][2] * M.array[2][0]) * t17;
Minv.array[1][1] = (M.array[0][0] * M.array[2][2] - t14) * t17;
Minv.array[1][2] = -(t6 - t10) * t17;
Minv.array[2][0] = (M.array[1][0] * M.array[2][1] - M.array[1][1] * M.array[2][0]) * t17;
Minv.array[2][1] = -(M.array[0][0] * M.array[2][1] - t12) * t17;
Minv.array[2][2] = (t4 - t8) * t17;
}
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char * img, * imgd;
int indexuv, indexxy;
int w,h;
int u,v,x,y;
double xreal,yreal,ureal,vreal;
Matrix T, Tinv;
cout<<"Visual Computing: Geometry, Graphics, and Vision (ISBN:1-58450-427-7)"<<endl;
cout<<"Demo program\n\n"<<endl;
cout<<"Forward/backward image mapping."<<endl;
T.array[0][0]=1.3; T.array[0][1]=0.0; T.array[0][2]=0.0;
T.array[1][0]=0.2; T.array[1][1]=0.9; T.array[1][2]=0.0;
T.array[2][0]=0.0; T.array[2][1]=0.0; T.array[2][2]=1.0;
InverseMatrix(T,Tinv);
img=LoadImagePPM(filenameinput,w,h);
imgd=new unsigned char [3*w*h];
memset(imgd,255,w*h*3); // background color
// Forward mapping from xy to uv
for(x=0;x<w;x++)
for(y=0;y<h;y++)
{
MatrixPoint(T,x,y,ureal,vreal);
// Roundings
u=(int)ureal;v=(int)vreal;
if ((u>=0)&&(u<w)&&(v>0)&&(v<h))
{
indexuv=3*(u+v*w);
indexxy=3*(y*w+x);
imgd[indexuv] =img[indexxy];
imgd[indexuv+1]=img[indexxy+1];
imgd[indexuv+2]=img[indexxy+2];
}
}
SaveImagePPM(imgd,w,h,filenameforward);
memset(imgd,255,w*h*3); // background color
// Backward mapping from uv to xy
for(u=0;u<w;u++)
for(v=0;v<h;v++)
{
MatrixPoint(Tinv,u,v,xreal,yreal);
x=(int)xreal;y=(int)yreal;
if ((x>=0)&&(x<w)&&(y>=0)&&(y<h))
{
indexuv=3*(u+v*w);
indexxy=3*(y*w+x);
imgd[indexuv]=img[indexxy];
imgd[indexuv+1]=img[indexxy+1];
imgd[indexuv+2]=img[indexxy+2];
}
}
SaveImagePPM(imgd,w,h,filenamebackward);
char line[256];
cout<<"Press Return key"<<endl;
gets(line);
delete [] imgd;
return 0;
}
// Save a PPM Image
void SaveImagePPM(unsigned char * data, int w, int h, char * file)
{
ofstream OUT(file, ios::binary);
if (OUT){
OUT << "P6" << endl << w << ' ' << h << endl << 255 << endl;
OUT.write((char *)data, 3*w*h);
OUT.close();}
}
// Load a PPM Image that does not contain comments.
unsigned char * LoadImagePPM(char *ifile, int &w, int &h)
{
char dummy1=0, dummy2=0; int maxc;
unsigned char * img;
ifstream IN(ifile, ios::binary);
IN.get(dummy1);IN.get(dummy2);
if ((dummy1!='P')&&(dummy2!='6')) {cerr<<"Not P6 PPM file"<<endl; return NULL;}
IN >> w >> h;
IN >> maxc;
IN.get(dummy1);
img=new unsigned char[3*w*h];
IN.read((char *)img, 3*w*h);
IN.close();
return img;
}
(C) Æliens
20/2/2008
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.