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
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
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;
00064
00065 warped_image[(i % height) * rowstride + (i / height)] = val;
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
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
00130 lcm_t * lcm = lcm_create(NULL);
00131 bot_lcmgl_t* lcmgl = bot_lcmgl_init(lcm, "Init_Homography_Test\n");
00132
00133
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
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
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
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 }