Skip to content
Browse files

session: Add DG Map RPC Session

This is a session specifically made so that we don't use a
TransformRef. This allows multiple copies of RPCMapTransform to be
created for each thread (w/ TransformRef a single copy would be hidden
behind a shared ptr). These multiple copies thus allow RPCMapTransform
to cache its DEM usage ... and thus Triangulation happens faster.
  • Loading branch information...
1 parent 81477d7 commit a8fec02b9a6e6e87d99de21f50580ef53559a0ae Zack Moratto committed Apr 27, 2013
View
1 .gitignore
@@ -85,6 +85,7 @@ src/asp/IsisIO/tests/TestIsisCameraModel
# Sessions
src/asp/Sessions/tests/TestInstantiation
src/asp/Sessions/tests/TestStereoSessionDG
+src/asp/Sessions/tests/TestStereoSessionDGMapRPC
src/asp/Sessions/tests/TestStereoSessionRPC
# Tools
View
1 configure.ac
@@ -498,6 +498,7 @@ AC_CONFIG_FILES([ \
src/asp/MPI/Makefile \
src/asp/Makefile \
src/asp/Sessions/DG/Makefile \
+ src/asp/Sessions/DGMapRPC/Makefile \
src/asp/Sessions/ISIS/Makefile \
src/asp/Sessions/Makefile \
src/asp/Sessions/NadirPinhole/Makefile \
View
3 src/asp/Sessions.h
@@ -26,7 +26,8 @@
#include <asp/Sessions/ISIS/StereoSessionIsis.h>
#endif
+#include <asp/Sessions/DG/StereoSessionDG.h>
+#include <asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.h>
#include <asp/Sessions/NadirPinhole/StereoSessionNadirPinhole.h>
#include <asp/Sessions/Pinhole/StereoSessionPinhole.h>
-#include <asp/Sessions/DG/StereoSessionDG.h>
#include <asp/Sessions/RPC/StereoSessionRPC.h>
View
237 src/asp/Sessions/DG/StereoSessionDG.cc
@@ -25,9 +25,8 @@
#include <asp/Core/AffineEpipolar.h>
#include <asp/Sessions/DG/LinescanDGModel.h>
#include <asp/Sessions/DG/StereoSessionDG.h>
-#include <asp/Sessions/DG/XML.h>
#include <asp/Sessions/RPC/RPCModel.h>
-#include <asp/Sessions/RPC/RPCMapTransform.h>
+#include <asp/Sessions/DG/XML.h>
// Vision Workbench
#include <vw/Camera/Extrinsics.h>
@@ -40,19 +39,16 @@
#include <iostream>
#include <string>
-// Other
-#include <xercesc/dom/DOM.hpp>
-#include <xercesc/parsers/XercesDOMParser.hpp>
-#include <xercesc/sax/HandlerBase.hpp>
-#include <xercesc/util/PlatformUtils.hpp>
-#include <xercesc/util/XMLString.hpp>
-
// Boost
#include <boost/date_time/posix_time/posix_time.hpp>
+// Other
+#include <xercesc/util/PlatformUtils.hpp>
+
using namespace vw;
using namespace asp;
using namespace xercesc;
+
namespace pt = boost::posix_time;
namespace fs = boost::filesystem;
@@ -75,91 +71,16 @@ class SecondsFrom {
};
-// Helper functor that converts projected pixel indices and height
-// value to unprojected pixel indices.
-class OriginalCameraIndex : public ReturnFixedType<Vector2f> {
- RPCModel m_rpc;
- BBox2i m_image_boundaries;
-public:
- OriginalCameraIndex( RPCModel const& rpc,
- BBox2i const& bbox ) : m_rpc(rpc),
- m_image_boundaries(bbox) {}
-
- Vector2f operator()( Vector3 const& point ) const {
-
- const double nan = std::numeric_limits<double>::quiet_NaN();
-
- if ( point == Vector3() )
- return Vector2f(nan, nan);
-
- Vector2f result = m_rpc.point_to_pixel( point );
- if ( m_image_boundaries.contains( result ) )
- return result;
-
- return Vector2f(nan, nan);
- }
-
-};
-
namespace asp {
- // Xerces-C initialize
- StereoSessionDG::StereoSessionDG() : m_rpc_map_projected(false) {
+ // These are initializers and closers for Xercesc since we use it to
+ // read our RPC models.
+ StereoSessionDG::StereoSessionDG() {
XMLPlatformUtils::Initialize();
}
- // Initializer to determine what kind of input we have.
- void StereoSessionDG::initialize(BaseOptions const& options,
- std::string const& left_image_file,
- std::string const& right_image_file,
- std::string const& left_camera_file,
- std::string const& right_camera_file,
- std::string const& out_prefix,
- std::string const& input_dem,
- std::string const& extra_argument1,
- std::string const& extra_argument2,
- std::string const& extra_argument3 ) {
- StereoSession::initialize( options, left_image_file,
- right_image_file, left_camera_file,
- right_camera_file, out_prefix,
- input_dem, extra_argument1,
- extra_argument2, extra_argument3 );
-
- // Is there a possible DEM?
- if ( !input_dem.empty() ) {
- boost::scoped_ptr<RPCModel> model1, model2;
- // Try and pull RPC Camera Models from left and right images.
- try {
- model1.reset( new RPCModel(left_image_file) );
- model2.reset( new RPCModel(right_image_file) );
- } catch ( NotFoundErr const& err ) {}
-
- // If the above failed to load the RPC Model, try from the XML.
- if ( !model1.get() || !model2.get() ) {
- try {
- RPCXML rpc_xml;
- rpc_xml.read_from_file( left_camera_file );
- model1.reset( new RPCModel( *rpc_xml.rpc_ptr() ) ); // Copy the ptr
- rpc_xml.read_from_file( right_camera_file );
- model2.reset( new RPCModel( *rpc_xml.rpc_ptr() ) );
- } catch ( IOErr const& err ) {
- // Just give up if it is not there.
- vw_out(WarningMessage) << "Could not read the RPC models. Ignoring the input DEM \"" << input_dem << "\".";
- return;
- }
- }
-
- // Double check that we can read the DEM and that it has
- // cartographic information.
- if ( !fs::exists( input_dem ) )
- vw_throw( ArgumentErr() << "StereoSessionDG: DEM \"" << input_dem
- << "\" does not exist." );
-
- // Verify that center of our lonlat boundaries from the RPC models
- // actually projects into the DEM. (?)
-
- m_rpc_map_projected = true;
- }
+ StereoSessionDG::~StereoSessionDG() {
+ XMLPlatformUtils::Terminate();
}
// Provide our camera model
@@ -247,33 +168,32 @@ namespace asp {
);
}
+ bool StereoSessionDG::ip_matching( std::string const& match_filename,
+ double left_nodata_value,
+ double right_nodata_value ) {
+ // Load the unmodified images
+ DiskImageView<float> left_disk_image( m_left_image_file ),
+ right_disk_image( m_right_image_file );
+
+ boost::shared_ptr<camera::CameraModel> left_cam, right_cam;
+ camera_models( left_cam, right_cam );
+
+ return
+ ip_matching_w_alignment( left_cam.get(), right_cam.get(),
+ left_disk_image, right_disk_image,
+ cartography::Datum("WGS84"), match_filename,
+ left_nodata_value,
+ right_nodata_value);
+ }
+
StereoSessionDG::left_tx_type
StereoSessionDG::tx_left() const {
Matrix<double> tx = math::identity_matrix<3>();
if ( stereo_settings().alignment_method == "homography" ||
stereo_settings().alignment_method == "affineepipolar" ) {
read_matrix( tx, m_out_prefix + "-align-L.exr" );
}
- if ( m_rpc_map_projected ) {
- cartography::GeoReference dem_georef, image_georef;
- if (!read_georeference( dem_georef, m_input_dem ) )
- vw_throw( ArgumentErr() << "The DEM \"" << m_input_dem << "\" lacks georeferencing information.");
- if (!read_georeference( image_georef, m_left_image_file ) )
- vw_throw( ArgumentErr() << "The image \"" << m_left_image_file << "\" lacks georeferencing information.");
-
- // Load DEM rsrc. RPCMapTransform is casting to float internally
- // no matter what the original type of the DEM file was.
- boost::shared_ptr<DiskImageResource>
- dem_rsrc( DiskImageResource::open( m_input_dem ) );
-
- // This composes the two transforms as it is possible to do
- // homography and affineepipolar alignment options with map
- // projected imagery.
- return TransformRef( compose( RPCMapTransform(*read_rpc_model(m_left_image_file, m_left_camera_file),
- image_georef, dem_georef, dem_rsrc),
- HomographyTransform(tx) ) );
- }
- return TransformRef( HomographyTransform( tx ) );
+ return left_tx_type( tx );
}
StereoSessionDG::right_tx_type
@@ -283,26 +203,7 @@ namespace asp {
stereo_settings().alignment_method == "affineepipolar" ) {
read_matrix( tx, m_out_prefix + "-align-R.exr" );
}
- if ( m_rpc_map_projected ) {
- cartography::GeoReference dem_georef, image_georef;
- if (!read_georeference( dem_georef, m_input_dem ) )
- vw_throw( ArgumentErr() << "The DEM \"" << m_input_dem << "\" lacks georeferencing information.");
- if (!read_georeference( image_georef, m_right_image_file ) )
- vw_throw( ArgumentErr() << "The image \"" << m_right_image_file << "\" lacks georeferencing information.");
-
- // Load DEM rsrc. RPCMapTransform is casting to float internally
- // no matter what the original type of the DEM file was.
- boost::shared_ptr<DiskImageResource>
- dem_rsrc( DiskImageResource::open( m_input_dem ) );
-
- // This composes the two transforms as it is possible to do
- // homography and affineepipolar alignment options with map
- // projected imagery.
- return TransformRef( compose( RPCMapTransform(*read_rpc_model(m_right_image_file, m_right_camera_file),
- image_georef, dem_georef, dem_rsrc),
- HomographyTransform(tx) ) );
- }
- return TransformRef( HomographyTransform( tx ) );
+ return right_tx_type( tx );
}
void StereoSessionDG::pre_preprocessing_hook(std::string const& left_input_file,
@@ -362,52 +263,16 @@ namespace asp {
= ip::match_filename(m_out_prefix, left_input_file, right_input_file);
if (!fs::exists(match_filename)) {
- bool inlier = false;
-
- boost::shared_ptr<camera::CameraModel> left_cam, right_cam;
- camera_models( left_cam, right_cam );
- if ( m_rpc_map_projected ) {
- // We'll make the assumption that the user has map
- // projected the images to the same scale. If they
- // haven't, below would be the ideal but lossy method.
- // inlier =
- // homography_ip_matching( left_disk_image, right_disk_image,
- // match_filename );
- boost::scoped_ptr<RPCModel>
- left_rpc( read_rpc_model( m_left_image_file, m_left_camera_file ) ),
- right_rpc( read_rpc_model( m_right_image_file, m_right_camera_file ) );
- cartography::GeoReference left_georef, right_georef, dem_georef;
- read_georeference( left_georef, m_left_image_file );
- read_georeference( right_georef, m_right_image_file );
- read_georeference( dem_georef, m_input_dem );
- boost::shared_ptr<DiskImageResource>
- dem_rsrc( DiskImageResource::open( m_input_dem ) );
- TransformRef
- left_tx( RPCMapTransform( *left_rpc, left_georef,
- dem_georef, dem_rsrc ) ),
- right_tx( RPCMapTransform( *right_rpc, right_georef,
- dem_georef, dem_rsrc ) );
- inlier =
- ip_matching( left_cam.get(), right_cam.get(),
- left_disk_image, right_disk_image,
- cartography::Datum("WGS84"), match_filename,
- left_nodata_value,
- right_nodata_value,
- left_tx, right_tx, false );
- } else {
- inlier =
- ip_matching_w_alignment( left_cam.get(), right_cam.get(),
- left_disk_image, right_disk_image,
- cartography::Datum("WGS84"), match_filename,
- left_nodata_value,
- right_nodata_value);
- }
-
+ // This is calling an internal virtualized method.
+ bool inlier =
+ ip_matching( match_filename,
+ left_nodata_value,
+ right_nodata_value );
if ( !inlier ) {
fs::remove( match_filename );
vw_throw( IOErr() << "Unable to match left and right images." );
}
- }else{
+ } else {
vw_out() << "\t--> Using cached match file: " << match_filename << "\n";
}
@@ -503,36 +368,6 @@ namespace asp {
apply_mask(crop(edge_extend(Rimg, ConstantEdgeExtension()), bounding_box(Limg)), output_nodata),
output_nodata, m_options,
TerminalProgressCallback("asp","\t R: ") );
-
- // We could write the LUT images at this point, but I'm going to
- // let triangulation render them on the fly. This will save a lot
- // of storage and possibly make the triangulation faster since we
- // don't mutex on these massive files
- }
-
- // Helper function to read RPC models.
- RPCModel* StereoSessionDG::read_rpc_model( std::string const& image_file,
- std::string const& camera_file ) {
- RPCModel* rpc_model = NULL;
- try {
- rpc_model = new RPCModel( image_file );
- } catch ( NotFoundErr const& err ) {}
-
- if ( !rpc_model ) {
- RPCXML rpc_xml;
- rpc_xml.read_from_file( camera_file );
- rpc_model = new RPCModel( *rpc_xml.rpc_ptr() ); // Copy the value
-
- // We don't catch an error here because the User will need to
- // know of a failure at this point. We previously opened the
- // XML safely before.
- }
- return rpc_model;
- }
-
- // Xerces-C terminate
- StereoSessionDG::~StereoSessionDG() {
- XMLPlatformUtils::Terminate();
}
}
View
34 src/asp/Sessions/DG/StereoSessionDG.h
@@ -29,36 +29,26 @@
namespace asp {
- // Forward declaration
- class RPCModel;
-
class StereoSessionDG : public StereoSession {
public:
StereoSessionDG();
virtual ~StereoSessionDG();
- // Initializer that determines if our input images are map
- // projected or if this is just a straight Digitial Globe session.
- virtual void initialize(BaseOptions const& options,
- std::string const& left_image_file,
- std::string const& right_image_file,
- std::string const& left_camera_file,
- std::string const& right_camera_file,
- std::string const& out_prefix,
- std::string const& input_dem,
- std::string const& extra_argument1,
- std::string const& extra_argument2,
- std::string const& extra_argument3);
-
// Produces a camera model from the images
virtual boost::shared_ptr<vw::camera::CameraModel>
camera_model( std::string const& image_file,
std::string const& camera_file = "" );
+ // Allows specialization of how matches are captured. Important
+ // for StereoSessionDGMapRPC.
+ virtual bool ip_matching( std::string const& match_filename,
+ double left_nodata_value,
+ double right_nodata_value );
+
// For reversing our arithmetic applied in preprocessing.
- typedef vw::TransformRef left_tx_type;
- typedef vw::TransformRef right_tx_type;
+ typedef vw::HomographyTransform left_tx_type;
+ typedef vw::HomographyTransform right_tx_type;
typedef vw::stereo::StereoModel stereo_model_type;
left_tx_type tx_left() const;
right_tx_type tx_right() const;
@@ -73,14 +63,6 @@ namespace asp {
std::string &right_output_file);
static StereoSession* construct() { return new StereoSessionDG; }
-
- protected:
-
- bool m_rpc_map_projected;
-
- vw::ImageViewRef<vw::Vector2f> generate_lut_image( std::string const&, std::string const& ) const;
- static RPCModel* read_rpc_model( std::string const& image_file, std::string const& camera_file );
-
};
}
View
34 src/asp/Sessions/DGMapRPC/Makefile.am
@@ -0,0 +1,34 @@
+# __BEGIN_LICENSE__
+# Copyright (c) 2009-2012, United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration. All
+# rights reserved.
+#
+# The NGT platform is licensed under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# __END_LICENSE__
+
+
+#########################################################################
+# sources
+#########################################################################
+
+include_HEADERS = StereoSessionDGMapRPC.h
+
+#########################################################################
+# general
+#########################################################################
+
+AM_CPPFLAGS = @ASP_CPPFLAGS@
+AM_LDFLAGS = @ASP_LDFLAGS@ -version-info @LIBTOOL_VERSION@
+
+includedir = $(prefix)/include/asp/Sessions/DGMapRPC
+
+include $(top_srcdir)/config/rules.mak
View
164 src/asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.cc
@@ -0,0 +1,164 @@
+// __BEGIN_LICENSE__
+// Copyright (c) 2009-2012, United States Government as represented by the
+// Administrator of the National Aeronautics and Space Administration. All
+// rights reserved.
+//
+// The NGT platform is licensed under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance with the
+// License. You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// __END_LICENSE__
+
+
+/// \file StereoSessionDGMapRPC.cc
+///
+#include <asp/Core/StereoSettings.h>
+#include <asp/Core/InterestPointMatching.h>
+#include <asp/Sessions/RPC/RPCModel.h>
+#include <asp/Sessions/RPC/StereoSessionRPC.h>
+#include <asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.h>
+#include <asp/Sessions/DG/XML.h>
+
+using namespace vw;
+using namespace asp;
+namespace fs = boost::filesystem;
+
+// Initializer to determine what kind of input we have.
+void StereoSessionDGMapRPC::initialize(BaseOptions const& options,
+ std::string const& left_image_file,
+ std::string const& right_image_file,
+ std::string const& left_camera_file,
+ std::string const& right_camera_file,
+ std::string const& out_prefix,
+ std::string const& input_dem,
+ std::string const& extra_argument1,
+ std::string const& extra_argument2,
+ std::string const& extra_argument3 ) {
+ StereoSessionDG::initialize( options, left_image_file,
+ right_image_file, left_camera_file,
+ right_camera_file, out_prefix,
+ input_dem, extra_argument1,
+ extra_argument2, extra_argument3 );
+
+ VW_ASSERT( !input_dem.empty(),
+ InputErr() << "StereoSessionDGMapRPC : Require input DEM" );
+
+ boost::scoped_ptr<RPCModel> model1, model2;
+ // Try and pull RPC Camera Models from left and right images.
+ try {
+ model1.reset( new RPCModel(left_image_file) );
+ model2.reset( new RPCModel(right_image_file) );
+ } catch ( NotFoundErr const& err ) {}
+
+ // If the above failed to load the RPC Model, try from the XML.
+ if ( !model1.get() || !model2.get() ) {
+ // Do not catch as these are required.
+ RPCXML rpc_xml;
+ rpc_xml.read_from_file( left_camera_file );
+ model1.reset( new RPCModel( *rpc_xml.rpc_ptr() ) ); // Copy the ptr
+ rpc_xml.read_from_file( right_camera_file );
+ model2.reset( new RPCModel( *rpc_xml.rpc_ptr() ) );
+ }
+
+ // Double check that we can read the DEM and that it has
+ // cartographic information.
+ if ( !fs::exists( input_dem ) )
+ vw_throw( ArgumentErr() << "StereoSessionDGMapRPC: DEM \"" << input_dem
+ << "\" does not exist." );
+
+ // Verify that center of our lonlat boundaries from the RPC models
+ // actually projects into the DEM. (?)
+}
+
+bool StereoSessionDGMapRPC::ip_matching( std::string const& match_filename,
+ double left_nodata_value,
+ double right_nodata_value ) {
+ // Load the unmodified images
+ DiskImageView<float> left_disk_image( m_left_image_file ),
+ right_disk_image( m_right_image_file );
+
+ boost::shared_ptr<camera::CameraModel> left_cam, right_cam;
+ camera_models( left_cam, right_cam );
+
+ boost::scoped_ptr<RPCModel>
+ left_rpc( StereoSessionRPC::read_rpc_model( m_left_image_file, m_left_camera_file ) ),
+ right_rpc( StereoSessionRPC::read_rpc_model( m_right_image_file, m_right_camera_file ) );
+ cartography::GeoReference left_georef, right_georef, dem_georef;
+ read_georeference( left_georef, m_left_image_file );
+ read_georeference( right_georef, m_right_image_file );
+ read_georeference( dem_georef, m_input_dem );
+ boost::shared_ptr<DiskImageResource>
+ dem_rsrc( DiskImageResource::open( m_input_dem ) );
+ TransformRef
+ left_tx( RPCMapTransform( *left_rpc, left_georef,
+ dem_georef, dem_rsrc ) ),
+ right_tx( RPCMapTransform( *right_rpc, right_georef,
+ dem_georef, dem_rsrc ) );
+ return
+ asp::ip_matching( left_cam.get(), right_cam.get(),
+ left_disk_image, right_disk_image,
+ cartography::Datum("WGS84"), match_filename,
+ left_nodata_value,
+ right_nodata_value,
+ left_tx, right_tx, false );
+}
+
+StereoSessionDGMapRPC::left_tx_type
+StereoSessionDGMapRPC::tx_left() const {
+ Matrix<double> tx = math::identity_matrix<3>();
+ if ( stereo_settings().alignment_method == "homography" ||
+ stereo_settings().alignment_method == "affineepipolar" ) {
+ read_matrix( tx, m_out_prefix + "-align-L.exr" );
+ }
+
+ cartography::GeoReference dem_georef, image_georef;
+ if (!read_georeference( dem_georef, m_input_dem ) )
+ vw_throw( ArgumentErr() << "The DEM \"" << m_input_dem << "\" lacks georeferencing information.");
+ if (!read_georeference( image_georef, m_left_image_file ) )
+ vw_throw( ArgumentErr() << "The image \"" << m_left_image_file << "\" lacks georeferencing information.");
+
+ // Load DEM rsrc. RPCMapTransform is casting to float internally
+ // no matter what the original type of the DEM file was.
+ boost::shared_ptr<DiskImageResource>
+ dem_rsrc( DiskImageResource::open( m_input_dem ) );
+
+ // This composes the two transforms as it is possible to do
+ // homography and affineepipolar alignment options with map
+ // projected imagery.
+ return left_tx_type( RPCMapTransform(*StereoSessionRPC::read_rpc_model(m_left_image_file, m_left_camera_file),
+ image_georef, dem_georef, dem_rsrc),
+ HomographyTransform(tx) );
+}
+
+StereoSessionDGMapRPC::right_tx_type
+StereoSessionDGMapRPC::tx_right() const {
+ Matrix<double> tx = math::identity_matrix<3>();
+ if ( stereo_settings().alignment_method == "homography" ||
+ stereo_settings().alignment_method == "affineepipolar" ) {
+ read_matrix( tx, m_out_prefix + "-align-R.exr" );
+ }
+
+ cartography::GeoReference dem_georef, image_georef;
+ if (!read_georeference( dem_georef, m_input_dem ) )
+ vw_throw( ArgumentErr() << "The DEM \"" << m_input_dem << "\" lacks georeferencing information.");
+ if (!read_georeference( image_georef, m_right_image_file ) )
+ vw_throw( ArgumentErr() << "The image \"" << m_right_image_file << "\" lacks georeferencing information.");
+
+ // Load DEM rsrc. RPCMapTransform is casting to float internally
+ // no matter what the original type of the DEM file was.
+ boost::shared_ptr<DiskImageResource>
+ dem_rsrc( DiskImageResource::open( m_input_dem ) );
+
+ // This composes the two transforms as it is possible to do
+ // homography and affineepipolar alignment options with map
+ // projected imagery.
+ return right_tx_type( RPCMapTransform(*StereoSessionRPC::read_rpc_model(m_right_image_file, m_right_camera_file),
+ image_georef, dem_georef, dem_rsrc),
+ HomographyTransform(tx) );
+}
View
86 src/asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.h
@@ -0,0 +1,86 @@
+// __BEGIN_LICENSE__
+// Copyright (c) 2009-2012, United States Government as represented by the
+// Administrator of the National Aeronautics and Space Administration. All
+// rights reserved.
+//
+// The NGT platform is licensed under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance with the
+// License. You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// __END_LICENSE__
+
+
+/// \file StereoSessionDG.h
+///
+/// This a session that support RPC Mapproject DG images. It is built
+/// entirely so that left and right TX are objects and not
+/// TransformRefs.
+
+#ifndef __STEREO_SESSION_DGMAPRPC_H__
+#define __STEREO_SESSION_DGMAPRPC_H__
+
+#include <asp/Sessions/DG/StereoSessionDG.h>
+#include <asp/Sessions/RPC/RPCMapTransform.h>
+#include <vw/Image/Transform.h>
+
+namespace asp {
+
+ // Specialize CompositionTransform that allows passing of BBox so
+ // RPCMapTransform can cache itself.
+ template <class Tx1T, class Tx2T>
+ class CompositionTransformPassBBox : public vw::TransformBase<CompositionTransformPassBBox<Tx1T,Tx2T> > {
+ Tx1T tx1;
+ Tx2T tx2;
+ public:
+ CompositionTransformPassBBox( Tx1T const& tx1, Tx2T const& tx2 ) : tx1(tx1), tx2(tx2) {}
+
+ inline vw::Vector2 forward( vw::Vector2 const& p ) const { return tx1.forward( tx2.forward( p ) ); }
+ inline vw::Vector2 reverse( vw::Vector2 const& p ) const { return tx2.reverse( tx1.reverse( p ) ); }
+
+ inline vw::BBox2i reverse_bbox( vw::BBox2i const& bbox ) const {
+ return this->tx2.reverse_bbox(this->tx1.reverse_bbox(bbox));
+ }
+ };
+
+ class StereoSessionDGMapRPC : public StereoSessionDG {
+ public:
+ StereoSessionDGMapRPC(){};
+ virtual ~StereoSessionDGMapRPC(){};
+
+ // Initializer verifies that the input is map projected
+ virtual void initialize(BaseOptions const& options,
+ std::string const& left_image_file,
+ std::string const& right_image_file,
+ std::string const& left_camera_file,
+ std::string const& right_camera_file,
+ std::string const& out_prefix,
+ std::string const& input_dem,
+ std::string const& extra_argument1,
+ std::string const& extra_argument2,
+ std::string const& extra_argument3);
+
+ // Allows specialization of how matches are captured.
+ virtual bool ip_matching( std::string const& match_filename,
+ double left_nodata_value,
+ double right_nodata_value );
+
+ // For reversing the arithmetic applied in preprocessing plus the
+ // map projection.
+ typedef CompositionTransformPassBBox<RPCMapTransform,vw::HomographyTransform> left_tx_type;
+ typedef CompositionTransformPassBBox<RPCMapTransform,vw::HomographyTransform> right_tx_type;
+ typedef vw::stereo::StereoModel stereo_model_type;
+ left_tx_type tx_left() const;
+ right_tx_type tx_right() const;
+
+ static StereoSession* construct() { return new StereoSessionDGMapRPC; }
+ };
+
+}
+
+#endif//__STEREO_SESSION_DGMAPRPC_H__
View
4 src/asp/Sessions/Makefile.am
@@ -28,13 +28,13 @@ libaspSessions_la_SOURCES = StereoSession.cc \
Pinhole/StereoSessionPinhole.cc DG/StereoSessionDG.cc DG/XMLBase.cc \
DG/XML.cc RPC/StereoSessionRPC.cc RPC/RPCStereoModel.cc \
RPC/RPCModel.cc RPC/RPCMapTransform.cc \
-NadirPinhole/StereoSessionNadirPinhole.cc
+NadirPinhole/StereoSessionNadirPinhole.cc DGMapRPC/StereoSessionDGMapRPC.cc
libaspSessions_la_LIBADD = @MODULE_SESSIONS_LIBS@
lib_LTLIBRARIES = libaspSessions.la
-SUBDIRS = . NadirPinhole Pinhole DG tests
+SUBDIRS = . NadirPinhole Pinhole DG DGMapRPC tests
if HAVE_PKG_ISIS
SUBDIRS += ISIS
View
21 src/asp/Sessions/RPC/StereoSessionRPC.cc
@@ -38,7 +38,26 @@ namespace asp {
boost::shared_ptr<camera::CameraModel>
StereoSessionRPC::camera_model(std::string const& image_file,
std::string const& camera_file ) {
- return boost::shared_ptr<camera::CameraModel>(StereoSessionDG::read_rpc_model(image_file, camera_file));
+ return boost::shared_ptr<camera::CameraModel>(read_rpc_model(image_file, camera_file));
}
+ // Helper function to read RPC models.
+ RPCModel* StereoSessionRPC::read_rpc_model( std::string const& image_file,
+ std::string const& camera_file ) {
+ RPCModel* rpc_model = NULL;
+ try {
+ rpc_model = new RPCModel( image_file );
+ } catch ( NotFoundErr const& err ) {}
+
+ if ( !rpc_model ) {
+ RPCXML rpc_xml;
+ rpc_xml.read_from_file( camera_file );
+ rpc_model = new RPCModel( *rpc_xml.rpc_ptr() ); // Copy the value
+
+ // We don't catch an error here because the User will need to
+ // know of a failure at this point. We previously opened the
+ // XML safely before.
+ }
+ return rpc_model;
+ }
} // namespace asp
View
11 src/asp/Sessions/RPC/StereoSessionRPC.h
@@ -26,18 +26,23 @@
namespace asp {
- class StereoSessionRPC : public StereoSessionDG {
+ // Forward declaration
+ class RPCModel;
+ class StereoSessionRPC : public StereoSessionDG {
public:
-
- StereoSessionRPC(): StereoSessionDG(){}
+ StereoSessionRPC(){};
+ virtual ~StereoSessionRPC(){};
// Produces a camera model from the images
virtual boost::shared_ptr<vw::camera::CameraModel>
camera_model( std::string const& image_file,
std::string const& camera_file);
static StereoSession* construct() { return new StereoSessionRPC; }
+
+ static RPCModel* read_rpc_model( std::string const& image_file,
+ std::string const& camera_file );
};
} // namespace asp
View
14 src/asp/Sessions/StereoSession.cc
@@ -22,6 +22,7 @@
#include <asp/Core/StereoSettings.h>
#include <asp/Sessions/StereoSession.h>
#include <asp/Sessions/DG/StereoSessionDG.h>
+#include <asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.h>
#include <asp/Sessions/NadirPinhole/StereoSessionNadirPinhole.h>
#include <asp/Sessions/Pinhole/StereoSessionPinhole.h>
#include <asp/Sessions/RPC/StereoSessionRPC.h>
@@ -74,14 +75,11 @@ namespace asp {
static bool already = false;
if ( already ) return;
already = true;
- StereoSession::register_session_type( "nadirpinhole",
- &StereoSessionNadirPinhole::construct );
- StereoSession::register_session_type( "pinhole",
- &StereoSessionPinhole::construct );
- StereoSession::register_session_type( "dg",
- &StereoSessionDG::construct );
- StereoSession::register_session_type( "rpc",
- &StereoSessionRPC::construct );
+ StereoSession::register_session_type( "dg", &StereoSessionDG::construct );
+ StereoSession::register_session_type( "dgmaprpc", &StereoSessionDGMapRPC::construct );
+ StereoSession::register_session_type( "nadirpinhole", &StereoSessionNadirPinhole::construct );
+ StereoSession::register_session_type( "pinhole", &StereoSessionPinhole::construct );
+ StereoSession::register_session_type( "rpc", &StereoSessionRPC::construct );
}
StereoSession* StereoSession::create( std::string const& session_type ) {
View
4 src/asp/Sessions/tests/Makefile.am
@@ -23,10 +23,12 @@
if MAKE_MODULE_SESSIONS
TestStereoSessionDG_SOURCES = TestStereoSessionDG.cxx
+TestStereoSessionDGMapRPC_SOURCES = TestStereoSessionDGMapRPC.cxx
TestStereoSessionRPC_SOURCES = TestStereoSessionRPC.cxx
TestInstantiation_SOURCES = TestInstantiation.cxx
-TESTS = TestStereoSessionDG TestStereoSessionRPC TestInstantiation
+TESTS = TestStereoSessionDG TestStereoSessionDGMapRPC \
+TestStereoSessionRPC TestInstantiation
endif
View
26 src/asp/Sessions/tests/TestInstantiation.cxx
@@ -16,6 +16,7 @@
// __END_LICENSE__
#include <asp/Sessions/DG/StereoSessionDG.h>
+#include <asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.h>
#include <asp/Sessions/RPC/StereoSessionRPC.h>
#include <asp/Sessions/ISIS/StereoSessionIsis.h>
#include <asp/Sessions/Pinhole/StereoSessionPinhole.h>
@@ -27,7 +28,8 @@ using namespace vw;
using namespace asp;
// This is to make sure the developers provide types for their
-// sessions. The test is to see if this even compiles.
+// sessions. The test is to see if this even compiles. Not if it
+// runs. (It doesn't)
template <typename T>
class InstantiationTest : public ::testing::Test {
public:
@@ -40,18 +42,18 @@ class InstantiationTest : public ::testing::Test {
SessionT session;
};
-typedef ::testing::Types<StereoSessionDG, StereoSessionRPC, StereoSessionIsis, StereoSessionPinhole, StereoSessionNadirPinhole> SessionTypes;
+typedef ::testing::Types<StereoSessionDG, StereoSessionDGMapRPC, StereoSessionRPC, StereoSessionIsis, StereoSessionPinhole, StereoSessionNadirPinhole> SessionTypes;
TYPED_TEST_CASE( InstantiationTest, SessionTypes );
TYPED_TEST( InstantiationTest, Typedefs ) {
- // Verify object for left transform
- typename TestFixture::SessionT::left_tx_type left_tx =
- this->session.tx_left();
-
- // Verify object for right transform
- typename TestFixture::SessionT::right_tx_type right_tx =
- this->session.tx_right();
-
- // Verify object for stereo model
- typename TestFixture::SessionT::stereo_model_type stereo_model();
+ try {
+ // Verify object for left transform
+ typename TestFixture::SessionT::left_tx_type left_tx =
+ this->session.tx_left();
+ // Verify object for right transform
+ typename TestFixture::SessionT::right_tx_type right_tx =
+ this->session.tx_right();
+ // Verify object for stereo model
+ typename TestFixture::SessionT::stereo_model_type stereo_model();
+ } catch ( const vw::Exception& e ) {}
}
View
71 src/asp/Sessions/tests/TestStereoSessionDG.cxx
@@ -202,74 +202,3 @@ TEST(StereoSessionDG, ProjectRPC) {
EXPECT_VECTOR_NEAR( rpc_model->point_to_pixel( xyz ),
dg_model->point_to_pixel( xyz ), 25 );
}
-
-TEST(StereoSessionDG, MapProjectedInput) {
- // Generate GeoReference projection that matches something that the
- // RPC models in dg_example1 and dg_example4 see.
- cartography::GeoReference lowres_georef; // WGS84
- lowres_georef.set_equirectangular( 37.745, -103.29, 37 );
- Matrix<double> tx = math::identity_matrix<3>();
- tx(0,0) = tx(1,1) = 500;
- tx(0,2) = tx(1,2) = -1000;
- lowres_georef.set_transform( tx );
-
- // Make low res images. We have to overcrop, otherwise the bicubic
- // interpolation of the DEM will have edge effects.
- cartography::GeoReference lowres_overcrop_georef = lowres_georef;
- tx(0,2) = tx(1,2) = -2000;
- lowres_overcrop_georef.set_transform( tx );
- ImageView<float> lowres_overcrop_image(8,8);
- fill( lowres_overcrop_image, 2287 ); // Average height of this area
- UnlinkName lowres_dem_name( "lowres_dem.tif" );
- write_georeferenced_image( lowres_dem_name, lowres_overcrop_image, lowres_overcrop_georef );
-
- // Make hires images
- cartography::GeoReference hires_georef = lowres_georef;
- tx(0,0) = tx(1,1) = 100;
- tx(0,2) = tx(1,2) = -1000;
- hires_georef.set_transform( tx );
- ImageView<float> hires_image(20,20);
- fill( hires_image, 1 );
- ImageView<float> lowres_image(4,4);
- fill( lowres_image, 2 );
- UnlinkName left_image_name("faked_left.tif"), right_image_name("faked_right.tif");
- write_georeferenced_image( left_image_name, lowres_image, lowres_georef );
- write_georeferenced_image( right_image_name, hires_image, hires_georef );
-
- // Create session
- BaseOptions opt;
- StereoSessionDG session;
- session.initialize( opt, left_image_name, right_image_name,
- "dg_example1.xml", "dg_example4.xml",
- "debug/debug", lowres_dem_name, "", "", "" );
- RPCXML left_xml, right_xml;
- left_xml.read_from_file( "dg_example1.xml" );
- right_xml.read_from_file( "dg_example4.xml" );
- StereoSessionDG::left_tx_type left_tx = session.tx_left();
- StereoSessionDG::right_tx_type right_tx = session.tx_right();
- cartography::Datum datum;
-
- // Verify that LX matches what we got by hand.
- for ( size_t j = 0; j < 4; j++ ) {
- for ( size_t i = 0; i < 4; i++ ) {
- Vector3 lonlatheight;
- subvector(lonlatheight,0,2) = lowres_georef.pixel_to_lonlat( Vector2(i,j) );
- lonlatheight.z() = 2287;
- Vector3 xyz = datum.geodetic_to_cartesian( lonlatheight );
- EXPECT_VECTOR_NEAR( left_xml.rpc_ptr()->point_to_pixel( xyz ),
- left_tx.reverse( Vector2(i,j) ), 1e-1 );
- }
- }
-
- // Verify that RX matches what we got by hand
- for ( size_t j = 0; j < 20; j++ ) {
- for ( size_t i = 0; i < 20; i++ ) {
- Vector3 lonlatheight;
- subvector(lonlatheight,0,2) = hires_georef.pixel_to_lonlat( Vector2(i,j) );
- lonlatheight.z() = 2287;
- Vector3 xyz = datum.geodetic_to_cartesian( lonlatheight );
- EXPECT_VECTOR_NEAR( right_xml.rpc_ptr()->point_to_pixel( xyz ),
- right_tx.reverse( Vector2(i,j) ), 1e-1 );
- }
- }
-}
View
101 src/asp/Sessions/tests/TestStereoSessionDGMapRPC.cxx
@@ -0,0 +1,101 @@
+// __BEGIN_LICENSE__
+// Copyright (c) 2009-2012, United States Government as represented by the
+// Administrator of the National Aeronautics and Space Administration. All
+// rights reserved.
+//
+// The NGT platform is licensed under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance with the
+// License. You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// __END_LICENSE__
+
+
+#include <asp/Sessions/DGMapRPC/StereoSessionDGMapRPC.h>
+#include <asp/Sessions/DG/XML.h>
+#include <asp/Sessions/RPC/RPCModel.h>
+#include <boost/scoped_ptr.hpp>
+#include <test/Helpers.h>
+
+#include <vw/Stereo/StereoModel.h>
+
+using namespace vw;
+using namespace asp;
+using namespace vw::test;
+
+TEST(StereoSessionDGMapRPC, TransformCycle) {
+ // Generate GeoReference projection that matches something that the
+ // RPC models in dg_example1 and dg_example4 see.
+ cartography::GeoReference lowres_georef; // WGS84
+ lowres_georef.set_equirectangular( 37.745, -103.29, 37 );
+ Matrix<double> tx = math::identity_matrix<3>();
+ tx(0,0) = tx(1,1) = 500;
+ tx(0,2) = tx(1,2) = -1000;
+ lowres_georef.set_transform( tx );
+
+ // Make low res images. We have to overcrop, otherwise the bicubic
+ // interpolation of the DEM will have edge effects.
+ cartography::GeoReference lowres_overcrop_georef = lowres_georef;
+ tx(0,2) = tx(1,2) = -2000;
+ lowres_overcrop_georef.set_transform( tx );
+ ImageView<float> lowres_overcrop_image(8,8);
+ fill( lowres_overcrop_image, 2287 ); // Average height of this area
+ UnlinkName lowres_dem_name( "lowres_dem.tif" );
+ write_georeferenced_image( lowres_dem_name, lowres_overcrop_image, lowres_overcrop_georef );
+
+ // Make hires images
+ cartography::GeoReference hires_georef = lowres_georef;
+ tx(0,0) = tx(1,1) = 100;
+ tx(0,2) = tx(1,2) = -1000;
+ hires_georef.set_transform( tx );
+ ImageView<float> hires_image(20,20);
+ fill( hires_image, 1 );
+ ImageView<float> lowres_image(4,4);
+ fill( lowres_image, 2 );
+ UnlinkName left_image_name("faked_left.tif"), right_image_name("faked_right.tif");
+ write_georeferenced_image( left_image_name, lowres_image, lowres_georef );
+ write_georeferenced_image( right_image_name, hires_image, hires_georef );
+
+ // Create session
+ BaseOptions opt;
+ StereoSessionDGMapRPC session;
+ session.initialize( opt, left_image_name, right_image_name,
+ "dg_example1.xml", "dg_example4.xml",
+ "debug/debug", lowres_dem_name, "", "", "" );
+ RPCXML left_xml, right_xml;
+ left_xml.read_from_file( "dg_example1.xml" );
+ right_xml.read_from_file( "dg_example4.xml" );
+ StereoSessionDGMapRPC::left_tx_type left_tx = session.tx_left();
+ StereoSessionDGMapRPC::right_tx_type right_tx = session.tx_right();
+ cartography::Datum datum;
+
+ // Verify that LX matches what we got by hand.
+ for ( size_t j = 0; j < 4; j++ ) {
+ for ( size_t i = 0; i < 4; i++ ) {
+ Vector3 lonlatheight;
+ subvector(lonlatheight,0,2) = lowres_georef.pixel_to_lonlat( Vector2(i,j) );
+ lonlatheight.z() = 2287;
+ Vector3 xyz = datum.geodetic_to_cartesian( lonlatheight );
+ EXPECT_VECTOR_NEAR( left_xml.rpc_ptr()->point_to_pixel( xyz ),
+ left_tx.reverse( Vector2(i,j) ), 1e-1 );
+ }
+ }
+
+ // Verify that RX matches what we got by hand
+ for ( size_t j = 0; j < 20; j++ ) {
+ for ( size_t i = 0; i < 20; i++ ) {
+ Vector3 lonlatheight;
+ subvector(lonlatheight,0,2) = hires_georef.pixel_to_lonlat( Vector2(i,j) );
+ lonlatheight.z() = 2287;
+ Vector3 xyz = datum.geodetic_to_cartesian( lonlatheight );
+ EXPECT_VECTOR_NEAR( right_xml.rpc_ptr()->point_to_pixel( xyz ),
+ right_tx.reverse( Vector2(i,j) ), 1e-1 );
+ }
+ }
+}
+
View
11 src/asp/Tools/stereo_tri.cc
@@ -18,7 +18,6 @@
/// \file stereo_tri.cc
///
-//#define USE_GRAPHICS
#include <asp/Tools/stereo.h>
#include <asp/Sessions/RPC/RPCModel.h>
@@ -155,6 +154,12 @@ class StereoTXAndErrorView : public ImageViewBase<StereoTXAndErrorView<Disparity
typedef typename DisparityImageT::pixel_type DPixelT;
ImageView<DPixelT> disparity_preraster( crop( m_disparity_map, bbox ) );
+ // This is to help any transforms (right now just RPCMapTransform)
+ // that must cache their side data. Normally this would happen if
+ // we were using a TransformView.
+ volatile BBox2i left_reverse = m_tx1.reverse_bbox( bbox );
+ volatile BBox2i right_reverse = m_tx2.reverse_bbox( bbox );
+
return prerasterize_type( crop(disparity_preraster,-bbox.min().x(),-bbox.min().y(),cols(),rows()),
m_tx1, m_tx2,
m_stereo_model );
@@ -277,7 +282,7 @@ int main( int argc, char* argv[] ) {
// Internal Processes
//---------------------------------------------------------
- if ( opt.stereo_session_string == "pinhole" ) {
+ if ( opt.stereo_session_string == "pinhole" ) {
stereo_triangulation<StereoSessionPinhole>( opt );
} else if ( opt.stereo_session_string == "nadirpinhole" ) {
stereo_triangulation<StereoSessionNadirPinhole>( opt );
@@ -287,6 +292,8 @@ int main( int argc, char* argv[] ) {
stereo_triangulation<StereoSessionRPC>( opt );
} else if ( opt.stereo_session_string == "dg" ) {
stereo_triangulation<StereoSessionDG>( opt );
+ } else if ( opt.stereo_session_string == "dgmaprpc" ) {
+ stereo_triangulation<StereoSessionDGMapRPC>( opt );
}
vw_out() << "\n[ " << current_posix_time_string()

0 comments on commit a8fec02

Please sign in to comment.
Something went wrong with that request. Please try again.