From 2d5540344986f81c190bbd09ad5c9ee860ae8083 Mon Sep 17 00:00:00 2001 From: Oleg Alexandrov Date: Tue, 27 Jul 2021 15:16:40 -0700 Subject: [PATCH] A handful of minor changes to push version 3.0.0 out --- INSTALLGUIDE.rst | 26 +++----- NEWS.rst | 13 ++-- RELEASEGUIDE | 21 +++--- docs/next_steps.rst | 27 +++++++- docs/stereo_algorithms.rst | 12 +++- docs/stereodefault.rst | 4 +- src/CMakeLists.txt | 4 +- src/asp/Core/AffineEpipolar.cc | 117 +++++++++++++++++++++++++++++---- src/asp/Core/LocalAlignment.cc | 38 +++++++---- src/asp/Core/LocalAlignment.h | 2 +- src/asp/Tools/parallel_stereo | 5 +- src/asp/Tools/stereo_corr.cc | 53 ++++++++++++++- 12 files changed, 252 insertions(+), 70 deletions(-) diff --git a/INSTALLGUIDE.rst b/INSTALLGUIDE.rst index 3c145dd83..549af0a8d 100644 --- a/INSTALLGUIDE.rst +++ b/INSTALLGUIDE.rst @@ -203,15 +203,9 @@ environments, which you don't want. Install ASP with the command:: - conda install stereo-pipeline==2.7.0 + conda install stereo-pipeline==3.0.0 -This will install ASP 2.7.0 together with ISIS 4.1.0. - -Running instead:: - - conda install stereo-pipeline==isis5.0.1 - -will install a development version of ASP together with ISIS 5.0.1. +This will install ASP 3.0.0 together with ISIS 5.0.1. If using ISIS, the environmental variable ISISROOT should be set to point to this distribution, such as:: @@ -228,11 +222,11 @@ found as a set of .yaml files in the ``conda/`` subdirectory of the Stereo Pipeline GitHub repository. So, alternatively, the installation can happen as:: - conda env create -f asp_2.7.0_linux_env.yaml + conda env create -f asp_3.0.0_linux_env.yaml or:: - conda env create -f asp_2.7.0_osx_env.yaml + conda env create -f asp_3.0.0_osx_env.yaml depending on your platform. Then invoke, as earlier:: @@ -261,11 +255,11 @@ The environments having the ASP dependencies are in the ``conda`` directory of the Stereo Pipeline repository, as above. After downloading those, one can run on Linux:: - conda env create -f asp_deps_2.7.0_linux_env.yaml + conda env create -f asp_deps_3.0.0_linux_env.yaml or on the Mac:: - conda env create -f asp_deps_2.7.0_osx_env.yaml + conda env create -f asp_deps_3.0.0_osx_env.yaml This will create an ``asp_deps`` environment. Activate it with:: @@ -304,7 +298,7 @@ Building VisionWorkbench and Stereo Pipeline on Linux:: ~/miniconda3/envs/asp_deps/bin/git clone \ git@github.com:visionworkbench/visionworkbench.git cd visionworkbench - git checkout 2.7.0 # check out the desired commit + git checkout 3.0.0 # check out the desired commit mkdir -p build cd build ~/miniconda3/envs/asp_deps/bin/cmake .. \ @@ -320,7 +314,7 @@ Building VisionWorkbench and Stereo Pipeline on Linux:: ~/miniconda3/envs/asp_deps/bin/git clone \ git@github.com:NeoGeographyToolkit/StereoPipeline.git cd StereoPipeline - git checkout 2.7.0 # check out the desired commit + git checkout 3.0.0 # check out the desired commit mkdir -p build cd build ~/miniconda3/envs/asp_deps/bin/cmake .. \ @@ -339,7 +333,7 @@ Building VisionWorkbench and ASP on OSX (just as above, but omitting the compile ~/miniconda3/envs/asp_deps/bin/git clone \ git@github.com:visionworkbench/visionworkbench.git cd visionworkbench - git checkout 2.7.0 # check out the desired commit + git checkout 3.0.0 # check out the desired commit mkdir -p build cd build ~/miniconda3/envs/asp_deps/bin/cmake .. \ @@ -353,7 +347,7 @@ Building VisionWorkbench and ASP on OSX (just as above, but omitting the compile ~/miniconda3/envs/asp_deps/bin/git clone \ git@github.com:NeoGeographyToolkit/StereoPipeline.git cd StereoPipeline - git checkout 2.7.0 # check out the desired commit + git checkout 3.0.0 # check out the desired commit mkdir -p build cd build ~/miniconda3/envs/asp_deps/bin/cmake .. \ diff --git a/NEWS.rst b/NEWS.rst index 4f24b2544..3a6f5f7e0 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,12 +1,16 @@ -RELEASE 3.0.0, upcoming! +RELEASE 3.0.0, July 27, 2021 +---------------------------- New functionality: * Added new stereo algorithms: MGM (original author implementation), - OpenCV SGBM, LIBELAS, MSMW, MSMW2, and OpenCV BM. + OpenCV SGBM, LIBELAS, MSMW, MSMW2, and OpenCV BM to complement + the existing ASP block matching, SGM, and MGM algorithms. See + https://stereopipeline.readthedocs.io/en/latest/next_steps.html + for usage. These will be further refined in subsequent releases. * Added the ability to perform piecewise local epipolar alignment for the input images, to be followed by a 1D disparity search (for non-mapprojected images), as suggested by the Satellite Stereo - Pipeline (S2P) approach. + Pipeline (S2P) approach. This is still somewhat experimental. * Added the ability for a user to plug into ASP any desired stereo program working on image clips to which epipolar alignment has been applied (as is customary in the computer vision community) @@ -27,7 +31,8 @@ isis: * Ship a full Python 3.6 runtime, as expected by ISIS. csm: - * Upgraded to USGSCSM 1.5.2. + * Upgraded to USGSCSM 1.5.2 (ASP's own build of it has an additional + bugfix for LRO NAC not present in the conda-forge package). * Validated the CSM model for CTX, HiRISE, and LRO NAC cameras. * Added documentation for how to create CSM models from .cub cameras. diff --git a/RELEASEGUIDE b/RELEASEGUIDE index df284cea9..52658bb3f 100644 --- a/RELEASEGUIDE +++ b/RELEASEGUIDE @@ -108,19 +108,22 @@ The resulting release tarballs will go to BinaryBuilder/asp_tarballs. 8.) Commit and tag the release in the VW and ASP repos. Example: - git tag 2.7.0 + git tag 3.0.0 Push the tags to the remote server with: - git push origin 2.7.0 # commit to your branch - git push god 2.7.0 # commit to main branch + git push origin 3.0.0 # commit to your branch + git push god 3.0.0 # commit to main branch + +(Here it is assumed that 'origin' points to your own fork and 'god' +points to the parent repository.) If more commits were made and it is desired to apply this tag to a different commit, first remove the exiting tag with: - git tag -d 2.7.0 - git push origin :refs/tags/2.7.0 - git push god :refs/tags/2.7.0 + git tag -d 3.0.0 + git push origin :refs/tags/3.0.0 + git push god :refs/tags/3.0.0 9.) Upload the builds and the pdf documentation to GitHub, in the release area. @@ -157,9 +160,9 @@ development, by updating the version number in: in both the VW and ASP repositories. -If you just released version 2.7.0, we expect that the next feature -release will be 2.8.0, if a major release, or 2.7.1 if a minor -release, so the version tag should be updated to 2.8.0-alpha in +If you just released version 3.0.0, we expect that the next feature +release will be 3.1.0, if a major release, or 3.0.1 if a minor +release, so the version tag should be updated to 3.1.0-alpha in anticipation (see https://semver.org for guidance). 13.) Reflect any changes in release policy by modifying this document. diff --git a/docs/next_steps.rst b/docs/next_steps.rst index 78ad48dc2..a8148dba0 100644 --- a/docs/next_steps.rst +++ b/docs/next_steps.rst @@ -31,22 +31,43 @@ This invokes block-matching stereo with parabola subpixel mode, which can be fast but not of high quality. The best results are likely produced with:: - parallel_stereo --alignment-method local_epipolar \ + parallel_stereo --alignment-method affineepipolar \ --stereo-algorithm asp_mgm --subpixel-mode 3 \ which uses ASP's implementation of MGM (:numref:`asp_sgm`). -ASP also ships with a handful of third-party stereo algorithms, such +ASP also implements local alignment, when the input images are split +into tiles (with overlap) and locally aligned. This makes it possible +to use third-party algorithms in addition to the ones ASP implements. + +This mode is still in development, and best results with it, for the +moment, are obtained with ASP's own MGM algorithm, if invoked as +follows:: + + parallel_stereo --alignment-method local_epipolar \ + --stereo-algorithm asp_mgm \ + + +ASP also ships with the following third-party stereo algorithms: MGM (original author implementation), OpenCV SGBM, LIBELAS, MSMW, MSMW2, and OpenCV BM. For more details see :numref:`stereo_algos`. -For example, the external MGM implementation can be called as follows:: +For example, the external MGM implementation can be called as:: parallel_stereo --alignment-method local_epipolar \ --stereo-algorithm mgm \ + --corr-tile-size 512 --sgm-collar-size 256 \ + +As before, this mode is still experimental. +Above we used tiles of size 512 pixels with an extra padding of 256 +pixels on each side, for a total size of 1024 pixels, to avoid using +too much memory. The defaults in ``parallel_stereo`` are double these +values, which work well with ASP's MGM which is more conservative with +its use of memory but can be too much for this other implementation. + It is suggested to not specify here ``--subpixel-mode``, in which case it will use MGM's own implementation. Using ``--subpixel-mode 3`` will refine that result using ASP's subpixel implementation. Using diff --git a/docs/stereo_algorithms.rst b/docs/stereo_algorithms.rst index e9001ca98..b0b31ac9b 100644 --- a/docs/stereo_algorithms.rst +++ b/docs/stereo_algorithms.rst @@ -372,9 +372,10 @@ SGBM options Choose among several flavors of SGBM. Use ``sgbm`` for the less-memory intensive mode. Setting this mode to ``hh`` will run the full-scale two-pass dynamic programming algorithm. It will - consume O(image_width * image_height * num_disparities) bytes and - it tends to crash for a large input disparity range. Use ``3way`` - for yet another flavor which OpenCV does not document. + consume O(image_width * image_height * num_disparities) bytes of + memory, and may run out of memory for a large input + disparity range. Use ``3way`` for yet another flavor which OpenCV + does not document. -block_size (default = 3): Block size to use to match blocks from left to right image. It @@ -537,6 +538,11 @@ follows. options being used, as well as what the input and output files are. +-debug_images (default = 0): + If non-zero, save the images to disk right before being passed + to libelas (the images are thus padded, aligned, and scaled + to have byte pixels). + .. _msmw: Multi-Scale Multi-Window stereo matching diff --git a/docs/stereodefault.rst b/docs/stereodefault.rst index 5e2a4443a..90df15ef1 100644 --- a/docs/stereodefault.rst +++ b/docs/stereodefault.rst @@ -38,8 +38,8 @@ ip-per-image ip-detect-method What type of interest point detection algorithm to use for image - alignment. 0 = Custom OBAloG implementation (default) 1 = SIFT - implementation from OpenCV 2 = ORB implementation from OpenCV If + alignment. 0 = Custom OBAloG implementation (default), 1 = SIFT + implementation from OpenCV, 2 = ORB implementation from OpenCV. If the default method does not perform well, try out one of the other two methods. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 363f54c0a..d0418475b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,8 +21,8 @@ project (StereoPipeline) # The line below is used by the docs/ so don't change it # without testing the result. Versioning is based on https://semver.org -set(PACKAGE_VERSION "2.7.0") -#set(PACKAGE_VERSION "2.7.1-alpha") +set(PACKAGE_VERSION "3.0.0") +#set(PACKAGE_VERSION "3.0.1-alpha") set(PACKAGE_NAME "NASA Ames Stereo Pipeline") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "scott.t.mcmichael@nasa.gov, oleg.alexandrov@nasa.gov") diff --git a/src/asp/Core/AffineEpipolar.cc b/src/asp/Core/AffineEpipolar.cc index 673cfc008..7ef53782d 100644 --- a/src/asp/Core/AffineEpipolar.cc +++ b/src/asp/Core/AffineEpipolar.cc @@ -18,12 +18,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include @@ -138,7 +140,7 @@ namespace asp { } /// This function can match points in any container that supports - /// the size() and operator[] methods. The container is usually a + /// the size() and operator[] methods. The container is usually a /// vw::Vector<>, but you could substitute other classes here as /// well. template @@ -190,22 +192,35 @@ namespace asp { solve_x_shear(ip1, ip2, left_matrix, right_matrix); // Work out the ideal render size - BBox2i output_bbox, right_bbox; - output_bbox.grow(subvector(left_matrix * Vector3(0, 0, 1), 0, 2)); - output_bbox.grow(subvector(left_matrix * Vector3(m_ldims.x(), 0, 1), 0, 2)); - output_bbox.grow(subvector(left_matrix * Vector3(m_ldims.x(), m_ldims.y(), 1), 0, 2)); - output_bbox.grow(subvector(left_matrix * Vector3(0, m_ldims.y(), 1), 0, 2)); + BBox2i left_bbox, right_bbox; + left_bbox.grow(subvector(left_matrix * Vector3(0, 0, 1), 0, 2)); + left_bbox.grow(subvector(left_matrix * Vector3(m_ldims.x(), 0, 1), 0, 2)); + left_bbox.grow(subvector(left_matrix * Vector3(m_ldims.x(), m_ldims.y(), 1), 0, 2)); + left_bbox.grow(subvector(left_matrix * Vector3(0, m_ldims.y(), 1), 0, 2)); right_bbox.grow(subvector(right_matrix * Vector3(0, 0, 1), 0, 2)); right_bbox.grow(subvector(right_matrix * Vector3(m_rdims.x(), 0, 1), 0, 2)); right_bbox.grow(subvector(right_matrix * Vector3(m_rdims.x(), m_rdims.y(), 1), 0, 2)); right_bbox.grow(subvector(right_matrix * Vector3(0, m_rdims.y(), 1), 0, 2)); + // TODO(oalexan1): There is room for improvement below, + // but the attempts tried below (commented out) need + // a lot more testing. Also, the current outlier filtering + // is apparently not foolproof yet. + + // Ensure that the transforms map the interest points to points + // with positive x and y, we will need that when later the + // transformed images are computed. if (m_crop_to_shared_area) { - output_bbox.crop(right_bbox); - left_matrix (0, 2) -= output_bbox.min().x(); - right_matrix(0, 2) -= output_bbox.min().x(); - left_matrix (1, 2) -= output_bbox.min().y(); - right_matrix(1, 2) -= output_bbox.min().y(); + left_bbox.crop(right_bbox); + left_matrix (0, 2) -= left_bbox.min().x(); + left_matrix (1, 2) -= left_bbox.min().y(); + right_matrix(0, 2) -= left_bbox.min().x(); + right_matrix(1, 2) -= left_bbox.min().y(); +// } else { +// left_matrix (0, 2) -= left_bbox.min().x(); +// left_matrix (1, 2) -= left_bbox.min().y(); +// right_matrix(0, 2) -= right_bbox.min().x(); +// right_matrix(1, 2) -= right_bbox.min().y(); } // Concatenate these into the answer @@ -214,9 +229,14 @@ namespace asp { submatrix(T, 0, 3, 3, 3) = right_matrix; // Also save the domain after alignment - T(0, 6) = output_bbox.width(); - T(1, 6) = output_bbox.height(); - + // if (m_crop_to_shared_area) { + T(0, 6) = left_bbox.width(); + T(1, 6) = left_bbox.height(); +// }else{ +// T(0, 6) = std::max(left_bbox.width(), right_bbox.width()); +// T(1, 6) = std::max(left_bbox.height(), right_bbox.height()); +// } + return T; } }; @@ -322,6 +342,75 @@ namespace asp { << "aligned inlier interest points is " << max_err << " pixels." << std::endl; + // This needs more testing + if (false && !crop_to_shared_area) { + // The bounds of the transforms have been a bit too generous. Tighten them to the bounding + // box of the IP. + // TODO(oalexan1): Remove outliers here! + + // Apply local alignment to inlier ip and estimate the search range + vw::HomographyTransform left_local_trans (left_matrix); + vw::HomographyTransform right_local_trans(right_matrix); + + // Find the transformed IP + std::vector left_trans_local_ip; + std::vector right_trans_local_ip; + + for (size_t it = 0; it < inlier_indices.size(); it++) { + int i = inlier_indices[it]; + Vector2 left_pt (ip1[i].x, ip1[i].y); + Vector2 right_pt(ip2[i].x, ip2[i].y); + + left_pt = left_local_trans.forward(left_pt); + right_pt = right_local_trans.forward(right_pt); + + // First copy all the data from the input ip, then apply the transform + left_trans_local_ip.push_back(ip1[i]); + right_trans_local_ip.push_back(ip2[i]); + left_trans_local_ip.back().x = left_pt.x(); + left_trans_local_ip.back().y = left_pt.y(); + right_trans_local_ip.back().x = right_pt.x(); + right_trans_local_ip.back().y = right_pt.y(); + } + + // Filter outliers + Vector2 params = stereo_settings().local_alignment_outlier_removal_params; + if (params[0] < 100.0) + asp::filter_ip_by_disparity(params[0], params[1], + left_trans_local_ip, right_trans_local_ip); + + vw::BBox2i left_bbox, right_bbox; + for (size_t i = 0; i < left_trans_local_ip.size(); i++) { + + Vector2 left_pt (left_trans_local_ip[i].x, left_trans_local_ip[i].y); + Vector2 right_pt(right_trans_local_ip[i].x, right_trans_local_ip[i].y); + + left_bbox.grow(left_pt); + right_bbox.grow(right_pt); + } + + // TODO(oalexan1): Run a large scale test to see if this is necessary. + left_bbox.expand(50); + right_bbox.expand(50); + + // The way the transforms were created, there is no good reason + // for transformed ip to have negative values. + left_bbox.min().x() = std::max(left_bbox.min().x(), 0); + left_bbox.min().y() = std::max(left_bbox.min().y(), 0); + right_bbox.min().x() = std::max(right_bbox.min().x(), 0); + right_bbox.min().y() = std::max(right_bbox.min().y(), 0); + + // Adjust the domains of the transforms to the bounding boxes of + // the interest points. + left_matrix (0, 2) -= left_bbox.min().x(); + left_matrix (1, 2) -= left_bbox.min().y(); + right_matrix(0, 2) -= right_bbox.min().x(); + right_matrix(1, 2) -= right_bbox.min().y(); + + trans_crop_box[0] = std::max(left_bbox.width(), right_bbox.width()); + trans_crop_box[1] = std::max(left_bbox.height(), right_bbox.height()); + } + // Optionally return the inliers if (inliers_ptr != NULL) *inliers_ptr = inlier_indices; diff --git a/src/asp/Core/LocalAlignment.cc b/src/asp/Core/LocalAlignment.cc index ead77bf9c..df07e98be 100644 --- a/src/asp/Core/LocalAlignment.cc +++ b/src/asp/Core/LocalAlignment.cc @@ -40,6 +40,9 @@ using namespace vw; namespace fs = boost::filesystem; +// Debug logic +#define DEBUG_IP 0 + namespace asp { // Algorithm to perform local alignment. Approach: @@ -127,7 +130,11 @@ namespace asp { // Ensure we do not exceed the image bounds left_trans_crop_win.crop(vw::bounding_box(left_globally_aligned_image)); - + + // TODO(oalexan1): Here need find the bounding box of the valid data + // and if necessary grow left_trans_crop_win to make the bounding box + // of the valid data be as wide and tall as a full tile. + if (left_trans_crop_win.width() == width && left_trans_crop_win.height() == height) break; } @@ -173,10 +180,10 @@ namespace asp { right_trans_ip.back().y = right_pt.y(); } -#if 0 +#if DEBUG_IP std::string out_match_filename = vw::ip::match_filename(opt.out_prefix + "-tile", "L.tif", "R.tif"); - vw_out() << "Writing match file: " << out_match_filename << ".\n"; + vw_out() << "Writing match file: " << out_match_filename << "\n"; vw::ip::write_binary_match_file(out_match_filename, left_trans_ip, right_trans_ip); #endif @@ -206,14 +213,14 @@ namespace asp { "" // do not save any match file to disk ); -#if 0 // Debug logic +#if DEBUG_IP { vw::cartography::GeoReference georef; bool has_georef = false, has_nodata = true; float nan_nodata = std::numeric_limits::quiet_NaN(); std::string left_crop = opt.out_prefix + "-" + "left-crop.tif"; - vw_out() << "\t--> Writing: " << left_crop << ".\n"; + vw_out() << "\t--> Writing: " << left_crop << "\n"; block_write_gdal_image(left_crop, crop(left_globally_aligned_image, left_trans_crop_win), has_georef, georef, @@ -221,7 +228,7 @@ namespace asp { TerminalProgressCallback("asp","\t Left: ")); std::string right_crop = opt.out_prefix + "-" + "right-crop.tif"; - vw_out() << "\t--> Writing: " << right_crop << ".\n"; + vw_out() << "\t--> Writing: " << right_crop << "\n"; block_write_gdal_image(right_crop, crop(right_globally_aligned_image, right_trans_crop_win), has_georef, georef, @@ -230,7 +237,7 @@ namespace asp { std::string local_match_filename = vw::ip::match_filename(opt.out_prefix, left_crop, right_crop); - vw_out() << "Writing match file: " << local_match_filename << ".\n"; + vw_out() << "Writing match file: " << local_match_filename << "\n"; vw::ip::write_binary_match_file(local_match_filename, left_local_ip, right_local_ip); } #endif @@ -345,13 +352,13 @@ namespace asp { std::string left_tile = "left-aligned-tile.tif"; std::string right_tile = "right-aligned-tile.tif"; left_aligned_file = opt.out_prefix + "-" + left_tile; - vw_out() << "\t--> Writing: " << left_aligned_file << ".\n"; + vw_out() << "\t--> Writing: " << left_aligned_file << "\n"; block_write_gdal_image(left_aligned_file, left_trans_clip, has_georef, georef, has_aligned_nodata, nan_nodata, opt, TerminalProgressCallback("asp","\t Left: ")); right_aligned_file = opt.out_prefix + "-" + right_tile; - vw_out() << "\t--> Writing: " << right_aligned_file << ".\n"; + vw_out() << "\t--> Writing: " << right_aligned_file << "\n"; block_write_gdal_image(right_aligned_file, right_trans_clip, has_georef, georef, @@ -365,8 +372,6 @@ namespace asp { vw::HomographyTransform left_local_trans (left_local_mat); vw::HomographyTransform right_local_trans(right_local_mat); -#define DEBUG_IP 0 - // Find the transformed IP std::vector left_trans_local_ip; std::vector right_trans_local_ip; @@ -390,7 +395,7 @@ namespace asp { #if DEBUG_IP // TODO(oalexan1): Some of these IP can still have outliers which // can result in an unreasonably large disparity range. - std::cout << "Diff is " << right_pt - left_pt << std::endl; + // std::cout << "Diff is " << right_pt - left_pt << std::endl; #endif } @@ -411,7 +416,7 @@ namespace asp { #if DEBUG_IP std::string local_aligned_match_filename = vw::ip::match_filename(opt.out_prefix, left_tile, right_tile); - vw_out() << "Writing match file: " << local_aligned_match_filename << ".\n"; + vw_out() << "Writing match file: " << local_aligned_match_filename << "\n"; vw::ip::write_binary_match_file(local_aligned_match_filename, left_trans_local_ip, right_trans_local_ip); #endif @@ -446,7 +451,12 @@ namespace asp { return out_box; } + + // TODO(oalexan1): if left pix or right pix is invalid in the image, + // the disparity must be invalid! Test with OpenCV SGBM, libelas, and mgm! + // Also implement for unalign_2d_disparity. + // DO the same for unalign_2d_disparity. // Go from 1D disparity of images with affine epipolar alignment to the 2D // disparity by undoing the transforms that applied this alignment. void unalign_1d_disparity(// Inputs @@ -856,7 +866,7 @@ namespace asp { ASPGlobalOptions const& opt, std::string const& disparity_file, // Output - vw::ImageViewRef & out_disp) { + vw::ImageView & out_disp) { DiskImageView left(left_file); DiskImageView right(right_file); diff --git a/src/asp/Core/LocalAlignment.h b/src/asp/Core/LocalAlignment.h index bf30da9cf..4c0ea0dea 100644 --- a/src/asp/Core/LocalAlignment.h +++ b/src/asp/Core/LocalAlignment.h @@ -123,7 +123,7 @@ namespace asp { ASPGlobalOptions const& opt, std::string const& disparity_file, // Output - vw::ImageViewRef & out_disp); + vw::ImageView & out_disp); } // end namespace asp diff --git a/src/asp/Tools/parallel_stereo b/src/asp/Tools/parallel_stereo index 267c89a40..02d5fb93e 100644 --- a/src/asp/Tools/parallel_stereo +++ b/src/asp/Tools/parallel_stereo @@ -742,7 +742,6 @@ if __name__ == '__main__': # to the correlation tile size. opt.job_size_w = corr_tile_size opt.job_size_h = opt.job_size_w - print ('Setting tile size (before collar addition) to: ' + str(opt.job_size_w)) else: # If the user specified these, they better be equal, and equal to corr_tile_size if opt.job_size_h != opt.job_size_w: @@ -767,6 +766,10 @@ if __name__ == '__main__': print("Making --corr-tile-size the minimum of --job-size-h and --job-size-w, " \ "that is equal to " + str(corr_tile_size) + ".") + print ('Using tiles (before collar addition) of ' + str(opt.job_size_w) + \ + ' x ' + str(opt.job_size_h) + ' pixels.') + print('Using a collar (padding) for each tile of ' + settings['collar_size'][0] + ' pixels.') + # TODO(oalexan1): The giant block below needs to be broken up into # several functions named parent_run(), child_run(), and # multiview_run(). Careful testing will be needed. diff --git a/src/asp/Tools/stereo_corr.cc b/src/asp/Tools/stereo_corr.cc index 533325992..7b98b9c8d 100644 --- a/src/asp/Tools/stereo_corr.cc +++ b/src/asp/Tools/stereo_corr.cc @@ -1414,6 +1414,21 @@ void stereo_correlation_1D(ASPGlobalOptions& opt) { cost_mode, corr_timeout, seconds_per_op), bounding_box(left_image)); +#if 0 // For debugging + // Write the aligned 2D disparity to disk + vw::cartography::GeoReference georef; + bool has_georef = false; + bool has_nodata = false; + double nodata = std::numeric_limits::quiet_NaN(); + std::string aligned_disp_file = opt.out_prefix + "-aligned-disparity_2D.tif"; + vw_out() << "Writing: " << aligned_disp_file << "\n"; + vw::cartography::block_write_gdal_image(aligned_disp_file, aligned_disp_2d, + has_georef, georef, + has_nodata, nan, opt, + TerminalProgressCallback + ("asp", "\t--> Disparity :")); +#endif + // Undo the alignment asp::unalign_2d_disparity(// Inputs aligned_disp_2d, @@ -1426,7 +1441,7 @@ void stereo_correlation_1D(ASPGlobalOptions& opt) { // External algorithms using 1D disparity - vw::ImageViewRef aligned_disp; + vw::ImageView aligned_disp; // Set the default options for all algorithms @@ -1627,6 +1642,42 @@ void stereo_correlation_1D(ASPGlobalOptions& opt) { save_empty_disparity(opt, tile_crop_win, out_disp_file); return; } + + if (0) { + // This needs more testing. + // TODO(oalexan1): Make this into a function. Filter the disparity. + // Wipe disparities which map to an invalid pixel + float nan = std::numeric_limits::quiet_NaN(); + ImageView>> left_masked_image + = vw::create_mask(DiskImageView>(left_aligned_file), nan); + ImageView>> right_masked_image + = vw::create_mask(DiskImageView>(right_aligned_file), nan); + + // invalid value for a PixelMask + PixelMask> nodata_mask = PixelMask>(); + ImageViewRef>> interp_right_masked_image + = interpolate(right_masked_image, BilinearInterpolation(), + ValueEdgeExtension>>(nodata_mask)); + + for (int col = 0; col < left_masked_image.cols(); col++) { + for (int row = 0; row < left_masked_image.rows(); row++) { + + if (std::isnan(aligned_disp(col, row))) + continue; // already nan + + // If the left pixel is not valid, the disparity cannot be valid + if (!is_valid(left_masked_image(col, row))) { + aligned_disp(col, row) = nan; + continue; + } + + // If the right pixel is not valid, the disparity cannot be valid + Vector2 right_pix(col + aligned_disp(col, row), row); + if (!is_valid(interp_right_masked_image(right_pix.x(), right_pix.y()))) + aligned_disp(col, row) = nan; + } + } + } // Undo the alignment asp::unalign_1d_disparity(// Inputs