Add to wrapper
							parent
							
								
									9dfe52d0b6
								
							
						
					
					
						commit
						5d6b8f445e
					
				|  | @ -31,15 +31,23 @@ class SfmTrack { | ||||||
| #include <gtsam/sfm/SfmData.h> | #include <gtsam/sfm/SfmData.h> | ||||||
| class SfmData { | class SfmData { | ||||||
|   SfmData(); |   SfmData(); | ||||||
|   gtsam::SfmData FromBundlerFile(string filename); |   static gtsam::SfmData FromBundlerFile(string filename); | ||||||
|   gtsam::SfmData FromBalFile(string filename); |   static gtsam::SfmData FromBalFile(string filename); | ||||||
| 
 | 
 | ||||||
|   size_t numberCameras() const; |  | ||||||
|   size_t numberTracks() const; |  | ||||||
|   gtsam::PinholeCamera<gtsam::Cal3Bundler> camera(size_t idx) const; |  | ||||||
|   gtsam::SfmTrack track(size_t idx) const; |  | ||||||
|   void addTrack(const gtsam::SfmTrack& t); |   void addTrack(const gtsam::SfmTrack& t); | ||||||
|   void addCamera(const gtsam::SfmCamera& cam); |   void addCamera(const gtsam::SfmCamera& cam); | ||||||
|  |   size_t numberTracks() const; | ||||||
|  |   size_t numberCameras() const; | ||||||
|  |   gtsam::SfmTrack track(size_t idx) const; | ||||||
|  |   gtsam::PinholeCamera<gtsam::Cal3Bundler> camera(size_t idx) const; | ||||||
|  | 
 | ||||||
|  |   gtsam::NonlinearFactorGraph generalSfmFactors( | ||||||
|  |       const gtsam::SharedNoiseModel& model = | ||||||
|  |           gtsam::noiseModel::Isotropic::Sigma(2, 1.0)) const; | ||||||
|  |   gtsam::NonlinearFactorGraph sfmFactorGraph( | ||||||
|  |       const gtsam::SharedNoiseModel& model = | ||||||
|  |           gtsam::noiseModel::Isotropic::Sigma(2, 1.0), | ||||||
|  |       size_t fixedCamera = 0, size_t fixedPoint = 0) const; | ||||||
| 
 | 
 | ||||||
|   // enabling serialization functionality |   // enabling serialization functionality | ||||||
|   void serialize() const; |   void serialize() const; | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ import logging | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import gtsam | import gtsam | ||||||
| from gtsam import (GeneralSFMFactorCal3Bundler, | from gtsam import (GeneralSFMFactorCal3Bundler, SfmData, | ||||||
|                    PriorFactorPinholeCameraCal3Bundler, PriorFactorPoint3) |                    PriorFactorPinholeCameraCal3Bundler, PriorFactorPoint3) | ||||||
| from gtsam.symbol_shorthand import C, P  # type: ignore | from gtsam.symbol_shorthand import C, P  # type: ignore | ||||||
| from gtsam.utils import plot  # type: ignore | from gtsam.utils import plot  # type: ignore | ||||||
|  | @ -26,7 +26,7 @@ logging.basicConfig(stream=sys.stdout, level=logging.INFO) | ||||||
| DEFAULT_BAL_DATASET = "dubrovnik-3-7-pre" | DEFAULT_BAL_DATASET = "dubrovnik-3-7-pre" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def plot_scene(scene_data: gtsam.SfmData, result: gtsam.Values) -> None: | def plot_scene(scene_data: SfmData, result: gtsam.Values) -> None: | ||||||
|     """Plot the SFM results.""" |     """Plot the SFM results.""" | ||||||
|     plot_vals = gtsam.Values() |     plot_vals = gtsam.Values() | ||||||
|     for cam_idx in range(scene_data.numberCameras()): |     for cam_idx in range(scene_data.numberCameras()): | ||||||
|  | @ -46,7 +46,7 @@ def run(args: argparse.Namespace) -> None: | ||||||
|     input_file = args.input_file |     input_file = args.input_file | ||||||
| 
 | 
 | ||||||
|     # Load the SfM data from file |     # Load the SfM data from file | ||||||
|     scene_data = gtsam.readBal(input_file) |     scene_data = SfmData.FromBalFile(input_file) | ||||||
|     logging.info("read %d tracks on %d cameras\n", scene_data.numberTracks(), |     logging.info("read %d tracks on %d cameras\n", scene_data.numberTracks(), | ||||||
|                  scene_data.numberCameras()) |                  scene_data.numberCameras()) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ import unittest | ||||||
| import numpy as np | import numpy as np | ||||||
| 
 | 
 | ||||||
| import gtsam | import gtsam | ||||||
|  | from gtsam import SfmData, SfmTrack, Point2, Point3 | ||||||
| from gtsam.utils.test_case import GtsamTestCase | from gtsam.utils.test_case import GtsamTestCase | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -25,29 +26,34 @@ class TestSfmData(GtsamTestCase): | ||||||
| 
 | 
 | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         """Initialize SfmData and SfmTrack""" |         """Initialize SfmData and SfmTrack""" | ||||||
|         self.data = gtsam.SfmData() |         self.data = SfmData() | ||||||
|         # initialize SfmTrack with 3D point |         # initialize SfmTrack with 3D point | ||||||
|         self.tracks = gtsam.SfmTrack() |         self.tracks = SfmTrack() | ||||||
| 
 | 
 | ||||||
|     def test_tracks(self): |     def test_tracks(self): | ||||||
|         """Test functions in SfmTrack""" |         """Test functions in SfmTrack""" | ||||||
|         # measurement is of format (camera_idx, imgPoint) |         # measurement is of format (camera_idx, imgPoint) | ||||||
|         # create arbitrary camera indices for two cameras |         # create arbitrary camera indices for two cameras | ||||||
|         i1, i2 = 4,5 |         i1, i2 = 4,5 | ||||||
|  | 
 | ||||||
|         # create arbitrary image measurements for cameras i1 and i2 |         # create arbitrary image measurements for cameras i1 and i2 | ||||||
|         uv_i1 = gtsam.Point2(12.6, 82) |         uv_i1 = Point2(12.6, 82) | ||||||
|  |          | ||||||
|         # translating point uv_i1 along X-axis |         # translating point uv_i1 along X-axis | ||||||
|         uv_i2 = gtsam.Point2(24.88, 82) |         uv_i2 = Point2(24.88, 82) | ||||||
|  |          | ||||||
|         # add measurements to the track |         # add measurements to the track | ||||||
|         self.tracks.addMeasurement(i1, uv_i1) |         self.tracks.addMeasurement(i1, uv_i1) | ||||||
|         self.tracks.addMeasurement(i2, uv_i2) |         self.tracks.addMeasurement(i2, uv_i2) | ||||||
|  |          | ||||||
|         # Number of measurements in the track is 2 |         # Number of measurements in the track is 2 | ||||||
|         self.assertEqual(self.tracks.numberMeasurements(), 2) |         self.assertEqual(self.tracks.numberMeasurements(), 2) | ||||||
|  |          | ||||||
|         # camera_idx in the first measurement of the track corresponds to i1 |         # camera_idx in the first measurement of the track corresponds to i1 | ||||||
|         cam_idx, img_measurement = self.tracks.measurement(0) |         cam_idx, img_measurement = self.tracks.measurement(0) | ||||||
|         self.assertEqual(cam_idx, i1) |         self.assertEqual(cam_idx, i1) | ||||||
|         np.testing.assert_array_almost_equal( |         np.testing.assert_array_almost_equal( | ||||||
|             gtsam.Point3(0.,0.,0.),  |             Point3(0.,0.,0.),  | ||||||
|             self.tracks.point3() |             self.tracks.point3() | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  | @ -56,24 +62,58 @@ class TestSfmData(GtsamTestCase): | ||||||
|         """Test functions in SfmData""" |         """Test functions in SfmData""" | ||||||
|         # Create new track with 3 measurements |         # Create new track with 3 measurements | ||||||
|         i1, i2, i3 = 3,5,6 |         i1, i2, i3 = 3,5,6 | ||||||
|         uv_i1 = gtsam.Point2(21.23, 45.64) |         uv_i1 = Point2(21.23, 45.64) | ||||||
|  |          | ||||||
|         # translating along X-axis |         # translating along X-axis | ||||||
|         uv_i2 = gtsam.Point2(45.7, 45.64) |         uv_i2 = Point2(45.7, 45.64) | ||||||
|         uv_i3 = gtsam.Point2(68.35, 45.64) |         uv_i3 = Point2(68.35, 45.64) | ||||||
|  |          | ||||||
|         # add measurements and arbitrary point to the track |         # add measurements and arbitrary point to the track | ||||||
|         measurements = [(i1, uv_i1), (i2, uv_i2), (i3, uv_i3)] |         measurements = [(i1, uv_i1), (i2, uv_i2), (i3, uv_i3)] | ||||||
|         pt = gtsam.Point3(1.0, 6.0, 2.0) |         pt = Point3(1.0, 6.0, 2.0) | ||||||
|         track2 = gtsam.SfmTrack(pt) |         track2 = SfmTrack(pt) | ||||||
|         track2.addMeasurement(i1, uv_i1) |         track2.addMeasurement(i1, uv_i1) | ||||||
|         track2.addMeasurement(i2, uv_i2) |         track2.addMeasurement(i2, uv_i2) | ||||||
|         track2.addMeasurement(i3, uv_i3) |         track2.addMeasurement(i3, uv_i3) | ||||||
|         self.data.addTrack(self.tracks) |         self.data.addTrack(self.tracks) | ||||||
|         self.data.addTrack(track2) |         self.data.addTrack(track2) | ||||||
|  | 
 | ||||||
|         # Number of tracks in SfmData is 2 |         # Number of tracks in SfmData is 2 | ||||||
|         self.assertEqual(self.data.numberTracks(), 2) |         self.assertEqual(self.data.numberTracks(), 2) | ||||||
|  |          | ||||||
|         # camera idx of first measurement of second track corresponds to i1 |         # camera idx of first measurement of second track corresponds to i1 | ||||||
|         cam_idx, img_measurement = self.data.track(1).measurement(0) |         cam_idx, img_measurement = self.data.track(1).measurement(0) | ||||||
|         self.assertEqual(cam_idx, i1) |         self.assertEqual(cam_idx, i1) | ||||||
| 
 | 
 | ||||||
|  |     def test_Balbianello(self): | ||||||
|  |         # The structure where we will save the SfM data | ||||||
|  |         filename = gtsam.findExampleDataFile("Balbianello") | ||||||
|  |         sfm_data = SfmData.FromBundlerFile(filename) | ||||||
|  | 
 | ||||||
|  |         # Check number of things | ||||||
|  |         self.assertEqual(5, sfm_data.numberCameras()) | ||||||
|  |         self.assertEqual(544, sfm_data.numberTracks()) | ||||||
|  |         track0 = sfm_data.track(0) | ||||||
|  |         self.assertEqual(3, track0.numberMeasurements()) | ||||||
|  | 
 | ||||||
|  |         # Check projection of a given point | ||||||
|  |         self.assertEqual(0, track0.measurement(0)[0]) | ||||||
|  |         camera0 = sfm_data.camera(0) | ||||||
|  |         expected = camera0.project(track0.point3()) | ||||||
|  |         actual = track0.measurement(0)[1] | ||||||
|  |         self.gtsamAssertEquals(expected, actual, 1) | ||||||
|  | 
 | ||||||
|  |         # We share *one* noiseModel between all projection factors | ||||||
|  |         model = gtsam.noiseModel.Isotropic.Sigma(2, 1.0)  # one pixel in u and v | ||||||
|  | 
 | ||||||
|  |         # Convert to NonlinearFactorGraph | ||||||
|  |         graph = sfm_data.sfmFactorGraph(model) | ||||||
|  |         self.assertEqual(1419, graph.size())  # regression | ||||||
|  | 
 | ||||||
|  |         # Get initial estimate | ||||||
|  |         values = gtsam.initialCamerasAndPointsEstimate(sfm_data) | ||||||
|  |         self.assertEqual(549, values.size())  # regression | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue