33 #include <Image/HomographyMapping.hh>
34 #include <Image/AffineMapping.hh>
35 #include <Image/DisplacementMapping.hh>
36 #include <Base/Image/ImageIO.hh>
37 #include <Base/Debug/TimeMeasure.hh>
38 #include <Base/Math/Random.hh>
45 int main(
int argc,
char *argv[])
47 cout<<endl<<
"Usage: "<<argv[0]
48 <<
" [testimage [ width height [homography.mat]]]"<<endl<<endl;
49 cout<<
"If you dont provide a test image, I will generate one :-)"
54 BIASERR(
"error loading "<<argv[1]);
61 cout<<
"Reading HMatrix "<<argv[4]<<endl;
63 cout<<
"H is "<<H<<endl;
73 double angle = -45.0 / 180.0 * M_PI;
75 double angle2 = 3.0 / 180.0 * M_PI;
77 HRot[0][0]= cos(angle); HRot[0][1] = sin(angle);
78 HRot[1][0]= -sin(angle); HRot[1][1]= cos(angle);
81 HRot2[0][0]= cos(angle2); HRot2[0][1] = sin(angle2);
82 HRot2[1][0]= -sin(angle2); HRot2[1][1]= cos(angle2);
87 HScale[0][0] = 4.0; HScale[1][1] = 1.0;
90 H = HRot2 * HRot.Transpose() * HScale * HRot;
93 cout<<
"Using default homography "<<H<<endl;
97 cout<<
"Generating test image orig.mip"<<endl;
98 bool highFreqCross =
true;
102 Hinv *= 1.0 / H[2][2];
104 if (!im.IsEmpty()) im.Release();
118 BIASERR(
"error loading "<<argv[1]);
122 int width = im.GetWidth()/2;
123 int height = im.GetHeight()/2;
126 width = atoi(argv[2]);
127 height = atoi(argv[3]);
128 cout<<
"Using imagesize "<<width<<
" x "<<height<<endl;
130 cout<<
"Using input image size "<<width<<
" x "<<height<<endl;
134 HMove[0][2]= double(im.GetWidth())/-2.0;
135 HMove[1][2] =double(im.GetHeight())/-2.0;
136 HMove2[0][2]= double(width)/-2.0; HMove2[1][2] = double(height)/-2.0;
138 H = HMoveInv * H * HMove2;
139 cout<<
"ROI of source image is "<<*im.GetROI()
140 <<
" while image size is "<<width<<
" x "<<height<<endl;
154 imresnearest (width, height, im.GetChannelCount()),
155 imresbilinear (width, height, im.GetChannelCount()),
156 imrestrilinear (width, height, im.GetChannelCount()),
158 imresnearest_dismap (width, height, im.GetChannelCount()),
160 imresnearest_lookup (width, height, im.GetChannelCount()),
161 imresbilinear_lookup (width, height, im.GetChannelCount()),
162 imrestrilinear_lookup (width, height, im.GetChannelCount()),
164 imresbicubic (width, height, im.GetChannelCount()),
165 imresanisotropic (width, height, im.GetChannelCount()),
166 imresdirect (width, height, im.GetChannelCount());
168 unsigned char *color =
new unsigned char[im.GetChannelCount()];
169 for(
unsigned int i=0;i<im.GetChannelCount();i++) color[i]=(
unsigned char)255;
172 imresbilinear.FillImageWithConstValue(color);
173 imrestrilinear.FillImageWithConstValue(color);
174 imresnearest_dismap.FillImageWithConstValue(color);
175 imresnearest_lookup.FillImageWithConstValue(color);
176 imresbilinear_lookup.FillImageWithConstValue(color);
177 imrestrilinear_lookup.FillImageWithConstValue(color);
178 imresbicubic.FillImageWithConstValue(color);
179 imresanisotropic.FillImageWithConstValue(color);
180 imresdirect.FillImageWithConstValue(color);
185 NN_dismap (width, height, 3);
188 Mapper.SetAffineTransformation(H[0][0],H[0][1],H[1][0], H[1][1],
198 Mapper.MapDirect(im, imresdirect);
206 unsigned char* Data = imresnearest_dismap.GetImageData();
209 int counter_index = 0;
210 double bias_x, bias_y;
212 for(
unsigned int j = 0; j < imresnearest_dismap.GetHeight(); j++){
213 for(
unsigned int i = 0; i < imresnearest_dismap.GetWidth(); i++){
222 im.TextureToBIASCoordinates(p_src[0], p_src[1], bias_x, bias_y);
242 int p_x = (int)rint(bias_x);
243 int p_y = (int)rint(bias_y);
244 int p_z = (int)(p_src[2]);
248 p_x < (
int)im.GetWidth() &&
250 p_y < (int)im.GetHeight()){
251 counter_index = im.GetWidth()*p_y + p_x;
252 *Data++ =(
unsigned char)im.GetImageData()[counter_index];
255 *Data++ = (
unsigned char)(0);
262 cout<<
"timing ..."<<endl<<flush;
263 unsigned int numbermeasurements = 1;
267 for (
unsigned int i=0; i<numbermeasurements; i++) {
303 BIASWARN(
"Anisoptropic filtering causes double free or corruption error.")
332 Mapper.MapDirect(im, imresdirect);
338 cout <<
"Anisotropic mapping took "
342 <<
"Bicubic mapping took "
346 <<
"NN-mapping (no lookups) took "
349 <<
"NN-mapping (wt lookups) init took "
350 <<t1l_init.
GetUserTime()/double(numbermeasurements)
352 <<
"NN-mapping (wt lookups) took "
356 <<
"Bilinear mapping (no lookups) took "
359 <<
"Bilinear mapping (wt lookups) init took "
360 <<t2l_init.
GetUserTime()/double(numbermeasurements)
362 <<
"Bilinear mapping (wt lookups) took "
366 <<
"Trilinear mapping (no lookups) took "
369 <<
"Trilinear mapping (wt lookups) init took "
370 <<t4l_init.
GetUserTime()/double(numbermeasurements)
372 <<
"Trilinear mapping (wt lookups) took "
376 <<
"Direct affine took "
377 <<t6.
GetUserTime()/double(numbermeasurements)<<
" ms"
382 if (
ImageIO::Save(
"image_homography_anisotropic.mip", imresanisotropic)!=0){
383 BIASERR(
"error image");
387 if (
ImageIO::Save(
"image_homography_trilinear.mip", imrestrilinear)!=0){
388 BIASERR(
"error image");
394 imrestrilinear_lookup)!=0){
395 BIASERR(
"error image");
399 if (
ImageIO::Save(
"image_homography_bicubic.mip", imresbicubic)!=0){
400 BIASERR(
"error image");
404 if (
ImageIO::Save(
"image_homography_bilinear.mip", imresbilinear)!=0){
405 BIASERR(
"error image");
411 imresbilinear_lookup)!=0){
412 BIASERR(
"error image");
416 if (
ImageIO::Save(
"image_homography_nearest.mip", imresnearest)!=0){
417 BIASERR(
"error image");
423 imresnearest_lookup)!=0){
424 BIASERR(
"error image");
430 imresnearest_dismap)!=0){
431 BIASERR(
"error image");
436 BIASERR(
"error image");
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
a 3x3 Matrix describing projective transformations between planes
Maps image src to image sink with homography H (software implementation)
int SetDisplacementMap(Image< float > &dismap)
virtual int GetSourceCoordinates_(const HomgPoint2D &sink, HomgPoint2D &source) const
reimplementation for homography, takes sink and computes coords in source taking the values from disp...
Maps image src to image sink with displacement mapl generated by backwardmapping method.
int GetInverse(Matrix3x3< T > &inv) const
Matrix inversion: inverts this and stores resulty in argument inv.
int Map(const Image< InputStorageType > &src, Image< OutputStorageType > &sink, InterpolationMethod=MapTrilinear, bool newSink=false, double SuperSampling=1.0)
backward mapping with various interpolations
int PrepareLookupTableMapping(const Image< InputStorageType > &src, Image< OutputStorageType > &sink, InterpolationMethod method, bool newSink=false)
precomputes lookup coordinates for accessing src
bool Load(const std::string &fname)
Maps image src to image sink with affine transformation.
static void GenerateTestImage(Image< InputStorageType > &testimage, bool highFrequencyCross=true, InputStorageType dark=5, InputStorageType bright=127, const Matrix3x3< double > &Hinv=Matrix3x3< double >(MatrixIdentity))
generates a siemens star like test image with lots of different frequencies to test backward mapping ...
void FillImageWithConstValue(StorageType Value)
fill grey images
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
int MapWithLookupTable(const Image< InputStorageType > &src, Image< OutputStorageType > &sink, InterpolationMethod method)
applies precomputed coordinates in src, fast for repeated usages of same mapping function ...
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
int GetDisplacementMap(Image< float > &dismap, int width, int height)
precomputes lookup coordinates and computes displacement map int TEXTURE coordinates, according to the size of src (or width,height)
void SetHomography(const HMatrix &H)
set your homography H (source = H * sink) before calling Map()
double GetUserTime() const
return user time (=system usage time) in msec JW For Win32: user-time is the sum over all processes o...
class for producing random numbers from different distributions
class TimeMeasure contains functions for timing real time and cpu time.