test_DsfTrackGenerator.py
Go to the documentation of this file.
1 """Unit tests for track generation using a Disjoint Set Forest data structure.
2 
3 Authors: John Lambert
4 """
5 
6 import unittest
7 from typing import Dict, List, Tuple
8 
9 import numpy as np
10 from gtsam.gtsfm import Keypoints
11 from gtsam.utils.test_case import GtsamTestCase
12 
13 import gtsam
14 from gtsam import IndexPair, Point2, SfmTrack2d
15 
16 
18  """Tests for DsfTrackGenerator."""
19 
21  self,
22  ) -> None:
23  """Tests DSF for non-transitive matches.
24 
25  Test will result in no tracks since nontransitive tracks are naively discarded by DSF.
26  """
27  keypoints_list = get_dummy_keypoints_list()
28  nontransitive_matches_dict = get_nontransitive_matches() # contains one non-transitive track
29 
30  # For each image pair (i1,i2), we provide a (K,2) matrix
31  # of corresponding keypoint indices (k1,k2).
32  matches_dict = {}
33  for (i1,i2), corr_idxs in nontransitive_matches_dict.items():
34  matches_dict[IndexPair(i1, i2)] = corr_idxs
35 
37  matches_dict,
38  keypoints_list,
39  verbose=True,
40  )
41  self.assertEqual(len(tracks), 0, "Tracks not filtered correctly")
42 
43  def test_track_generation(self) -> None:
44  """Ensures that DSF generates three tracks from measurements
45  in 3 images (H=200,W=400)."""
46  kps_i0 = Keypoints(np.array([[10.0, 20], [30, 40]]))
47  kps_i1 = Keypoints(np.array([[50.0, 60], [70, 80], [90, 100]]))
48  kps_i2 = Keypoints(np.array([[110.0, 120], [130, 140]]))
49 
50  keypoints_list = []
51  keypoints_list.append(kps_i0)
52  keypoints_list.append(kps_i1)
53  keypoints_list.append(kps_i2)
54 
55  # For each image pair (i1,i2), we provide a (K,2) matrix
56  # of corresponding keypoint indices (k1,k2).
57  matches_dict = {}
58  matches_dict[IndexPair(0, 1)] = np.array([[0, 0], [1, 1]])
59  matches_dict[IndexPair(1, 2)] = np.array([[2, 0], [1, 1]])
60 
62  matches_dict,
63  keypoints_list,
64  verbose=False,
65  )
66  assert len(tracks) == 3
67 
68  # Verify track 0.
69  track0 = tracks[0]
70  assert track0.numberMeasurements() == 2
71  np.testing.assert_allclose(track0.measurements[0][1], Point2(10, 20))
72  np.testing.assert_allclose(track0.measurements[1][1], Point2(50, 60))
73  assert track0.measurements[0][0] == 0
74  assert track0.measurements[1][0] == 1
75  np.testing.assert_allclose(
76  track0.measurementMatrix(),
77  [
78  [10, 20],
79  [50, 60],
80  ],
81  )
82  np.testing.assert_allclose(track0.indexVector(), [0, 1])
83 
84  # Verify track 1.
85  track1 = tracks[1]
86  np.testing.assert_allclose(
87  track1.measurementMatrix(),
88  [
89  [30, 40],
90  [70, 80],
91  [130, 140],
92  ],
93  )
94  np.testing.assert_allclose(track1.indexVector(), [0, 1, 2])
95 
96  # Verify track 2.
97  track2 = tracks[2]
98  np.testing.assert_allclose(
99  track2.measurementMatrix(),
100  [
101  [90, 100],
102  [110, 120],
103  ],
104  )
105  np.testing.assert_allclose(track2.indexVector(), [1, 2])
106 
107 
109  """Tests for SfmTrack2d."""
110 
111  def test_sfm_track_2d_constructor(self) -> None:
112  """Test construction of 2D SfM track."""
113  measurements = []
114  measurements.append((0, Point2(10, 20)))
115  track = SfmTrack2d(measurements=measurements)
116  track.measurement(0)
117  assert track.numberMeasurements() == 1
118 
119 
120 def get_dummy_keypoints_list() -> List[Keypoints]:
121  """ """
122  img1_kp_coords = np.array([[1, 1], [2, 2], [3, 3.]])
123  img1_kp_scale = np.array([6.0, 9.0, 8.5])
124  img2_kp_coords = np.array(
125  [
126  [1, 1.],
127  [2, 2],
128  [3, 3],
129  [4, 4],
130  [5, 5],
131  [6, 6],
132  [7, 7],
133  [8, 8],
134  ]
135  )
136  img3_kp_coords = np.array(
137  [
138  [1, 1.],
139  [2, 2],
140  [3, 3],
141  [4, 4],
142  [5, 5],
143  [6, 6],
144  [7, 7],
145  [8, 8],
146  [9, 9],
147  [10, 10],
148  ]
149  )
150  img4_kp_coords = np.array(
151  [
152  [1, 1.],
153  [2, 2],
154  [3, 3],
155  [4, 4],
156  [5, 5],
157  ]
158  )
159  keypoints_list = [
160  Keypoints(coordinates=img1_kp_coords),
161  Keypoints(coordinates=img2_kp_coords),
162  Keypoints(coordinates=img3_kp_coords),
163  Keypoints(coordinates=img4_kp_coords),
164  ]
165  return keypoints_list
166 
167 
168 def get_nontransitive_matches() -> Dict[Tuple[int, int], np.ndarray]:
169  """Set up correspondences for each (i1,i2) pair that violates transitivity.
170 
171  (i=0, k=0) (i=0, k=1)
172  | \\ |
173  | \\ |
174  (i=1, k=2)--(i=2,k=3)--(i=3, k=4)
175 
176  Transitivity is violated due to the match between frames 0 and 3.
177  """
178  nontransitive_matches_dict = {
179  (0, 1): np.array([[0, 2]]),
180  (1, 2): np.array([[2, 3]]),
181  (0, 2): np.array([[0, 3]]),
182  (0, 3): np.array([[1, 4]]),
183  (2, 3): np.array([[3, 4]]),
184  }
185  return nontransitive_matches_dict
186 
187 
188 if __name__ == "__main__":
189  unittest.main()
gtsam::gtsfm::Keypoints
Definition: DsfTrackGenerator.h:40
test_DsfTrackGenerator.TestSfmTrack2d
Definition: test_DsfTrackGenerator.py:108
gtsam::SfmTrack2d
Track containing 2D measurements associated with a single 3D point. Note: Equivalent to gtsam....
Definition: SfmTrack.h:42
gtsam::gtsfm
Definition: DsfTrackGenerator.cpp:27
test_DsfTrackGenerator.TestSfmTrack2d.test_sfm_track_2d_constructor
None test_sfm_track_2d_constructor(self)
Definition: test_DsfTrackGenerator.py:111
test_DsfTrackGenerator.TestDsfTrackGenerator.test_generate_tracks_from_pairwise_matches_nontransitive
None test_generate_tracks_from_pairwise_matches_nontransitive(self)
Definition: test_DsfTrackGenerator.py:20
test_DsfTrackGenerator.TestDsfTrackGenerator
Definition: test_DsfTrackGenerator.py:17
gtsam::utils.test_case
Definition: test_case.py:1
gtsam::Point2
Vector2 Point2
Definition: Point2.h:32
test_DsfTrackGenerator.get_dummy_keypoints_list
List[Keypoints] get_dummy_keypoints_list()
Definition: test_DsfTrackGenerator.py:120
test_DsfTrackGenerator.get_nontransitive_matches
Dict[Tuple[int, int], np.ndarray] get_nontransitive_matches()
Definition: test_DsfTrackGenerator.py:168
gtsam::utils.test_case.GtsamTestCase
Definition: test_case.py:15
gtsam::IndexPair
Small utility class for representing a wrappable pairs of ints.
Definition: DSFMap.h:117
test_DsfTrackGenerator.TestDsfTrackGenerator.test_track_generation
None test_track_generation(self)
Definition: test_DsfTrackGenerator.py:43
len
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2399
gtsam::gtsfm::tracksFromPairwiseMatches
std::vector< SfmTrack2d > tracksFromPairwiseMatches(const MatchIndicesMap &matches, const KeypointsVector &keypoints, bool verbose)
Creates a list of tracks from 2d point correspondences.
Definition: DsfTrackGenerator.cpp:103


gtsam
Author(s):
autogenerated on Tue Jun 25 2024 03:05:28