00001
00002
00003 #include <assert.h>
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <vector>
00007 #include <string>
00008 #include <string.h>
00009
00010
00011 #include <sys/stat.h>
00012 #include <sys/types.h>
00013
00014 #include "image.h"
00015 #include "matrix.h"
00016 #include "sfm.h"
00017 #include "LoadJPEG.h"
00018
00019 typedef struct
00020 {
00021 double pos[3];
00022 double color[3];
00023
00024 } point_t;
00025
00026 void ReadListFile(char *list_file, std::vector<std::string> &files)
00027 {
00028 FILE *f = fopen(list_file, "r");
00029
00030 char buf[256];
00031 while (fgets(buf, 256, f)) {
00032 if (buf[strlen(buf)-1] == '\n')
00033 buf[strlen(buf)-1] = 0;
00034
00035 char *space = strchr(buf, ' ');
00036 if (space) *space = 0;
00037
00038 files.push_back(std::string(buf));
00039 }
00040
00041 fclose(f);
00042 }
00043
00044 void ReadBundleFile(char *bundle_file,
00045 std::vector<camera_params_t> &cameras,
00046 std::vector<point_t> &points, double &bundle_version)
00047 {
00048 FILE *f = fopen(bundle_file, "r");
00049 if (f == NULL) {
00050 printf("Error opening file %s for reading\n", bundle_file);
00051 return;
00052 }
00053
00054 int num_images, num_points;
00055
00056 char first_line[256];
00057 fgets(first_line, 256, f);
00058 if (first_line[0] == '#') {
00059 double version;
00060 sscanf(first_line, "# Bundle file v%lf", &version);
00061
00062 bundle_version = version;
00063 printf("[ReadBundleFile] Bundle version: %0.3f\n", version);
00064
00065 fscanf(f, "%d %d\n", &num_images, &num_points);
00066 } else if (first_line[0] == 'v') {
00067 double version;
00068 sscanf(first_line, "v%lf", &version);
00069 bundle_version = version;
00070 printf("[ReadBundleFile] Bundle version: %0.3f\n", version);
00071
00072 fscanf(f, "%d %d\n", &num_images, &num_points);
00073 } else {
00074 bundle_version = 0.1;
00075 sscanf(first_line, "%d %d\n", &num_images, &num_points);
00076 }
00077
00078 printf("[ReadBundleFile] Reading %d images and %d points...\n",
00079 num_images, num_points);
00080
00081
00082 for (int i = 0; i < num_images; i++) {
00083 double focal_length, k0, k1;
00084 double R[9];
00085 double t[3];
00086
00087 if (bundle_version < 0.2) {
00088
00089 fscanf(f, "%lf\n", &focal_length);
00090 } else {
00091 fscanf(f, "%lf %lf %lf\n", &focal_length, &k0, &k1);
00092 }
00093
00094
00095 fscanf(f, "%lf %lf %lf\n%lf %lf %lf\n%lf %lf %lf\n",
00096 R+0, R+1, R+2, R+3, R+4, R+5, R+6, R+7, R+8);
00097
00098 fscanf(f, "%lf %lf %lf\n", t+0, t+1, t+2);
00099
00100
00101
00102
00103 camera_params_t cam;
00104
00105 cam.f = focal_length;
00106 memcpy(cam.R, R, sizeof(double) * 9);
00107 memcpy(cam.t, t, sizeof(double) * 3);
00108
00109 cameras.push_back(cam);
00110 }
00111
00112
00113 for (int i = 0; i < num_points; i++) {
00114 point_t pt;
00115
00116
00117 fscanf(f, "%lf %lf %lf\n",
00118 pt.pos + 0, pt.pos + 1, pt.pos + 2);
00119
00120
00121 fscanf(f, "%lf %lf %lf\n",
00122 pt.color + 0, pt.color + 1, pt.color + 2);
00123
00124 int num_visible;
00125 fscanf(f, "%d", &num_visible);
00126
00127 for (int j = 0; j < num_visible; j++) {
00128 int view, key;
00129 fscanf(f, "%d %d", &view, &key);
00130
00131 double x, y;
00132 if (bundle_version >= 0.3)
00133 fscanf(f, "%lf %lf", &x, &y);
00134 }
00135
00136 if (num_visible > 0) {
00137 points.push_back(pt);
00138 }
00139 }
00140
00141 fclose(f);
00142 }
00143
00144 void WritePMVS(const char *output_path, char *list_file, char *bundle_file,
00145 std::vector<std::string> images,
00146 std::vector<camera_params_t> &cameras)
00147 {
00148 int num_cameras = (int) cameras.size();
00149
00150
00151 mkdir(output_path, 0770);
00152
00153 char buf[2048];
00154 sprintf(buf, "%s/prep_pmvs.sh", output_path);
00155
00156 FILE *f_scr = fopen(buf, "w");
00157
00158 fprintf(f_scr, "#!/bin/bash\n\n");
00159 fprintf(f_scr, "# Script for preparing images and calibration data \n"
00160 "# for Yasutaka Furukawa's PMVS system\n");
00161 fprintf(f_scr, "# Modified by Dorian Galvez for RoboEarth WP1\n\n");
00162
00163 fprintf(f_scr, "BUNDLER_BIN_PATH=\"$1\" # Edit this line before running\n");
00164 fprintf(f_scr, "USE_IMAGES_WITH_BG=$2\n\n");
00165
00166
00167
00168
00169
00170
00171 std::string list_file_with_bg;
00172 std::string s_list_file = list_file;
00173
00174 std::string::size_type n = s_list_file.find_last_of('.');
00175
00176 if(n == std::string::npos)
00177 list_file_with_bg = s_list_file + "_with_bg";
00178 else
00179 {
00180 list_file_with_bg = s_list_file.substr(0, n) + "_with_bg.txt";
00181 }
00182
00183 fprintf(f_scr, "if [ $USE_IMAGES_WITH_BG -eq 0 ]; then\n");
00184 fprintf(f_scr, " LIST_FILE=%s\n", list_file);
00185 fprintf(f_scr, "else\n");
00186 fprintf(f_scr, " LIST_FILE=%s\n", list_file_with_bg.c_str());
00187 fprintf(f_scr, "fi\n\n");
00188
00189 fprintf(f_scr, "# Apply radial undistortion to the images\n");
00190 fprintf(f_scr, "$BUNDLER_BIN_PATH/RadialUndistort %s %s %s\n",
00191 "$LIST_FILE", bundle_file, output_path);
00192 fprintf(f_scr, "\n# Create directory structure\n");
00193
00194 fprintf(f_scr, "mkdir -p %s/txt/\n", output_path);
00195 fprintf(f_scr, "mkdir -p %s/visualize/\n", output_path);
00196 fprintf(f_scr, "mkdir -p %s/models/\n", output_path);
00197 fprintf(f_scr, "\n# Copy and rename files\n");
00198
00199 int count = 0;
00200 for (int i = 0; i < num_cameras; i++) {
00201 if (cameras[i].f == 0.0)
00202 continue;
00203
00204 char buf[256];
00205 sprintf(buf, "%s/%08d.txt", output_path, count);
00206 FILE *f = fopen(buf, "w");
00207 assert(f);
00208
00209
00210 double focal = cameras[i].f;
00211 double *R = cameras[i].R;
00212 double *t = cameras[i].t;
00213
00214 int w, h;
00215 GetJPEGDimensions(images[i].c_str(), w, h);
00216
00217 double K[9] =
00218 { -focal, 0.0, 0.5 * w - 0.5,
00219 0.0, focal, 0.5 * h - 0.5,
00220 0.0, 0.0, 1.0 };
00221
00222 double Ptmp[12] =
00223 { R[0], R[1], R[2], t[0],
00224 R[3], R[4], R[5], t[1],
00225 R[6], R[7], R[8], t[2] };
00226
00227 double P[12];
00228 matrix_product(3, 3, 3, 4, K, Ptmp, P);
00229 matrix_scale(3, 4, P, -1.0, P);
00230
00231 fprintf(f, "CONTOUR\n");
00232 fprintf(f, "%0.6f %0.6f %0.6f %0.6f\n", P[0], P[1], P[2], P[3]);
00233 fprintf(f, "%0.6f %0.6f %0.6f %0.6f\n", P[4], P[5], P[6], P[7]);
00234 fprintf(f, "%0.6f %0.6f %0.6f %0.6f\n", P[8], P[9], P[10], P[11]);
00235
00236 fclose(f);
00237
00238 int last_dot = images[i].rfind('.', images[i].length()-1);
00239 int first_pos = images[i].rfind('/');
00240 if(first_pos == std::string::npos) first_pos = 0;
00241 else first_pos++;
00242
00243 std::string basename = images[i].substr(first_pos, last_dot-first_pos);
00244
00245 fprintf(f_scr, "mv %s/%s.rd.jpg %s/visualize/%08d.jpg\n",
00246 output_path, basename.c_str(), output_path, count);
00247 fprintf(f_scr, "mv %s %s/txt/\n", buf, output_path);
00248
00249 count++;
00250 }
00251
00252
00253 sprintf(buf, "%s/pmvs_options.txt", output_path);
00254 FILE *f_opt = fopen(buf, "w");
00255
00256 fprintf(f_opt, "level 1\n");
00257 fprintf(f_opt, "csize 2\n");
00258 fprintf(f_opt, "threshold 0.7\n");
00259 fprintf(f_opt, "wsize 7\n");
00260 fprintf(f_opt, "minImageNum 3\n");
00261 fprintf(f_opt, "CPU 8\n");
00262 fprintf(f_opt, "setEdge 0\n");
00263 fprintf(f_opt, "useBound 0\n");
00264 fprintf(f_opt, "useVisData 1\n");
00265 fprintf(f_opt, "sequence -1\n");
00266 fprintf(f_opt, "timages -1 0 %d\n", count);
00267 fprintf(f_opt, "oimages -3\n");
00268
00269 fclose(f_opt);
00270
00271 fprintf(f_scr, "\necho \"Running Bundle2Vis to generate vis.dat\"\n");
00272 fprintf(f_scr, "$BUNDLER_BIN_PATH/Bundle2Vis %s/bundle.rd.out %s/vis.dat\n",
00273 output_path, output_path);
00274
00275 fprintf(f_scr, "\n\n\necho @@ Sample command for running pmvs:\n");
00276 fprintf(f_scr, "echo \" pmvs2 %s/ pmvs_options.txt\"\n", output_path);
00277 fprintf(f_scr, "echo \" - or - \"\n");
00278 fprintf(f_scr, "echo \" use Dr. Yasutaka Furukawa's view clustering algorithm to generate a set of options files.\"\n");
00279 fprintf(f_scr, "echo \" The clustering software is available at http://grail.cs.washington.edu/software/cmvs\"\n");
00280
00281 fclose(f_scr);
00282 }
00283
00284 int main(int argc, char **argv)
00285 {
00286 if (argc != 3 && argc != 4) {
00287 printf("Usage: %s <list.txt> <bundle.out> [pmvs_output_path (default: pmvs)]\n",
00288 argv[0]);
00289 return 1;
00290 }
00291
00292 char *list_file = argv[1];
00293 char *bundle_file = argv[2];
00294 char *output_path = "pmvs";
00295
00296 if (argc == 4)
00297 output_path = argv[3];
00298
00299
00300 FILE *f = fopen(list_file, "r");
00301 if (f == NULL) {
00302 printf("Error opening file %s for reading\n", list_file);
00303 return 1;
00304 }
00305
00306 std::vector<std::string> images;
00307 ReadListFile(list_file, images);
00308
00309
00310 std::vector<camera_params_t> cameras;
00311 std::vector<point_t> points;
00312 double bundle_version;
00313 ReadBundleFile(bundle_file, cameras, points, bundle_version);
00314
00315
00316 WritePMVS(output_path, list_file, bundle_file, images, cameras);
00317
00318 printf("\n\n");
00319 printf("@@ Conversion complete, execute \"sh %s/prep_pmvs.sh\" to finalize\n", output_path);
00320 printf("@@ (you will first need to edit prep_pmvs.sh to specify your bundler path, \n");
00321 printf("@@ so that the script knows where to find your\n"
00322 "@@ RadialUndistort and Bundle2Vis binaries)\n");
00323
00324 return 0;
00325 }