From 6e08c416da1c889c5d0fa2204c5d9a973ab705fd Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Tue, 23 Apr 2024 14:57:03 -0700 Subject: [PATCH] Expand the camera_calibrate tool and the doc of camera solve, mention --fix-gcp-xyz --- docs/sfm.rst | 32 +++++++------- docs/tools/bundle_adjust.rst | 8 +++- docs/tools/camera_calibrate.rst | 62 +++++++++++++++++----------- docs/tools/camera_solve.rst | 11 ++--- docs/tools/stereo_gui.rst | 3 ++ src/asp/Camera/BundleAdjustCamera.cc | 2 +- src/asp/Core/GCP.cc | 4 +- src/asp/Core/MatchList.cc | 1 - src/asp/Tools/bundle_adjust.cc | 24 ++++++----- 9 files changed, 90 insertions(+), 57 deletions(-) diff --git a/docs/sfm.rst b/docs/sfm.rst index deccf9299..3f9324f69 100644 --- a/docs/sfm.rst +++ b/docs/sfm.rst @@ -169,8 +169,9 @@ Creation of cameras in an arbitrary coordinate system If we do not see any obvious problems we can go ahead and run the ``camera_solve`` tool:: - camera_solve out/ AS15-M-0114_MED.png AS15-M-0115_MED.png \ - --datum D_MOON --calib-file metric_model.tsai + camera_solve out/ AS15-M-0114_MED.png AS15-M-0115_MED.png \ + --theia-overrides '--matching_strategy=CASCADE_HASHING' \ + --datum D_MOON --calib-file metric_model.tsai The reconstruction can be visualized as:: @@ -214,13 +215,15 @@ such a GCP file to ``camera_solve`` together with the flag:: --bundle-adjust-params "--transform-cameras-using-gcp" -This may not be as robust as the earlier approach. +This may not be as robust as the earlier approach. Consider the option +``--fix-gcp-xyz``, to not move the GCP during optimization. Solving for cameras when using GCP:: - camera_solve out_gcp/ \ - AS15-M-0114_MED.png AS15-M-0115_MED.png \ - --datum D_MOON --calib-file metric_model.tsai \ + camera_solve out_gcp/ \ + AS15-M-0114_MED.png AS15-M-0115_MED.png \ + --datum D_MOON --calib-file metric_model.tsai \ + --theia-overrides '--matching_strategy=CASCADE_HASHING' \ --gcp-file ground_control_points.gcp Examine the lines ending in ``# GCP`` in the file:: @@ -382,14 +385,15 @@ to match. Commands using these options may look like this:: icebridge_kmz_to_csv 1000123_DMS_Frame_Events.kmz \ camera_positions.csv - camera_solve out \ - 2009_11_05_00667.JPG 2009_11_05_00668.JPG \ - 2009_11_05_00669.JPG 2009_11_05_00670.JPG \ - 2009_11_05_02947.JPG 2009_11_05_02948.JPG \ - 2009_11_05_02949.JPG 2009_11_05_02950.JPG \ - 2009_11_05_01381.JPG 2009_11_05_01382.JPG \ - --datum WGS84 --calib-file icebridge_model.tsai \ - --bundle-adjust-params \ + camera_solve out \ + 2009_11_05_00667.JPG 2009_11_05_00668.JPG \ + 2009_11_05_00669.JPG 2009_11_05_00670.JPG \ + 2009_11_05_02947.JPG 2009_11_05_02948.JPG \ + 2009_11_05_02949.JPG 2009_11_05_02950.JPG \ + 2009_11_05_01381.JPG 2009_11_05_01382.JPG \ + --theia-overrides '--matching_strategy=CASCADE_HASHING' \ + --datum WGS84 --calib-file icebridge_model.tsai \ + --bundle-adjust-params \ '--no-datum --camera-positions camera_positions.csv --csv-format "1:file 2:lon 3:lat 4:height_above_datum" diff --git a/docs/tools/bundle_adjust.rst b/docs/tools/bundle_adjust.rst index 0bc1c117f..f66c2a1bd 100644 --- a/docs/tools/bundle_adjust.rst +++ b/docs/tools/bundle_adjust.rst @@ -55,13 +55,16 @@ control points (:numref:`bagcp`):: file1.tif file2.tif \ file1.xml file2.xml \ gcp1.gcp gcp2.gcp gcp3.gcp \ + --fix-gcp-xyz \ -o run_ba/run Using the proper value for ``--datum`` is very important, otherwise the longitude-latitude-height values in the GCP files will not be interpreted correctly. -There can be more than one GCP file. +There can be more than one GCP file. The option ``--fix-gcp-xyz`` fixes the GCP +coordinates during optimization. This is useful when the GCP are very accurate. +Otherwise set per-GCP sigma. The residuals for the GCP will be printed at the end of the ``{output-prefix}-final_residuals_pointmap.csv`` file, @@ -471,6 +474,9 @@ to transform them as a group, with the ``bundle_adjust`` options ``--transform-cameras-with-shared-gcp`` and ``--transform-cameras-using-gcp``. For use with SfM, see :numref:`sfm_world_coords`. +The option ``--fix-gcp-xyz`` fixes the GCP coordinates during optimization. This +is useful when the GCP are very accurate. Otherwise set per-GCP sigma. + The option ``--save-cnet-as-csv`` can be invoked to save the entire control network in the GCP format, before any optimization. This can be useful for comparing with any manually created GCP. diff --git a/docs/tools/camera_calibrate.rst b/docs/tools/camera_calibrate.rst index 519348665..9b94b5939 100644 --- a/docs/tools/camera_calibrate.rst +++ b/docs/tools/camera_calibrate.rst @@ -3,14 +3,48 @@ camera_calibrate ---------------- +Overview +~~~~~~~~ + The ``camera_calibrate`` tool can generate camera models suitable for use by ``camera_solve`` (:numref:`camera_solve`), and other ASP tools. This program only solves for intrinsic camera parameters. To obtain the camera pose you should use ``camera_solve``. -This tool is a wrapper around the OpenCV (http://opencv.org/) checkerboard -calibration tool which takes care of converting the output into readily usable -formats. +This tool is a wrapper around the `OpenCV camera calibration +`_ software, +which takes care of converting the output into readily usable formats. + +Other tools +~~~~~~~~~~~ + +ASP also ships the ``rig_calibrator`` program (:numref:`rig_calibrator`), +which calibrates the intrinsic and extrinsics of a rig of cameras, without +using a calibration target. + +The ``bundle_adjust`` program can refine the intrinsics and extrinsics of +cameras, and can also constrain against a known well-aligned terrain (:numref:`floatingintrinsics`). + +Example +~~~~~~~ + +:: + + camera_calibrate --box-size-cm 4.28625 outputFolder \ + 12 12 "images/image*.jpg" + +Here, the checkerboard pattern has 13 squares in each direction, so +12 inner corners. + +How to use +~~~~~~~~~~ + +:: + + camera_calibrate [options] \ + \ + \ + When you run the tool, three camera model files will be created in the output folder: ``solve_cam_params.txt``, ``vw_cam_params.tsai``, and @@ -35,26 +69,8 @@ This must be in quotes so that the wildcard is not expanded before it is passed to the tool. If you do not provide the ``--box-size`` parameter, the output calibration numbers will be unitless. -ASP also ships the ``rig_calibrator`` program (:numref:`rig_calibrator`), -which calibrates the intrinsic and extrinsics of a rig of cameras, without -using a calibration target. - -Example:: - - camera_calibrate --box-size-cm 4.28625 outputFolder \ - 12 12 "images/image*.jpg" - -Here, the checkerboard pattern has 13 squares in each direction, so -12 inner corners. - -Usage:: - - camera_calibrate [options] \ - \ - \ - - -Command-line options for camera_calibrate: +Command-line options +~~~~~~~~~~~~~~~~~~~~ -h, --help Display this help message. diff --git a/docs/tools/camera_solve.rst b/docs/tools/camera_solve.rst index 9a9cb5268..04fc184cb 100644 --- a/docs/tools/camera_solve.rst +++ b/docs/tools/camera_solve.rst @@ -45,17 +45,18 @@ each output folder and pass it back to ``camera_solve`` via ``--theia-flagfile``, or use the option ``--theia-overrides``. In particular, setting ``--feature_density=DENSE`` in the flags file can be of -great help if there are not enough matches between images. +great help if there are not enough matches between images. The option +``--matching_strategy=CASCADE_HASHING`` can greatly speed up finding matches. Example ^^^^^^^ :: - camera_solve \ - --bundle-adjust-params '--camera-positions nav.csv \ - --csv-format "1:file 12:lat 13:lon 14:height_above_datum" \ - --camera-weight 100.0' \ + camera_solve \ + --theia-overrides '--matching_strategy=CASCADE_HASHING' \ + --bundle-adjust-params '--camera-positions nav.csv + --csv-format 1:file,12:lat,13:lon,14:height_above_datum' \ The produced Theia reconstruction can be visualized with ``view_reconstruction`` diff --git a/docs/tools/stereo_gui.rst b/docs/tools/stereo_gui.rst index d49f9a4e9..3144bfc7c 100644 --- a/docs/tools/stereo_gui.rst +++ b/docs/tools/stereo_gui.rst @@ -591,6 +591,9 @@ will prompt for their names. If having many images, this process can be repeated for several small sets, creating several GCP files that can then be passed together to ``bundle_adjust``. +The sigmas for the GCP should be set manually. Or use ``bundle_adjust`` +with the option ``--fix-gcp-xyz`` to ensure they are not adjusted. + GCP can be visualized in ``stereo_gui`` (:numref:`stereo_gui_vwip_gcp`). If the input images and the orthoimage are very similar visually, one can diff --git a/src/asp/Camera/BundleAdjustCamera.cc b/src/asp/Camera/BundleAdjustCamera.cc index 438f3cae8..47b13b26c 100644 --- a/src/asp/Camera/BundleAdjustCamera.cc +++ b/src/asp/Camera/BundleAdjustCamera.cc @@ -1598,7 +1598,7 @@ void asp::matchFilesProcessing(vw::ba::ControlNetwork const& cnet, std::vector> & mapprojOffsetsPerCam, std::vector & horizVertErrors) { - vw_out() << "Filtering outliers and creating reports.\n"; + vw_out() << "Creating reports.\n"; // Wipe the outputs mapprojPoints.clear(); diff --git a/src/asp/Core/GCP.cc b/src/asp/Core/GCP.cc index 30f68ee88..0bfab369b 100644 --- a/src/asp/Core/GCP.cc +++ b/src/asp/Core/GCP.cc @@ -80,8 +80,10 @@ void writeGCP(std::vector const& image_files, // It is important to keep track of the datum and projection, because the // elevations are relative to it // TODO(oalexan1): Put below dem_georef.get_wkt() instead. + // TODO(oalexan1): Have a single GCP-writing function, and put it in VW. + // See also the existing one called write_in_gcp_format() in VW. output_handle << "# WKT: " << dem_georef.datum().get_wkt() << std::endl; - + // TODO(oalexan1): Write here if the format is lon,lat,height, or easting, northing, height. size_t num_pts_skipped = 0, num_pts_used = 0; const size_t num_ips = matchlist.getNumPoints(); diff --git a/src/asp/Core/MatchList.cc b/src/asp/Core/MatchList.cc index ba1fa54fa..63a347a78 100644 --- a/src/asp/Core/MatchList.cc +++ b/src/asp/Core/MatchList.cc @@ -20,7 +20,6 @@ #include #include #include // Needed for vw::ip::match_filename - #include using namespace vw; diff --git a/src/asp/Tools/bundle_adjust.cc b/src/asp/Tools/bundle_adjust.cc index 744dd6068..8368eaa88 100644 --- a/src/asp/Tools/bundle_adjust.cc +++ b/src/asp/Tools/bundle_adjust.cc @@ -1509,6 +1509,10 @@ void do_ba_ceres(Options & opt, std::vector const& estimated_camera_gcc // Always save the updated cameras, even if we are not doing any optimization saveUpdatedCameras(opt, param_storage); + // If we are only applying an initial transform, we are done + if (opt.apply_initial_transform_only) + return; + // Write the GCP stats to a file if (num_gcp > 0) param_storage.print_gcp_stats(opt.out_prefix, cnet, opt.datum); @@ -1594,24 +1598,22 @@ void do_ba_ceres(Options & opt, std::vector const& estimated_camera_gcc asp::saveTriOffsetsPerCamera(opt.image_files, orig_parameters, param_storage, crn, tri_offsets_file); - if (!opt.apply_initial_transform_only && has_datum && + if (has_datum && (opt.stereo_session == "pinhole") || (opt.stereo_session == "nadirpinhole")) saveCameraReport(opt, param_storage, opt.datum, "final"); // Save the updated cnet to ISIS or nvm format. Note that param_storage has // the latest triangulated points and outlier info, while the cnet has the // initially triangulated points and the interest point matches. - if (!opt.apply_initial_transform_only) { - if (opt.isis_cnet != "" && opt.output_cnet_type == "isis-cnet") - asp::saveUpdatedIsisCnet(opt.out_prefix, cnet, param_storage, isisCnetData); - else if (opt.output_cnet_type == "isis-cnet") - asp::saveIsisCnet(opt.out_prefix, opt.datum, cnet, param_storage); - else if (opt.output_cnet_type == "nvm") { - asp::saveNvm(opt, opt.no_poses_from_nvm, cnet, param_storage, - world_to_cam, optical_offsets); - } + if (opt.isis_cnet != "" && opt.output_cnet_type == "isis-cnet") + asp::saveUpdatedIsisCnet(opt.out_prefix, cnet, param_storage, isisCnetData); + else if (opt.output_cnet_type == "isis-cnet") + asp::saveIsisCnet(opt.out_prefix, opt.datum, cnet, param_storage); + else if (opt.output_cnet_type == "nvm") { + asp::saveNvm(opt, opt.no_poses_from_nvm, cnet, param_storage, + world_to_cam, optical_offsets); } - + } // end do_ba_ceres /// Looks in the input camera position file to generate a GCC position for