initial_homography_estimation_tester.cpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <iostream>
00003 #include <iomanip>
00004 
00005 #include <Eigen/Core>
00006 
00007 #include "../libfovis/initial_homography_estimation.hpp"
00008 #include <bot_core/bot_core.h>
00009 #include <bot_lcmgl_client/lcmgl.h>
00010 #include <GL/gl.h>
00011 
00012 using namespace std;
00013 
00014 #define dump(var) (cerr<<" "#var<<" =[\n"<< setprecision (3)<<var<<"];"<<endl)
00015 
00016 static Eigen::ArrayXf flattenMatrix(Eigen::MatrixXf &m)
00017 {
00018   return Eigen::Map<Eigen::ArrayXf>(m.data(), m.rows() * m.cols());
00019 }
00020 
00021 static void warpImage(const uint8_t * image, int width, int height, int rowstride, const Eigen::Matrix3f &H,
00022     uint8_t * warped_image)
00023 {
00024   //setup the utility matrices
00025   Eigen::MatrixXf x = Eigen::VectorXf::LinSpaced(width, 0, width - 1).transpose().replicate(height, 1);
00026   Eigen::MatrixXf y = Eigen::VectorXf::LinSpaced(height, 0, height - 1).replicate(1, width);
00027   Eigen::MatrixXf xx = flattenMatrix(x);
00028   Eigen::MatrixXf yy = flattenMatrix(y);
00029 
00030   Eigen::MatrixXf imageHomogeneousPoints(3, xx.rows());
00031   imageHomogeneousPoints.row(0) = xx.transpose();
00032   imageHomogeneousPoints.row(1) = yy.transpose();
00033   imageHomogeneousPoints.row(2).setOnes();
00034 
00035   Eigen::MatrixXf warpedHomogeneousPoints;
00036   warpedHomogeneousPoints = H * imageHomogeneousPoints;
00037 
00038   Eigen::MatrixXf warped = Eigen::MatrixXf(height, width);
00039 
00040   const double defaultValue = 128;
00041   //Bilinear interpolation
00042   for (int i = 0; i < warpedHomogeneousPoints.cols(); i++) {
00043     double val;
00044     Eigen::Vector2f pt = warpedHomogeneousPoints.col(i).head(2) / warpedHomogeneousPoints(2, i);
00045     Eigen::Vector2i fipt(floor(pt(0)), floor(pt(1)));
00046     Eigen::Vector2i cipt(ceil(pt(0)), ceil(pt(1)));
00047     if (0 <= pt(0) && pt(0) < width - 1 && 0 <= pt(1) && pt(1) < height - 1) {
00048       double x1 = pt(0) - fipt(0);
00049       double y1 = pt(1) - fipt(1);
00050       double x2 = 1 - x1;
00051       double y2 = 1 - y1;
00052       val = x2 * y2 * image[fipt(1) * rowstride + fipt(0)] + x1 * y2 * image[fipt(1) * rowstride + fipt(0) + 1] + x2
00053           * y1 * image[(fipt(1) + 1) * rowstride + fipt(0)] + x1 * y1 * image[(fipt(1) + 1) * rowstride + fipt(0) + 1];
00054 
00055     }
00056     else if (0 <= fipt(0) && fipt(0) < width && 0 <= fipt(1) && fipt(1) < height) {
00057       val = image[fipt(1) * rowstride + fipt(0)];
00058     }
00059     else if (0 <= cipt(0) && cipt(0) < width && 0 <= cipt(1) && cipt(1) < height) {
00060       val = image[cipt(1) * rowstride + cipt(0)];
00061     }
00062     else
00063       val = defaultValue; //templateImage(i / width, i % width); //default to the same as template, so error is 0
00064 
00065     warped_image[(i % height) * rowstride + (i / height)] = val; //Eigen is Column-major
00066   }
00067 }
00068 
00069 int main(int argc, char** argv)
00070 {
00071 
00072   uint8_t* src_im = (uint8_t*) malloc(640 * 480 * sizeof(uint8_t));
00073 
00074   int width, height, rowstride;
00075   bot_pgm_read_fname("test_im.pgm", &src_im, &width, &height, &rowstride);
00076 
00077   Eigen::MatrixXf ref_image = Eigen::MatrixXf::Zero(60, 80);
00078   ref_image.block(15, 25, 30, 30).setConstant(255.0);
00079 
00080   Eigen::Matrix3f H_warp;
00081   H_warp.setZero();
00082 
00083   double u = 2;
00084   double v = 1;
00085   double theta = 1 * M_PI / 180.0;
00086   int downsample = 0;
00087   if (argc >= 2)
00088     u = atof(argv[1]);
00089 
00090   if (argc >= 3)
00091     v = atof(argv[2]);
00092 
00093   if (argc >= 4)
00094     theta = atof(argv[3]) * M_PI / 180.0;
00095 
00096   if (argc >= 5)
00097     downsample = atoi(argv[4]);
00098 
00099   H_warp(0, 0) = cos(theta);
00100   H_warp(0, 1) = sin(theta);
00101   H_warp(1, 0) = -sin(theta);
00102   H_warp(1, 1) = cos(theta);
00103 
00104   H_warp(0, 2) = u;
00105   H_warp(1, 2) = v;
00106   H_warp(2, 2) = 1;
00107 
00108   uint8_t* warped_im = (uint8_t*) malloc(width * height * sizeof(uint8_t));
00109   warpImage(src_im, width, height, rowstride, H_warp, warped_im);
00110 
00111   fovis::InitialHomographyEstimator rotation_estimator;
00112   rotation_estimator.setTemplateImage(warped_im, width, height, rowstride, downsample);
00113 
00114   rotation_estimator.setTestImage(src_im, width, height, rowstride, downsample);
00115   double finalRMS = 0;
00116   Eigen::Matrix3f H_est = rotation_estimator.track(Eigen::Matrix3f::Identity(), 10, &finalRMS);
00117 
00118   double scale_factor = 1 << downsample;
00119   Eigen::Matrix3f S = Eigen::Matrix3f::Identity() * scale_factor;
00120   S(2,2)=1;
00121 
00122   //scale homography up to the full size image
00123   H_est = S * H_est * S.inverse();
00124 
00125   dump(H_warp);
00126   dump(H_est);
00127   fprintf(stderr, "finalRMS=%f\n", finalRMS);
00128 
00129   //draw results
00130   lcm_t * lcm = lcm_create(NULL);
00131   bot_lcmgl_t* lcmgl = bot_lcmgl_init(lcm, "Init_Homography_Test\n");
00132 
00133   //convert to pixel coords
00134   bot_lcmgl_push_matrix(lcmgl);
00135   bot_lcmgl_rotated(lcmgl, -90, 0, 0, 1);
00136   bot_lcmgl_scalef(lcmgl, 10.0 / width, -10.0 / width, 1);
00137 
00138   // template image
00139   bot_lcmgl_color3f(lcmgl, 1, 1, 1);
00140   int template_texid = bot_lcmgl_texture2d(lcmgl, warped_im, width, height, rowstride, BOT_LCMGL_LUMINANCE,
00141       BOT_LCMGL_COMPRESS_NONE);
00142 
00143   bot_lcmgl_push_matrix(lcmgl);
00144   bot_lcmgl_translated(lcmgl, 0, height + 10, 0);
00145   bot_lcmgl_texture_draw_quad(lcmgl, template_texid, 0, 0, 0, 0, height, 0, width, height, 0, width, 0, 0);
00146   bot_lcmgl_pop_matrix(lcmgl);
00147 
00148   // test image
00149   bot_lcmgl_color3f(lcmgl, 1, 1, 1);
00150   int gray_texid = bot_lcmgl_texture2d(lcmgl, src_im, width, height, rowstride, BOT_LCMGL_LUMINANCE,
00151       BOT_LCMGL_COMPRESS_NONE);
00152   bot_lcmgl_texture_draw_quad(lcmgl, gray_texid, 0, 0, 0, 0, height, 0, width, height, 0, width, 0, 0);
00153 
00154   //draw the ESM homography estimate
00155   bot_lcmgl_line_width(lcmgl, 2.0);
00156   bot_lcmgl_color3f(lcmgl, 1, 1, 0);
00157   bot_lcmgl_begin(lcmgl, GL_LINE_STRIP);
00158   Eigen::MatrixXf vertices(5, 3);
00159   vertices << 0, 0, 1, width, 0, 1, width, height, 1, 0, height, 1, 0, 0, 1;
00160 
00161   Eigen::MatrixXf warpedPoints = H_est * vertices.transpose();
00162   warpedPoints.row(0) = warpedPoints.row(0).array() / warpedPoints.row(2).array();
00163   warpedPoints.row(1) = warpedPoints.row(1).array() / warpedPoints.row(2).array();
00164   for (int i = 0; i < warpedPoints.cols(); i++) {
00165     bot_lcmgl_vertex2f(lcmgl, warpedPoints(0, i), warpedPoints(1, i));
00166   }
00167   bot_lcmgl_end(lcmgl);
00168 
00169   bot_lcmgl_pop_matrix(lcmgl);
00170 
00171   bot_lcmgl_switch_buffer(lcmgl);
00172 
00173   return 0;
00174 }


libfovis
Author(s): Albert Huang, Maurice Fallon
autogenerated on Thu Jun 6 2019 20:16:12