www.pudn.com > 99273898StereoMatch_1_0.zip > StereoIO.cpp
/////////////////////////////////////////////////////////////////////////// // // NAME // StereoIO.cpp -- stereo matcher file and parameter input/output // // DESCRIPTION // The CStereoIO class reads and write image and parameter files // needed to drive the CStereoMatcher class. // // SEE ALSO // StereoIO.h longer description this class // // Copyright © Richard Szeliski and Daniel Scharstein, 2001. // See Copyright.h for more details // /////////////////////////////////////////////////////////////////////////// #include "Error.h" #include "StereoIO.h" #include "ImageIO.h" #include "Convert.h" #ifdef WIN32 #include#else #include #endif // struct CStereoFrameDescriptor: // An input image and its associated meta-data (depth map, ground truth, ...) CStereoFrameDescriptor::CStereoFrameDescriptor() { memset(this, 0, sizeof(CStereoFrameDescriptor)); } void CStereoFrameDescriptor::PIOInitialize(CParameterIO& o) { // Initialize parameter input/output object // An input image and its associated meta-data (depth map, ground truth, ...): o.PPPS(input_file); // input image (gray or color) o.PPPS(depth_file); // depth image (input/output) o.PPPS(truth_file); // ground truth depth image o.PPPS(resampled_file); // resampled image (for reprojection error) } static void ReadIfThere(CByteImage& img, const char* filename, bool ok_if_not_there, int verbose) { if (filename[0] == 0) return; if (verbose >= eVerboseFileIO) fprintf(stderr, "reading image %s\n", filename); if (! ok_if_not_there) ReadImage(img, filename); else try { ReadImage(img, filename); } catch (CError& err) { // err.message; // Don't do anything, since image may not exist } // Most of the stereo matching code assumes nbands==1 or nbands==4 // make sure this is true int nb = img.Shape().nBands; if (! (nb == 1 || nb == 4)) throw CError("ReadImage(%s): number of bands (%d) not supported by stereo matcher", filename, nb); } void CStereoFrameDescriptor::ReadFrame(CStereoFrame& fr, int verbose) { // Read the constituent images ReadIfThere(fr.input_image, input_file, false, verbose); ReadIfThere(fr.depth_image, depth_file, true, verbose); ReadIfThere(fr.truth_image, truth_file, false, verbose); // Don't read the resampled image (will be recomputed, if needed) // ReadIfThere(fr.resampled_image, resampled_file, true, verbose); } static void WriteIfThere(CByteImage& img, const char* filename, int verbose) { if (filename[0] == 0 || img.Shape().height == 0) return; if (verbose >= eVerboseFileIO) fprintf(stderr, "writing image %s\n", filename); WriteImage(img, filename); } void CStereoFrameDescriptor::WriteFrame(CStereoFrame& fr, int verbose, bool write_depth) { // Write the depth and resampled images if (write_depth) WriteIfThere(fr.depth_image, depth_file, verbose); WriteIfThere(fr.resampled_image, resampled_file, verbose); } // struct CStereoIOParameters // Additional parameters for running stereo from command-line or script: CStereoIOParameters::CStereoIOParameters() { memset(this, 0, sizeof(CStereoIOParameters)); } void CStereoIOParameters::PIOInitialize(CParameterIO& o) { // Initialize parameter input/output object // Additional parameters for running stereo from command-line or script: o.PPPS(input_params); // input parameter file o.PPPS(output_params); // output parameter and result file o.PPPS(input_data); // original image and depth map filenames o.PPPS(output_data); // final image and depth map filenames o.PPPS(depth_map); // depth map image (override input_data) o.PPPS(cost_map); // cost map (DSI), for debugging } CStereoIO::CStereoIO() { // Constructor CStereoParameters::PIOInitialize(m_pio); CStereoIOParameters::PIOInitialize(m_pio); m_fd0.PIOInitialize(m_dio); } int CStereoIO::InterpretCommandLine(int argc, const char *argv[]) { // Interpret the command (or script file) line const char *command = argv[1]; const char *argument = argv[2]; // Zero out the parameters in this class before initial read memset(&this->input_params, 0, sizeof(CStereoIOParameters)); // Read in the arguments (may get clobbered by input_params, but fix that later) m_pio.ReadFromCommandLine(argc-1, argv+1); if (command == 0 || command[0] == 0) throw CError("No command is given on command line.\n\ Please see the README-StereoMatch.txt file for proper usage.\n"); // Interpret the script file if (strcmp("script", command) == 0) { InterpretScriptFile(argument); return 0; // no other commands executed } // Change the directory if (strcmp("cd", command) == 0) { int retval = chdir(argument); if (verbose >= eVerboseSummary) { char buf[1024]; getcwd(buf, 1024); fprintf(stderr, "working dir: %s\n", buf); } if (retval) throw CError("Could not cd to %s", argument); return 0; // no other commands executed } // Reset all CStereoParameters that affect the algorithm to their default values if (strcmp("reset", command) == 0) { ReInitializeAlgParams(); } // Exit this script if (strcmp("exit", command) == 0) { return 1; } // Read in the parameter file if specified ReadParameters(); // Re-read the command-line arguments (to override parameter file) m_pio.ReadFromCommandLine(argc-1, argv+1, false); // Reset the output parameters ResetOutputParams(); // Read in the data (input images) if specified ReadData(); // Copy the depth_map name into the frame descriptor if (frame_ref >= 0 && frame_ref < (int)m_fd.size() && depth_map[0]) strcpy(m_fd[frame_ref].depth_file, depth_map); // Early out if no matching or evaluation if (depth_map[0] == 0 && output_params[0] == 0) return 0; // At this point, a "depth_map" and/or an "output_params" command is present // in the current command line if (frame_ref >= (int)m_fd.size() || frame_match >= (int)m_fd.size()) throw CError("Data has not yet been read in"); // Read in the depth_map if only evaluating if (evaluate_only) { ReadIfThere(m_frame[frame_ref].depth_image, depth_map, false, verbose); } // If output_params is not specified, derive name from depth_map if (output_params[0] == 0) { strcpy(output_params, depth_map); strcpy(&output_params[strlen(output_params)-3], "txt"); } // Execute the command RunMatcher(); // Write out the data (results) WriteData(); // Write out the (updated) parameter file if specified WriteParameters(); if (verbose >= eVerboseSummary) fprintf(stderr, " writing %s\n", output_params[0] ? output_params : depth_map); return 0; } void CStereoIO::RunMatcher() { // Run the matcher and evaluator // TODO: ALWAYS need to call ComputeCorrespondence because that's where // m_float_disparity is initialized from depth_image?? if (depth_map[0]) ComputeCorrespondence(); if (output_params[0]) Evaluate(); } class CCommandLineParser { public: CCommandLineParser(char *command_line); int argc; const char *argv[256]; }; CCommandLineParser::CCommandLineParser(char *command_line) { // Set up the pointers to the parsed line (modifies the command_line string) argc = 1; argv[0] = 0; // no valid argv[0] if parsing from string int spn = strspn(command_line, " \t\n"); // skip whitespace command_line += spn; while (command_line[0] && argc < 256) { if (command_line[0] == '#') // comment line or trailing comment return; argv[argc] = command_line; // push the next command line argument argc += 1; char *last = strpbrk(command_line, " \t\n"); // find next whitespace if (last) { last[0] = 0; // null-terminate the argument (destructive) command_line = last+1; int spn = strspn(command_line, " \t\n"); // skip whitespace command_line += spn; } else break; } } void CStereoIO::InterpretScriptFile(const char* script_file) { // Interpret the commands in the script file FILE *stream = fopen(script_file, "r"); if (stream == 0) throw CError("InterpretScriptFile: could not open %s", script_file); // Echo where we are if (verbose >= eVerboseScriptFile) fprintf(stderr, "Interpreting script file %s\n", script_file); // Iterate over the lines const int MAX_LINE = 4096; // maximum command line length char command_line[MAX_LINE]; while (fgets(command_line, MAX_LINE, stream)) { // Echo if verbose if (verbose >= eVerboseScriptFile) fprintf(stderr, command_line); CCommandLineParser clp(command_line); if (clp.argc > 1) { // Re-use current object, so remember previous state/parameters int retval = InterpretCommandLine(clp.argc, clp.argv); if (retval) break; } } fclose(stream); } void CStereoIO::ReadParameters() { // Read in the algorithm parameters if (input_params[0]) { m_pio.ReadFromFile(input_params); } } void CStereoIO::WriteParameters() { // Write out the algorithm parameters and accuracy measures if (output_params[0]) { m_pio.WriteToFile(output_params); } } void CStereoIO::ReadData() { // Read in the images and (optional) ground truth if (input_data[0] == 0) return; FILE *stream = fopen(input_data, "r"); if (stream == 0) throw CError("ReadData: could not open %s", input_data); // Iterate over the frames const int MAX_LINE = 4096; // maximum descriptor line length char line[MAX_LINE]; m_fd.clear(); m_frame.clear(); while (fgets(line, MAX_LINE, stream)) { CCommandLineParser clp(line); if (clp.argc > 1) { // Read the descriptor memset(&m_fd0, 0, sizeof(m_fd0)); m_dio.ReadFromCommandLine(clp.argc-1, clp.argv+1); // Override the depth_map? if ((int)m_fd.size() == frame_ref && depth_map[0]) strcpy(m_fd0.depth_file, depth_map); m_fd.push_back(m_fd0); // Read the files CStereoFrame fr; m_fd0.ReadFrame(fr, verbose); m_frame.push_back(fr); } } fclose(stream); } void CStereoIO::WriteData() { // Write out the resulting disparity maps (unless evaluate_only) // reprojected images (if specified) and // the descriptor file (if specified) FILE *stream = 0; if (output_data[0]) { stream = fopen(output_data, "w"); if (stream == 0) throw CError("WriteData: could not open %s", output_data); } // Iterate over the frames for (int i = 0, n = m_fd.size(); i < n; i++) { m_fd0 = m_fd[i]; CStereoFrame& fr = m_frame[i]; m_fd0.WriteFrame(fr, verbose, ! evaluate_only); if (stream) m_dio.WriteToStream(stream, true); } if (stream) fclose(stream); // Write out the error images if (eval_error_scale > 0.0f) { // Create the new filenames (suffix _e and _b) char filename[FILENAME_MAX]; char *dot = strrchr(depth_map, '.'); int n_stem = dot - depth_map; strncpy(filename, depth_map, n_stem); strcpy(&filename[n_stem], "_e"); strcat(filename, dot); WriteImage(m_disparity_error, filename); filename[n_stem+1] = 'b'; WriteImage(m_bad_pixels, filename); if (m_disparity_histogram.Shape().width > 0) { filename[n_stem+1] = 'h'; WriteImage(m_disparity_histogram, filename); } } // Write out combined disparity and status color image if (m_status_disp.Shape().width > 0) { // Create the new filename (.ppm instead of .pgm) char filename[FILENAME_MAX]; strcpy(filename, depth_map); filename[strlen(filename)-2] = 'p'; WriteImage(m_status_disp, filename); } }