def test_empty_len_size(self): ts = TrackSet() nt.assert_true(ts, "Invalid track set instance constructed") l = len(ts) s = ts.size() nt.assert_equal(l, 0) nt.assert_equal(l, s)
def test_new_nonempty(self): n = 10 tracks = [Track(i) for i in xrange(n)] ts = TrackSet(tracks) nt.assert_true(ts, "Invalid track set instance constructed") nt.assert_equal(len(ts), n) nt.assert_equal(ts.size(), n)
def test_new_nonempty(self): n = 10 tracks = [Track() for _ in xrange(n)] ts = TrackSet(tracks) nt.assert_true(ts, "Invalid track set instance constructed") nt.assert_equal(len(ts), n) nt.assert_equal(ts.size(), n)
def test_get_track_single(self): # get track when only track t = Track(0) ts = TrackSet([t]) u = ts.get_track(0) # Check that they're the same underlying instance nt.assert_equal(ctypes.addressof(t.c_pointer.contents), ctypes.addressof(u.c_pointer.contents))
def test_all_frame_ids_single_track(self): # From a single track n = 10 t = Track(1) for i in range(n): t.append(TrackState(i)) ts = TrackSet([t]) nt.assert_equal(ts.all_frame_ids(), set(range(10)))
def test_tracklist_accessor(self): n = 10 tracks = [Track(i) for i in range(n)] ts = TrackSet(tracks) ts_tracks = ts.tracks() nt.assert_equal(len(ts_tracks), n) for i, t in enumerate(ts_tracks): nt.assert_equal(t.id, i)
def test_get_track_multiple(self): n = 10 tracks = [Track(i) for i in range(n)] ts = TrackSet(tracks) # Check that they're the same underlying instance for i in range(n): nt.assert_equal( ctypes.addressof(ts.get_track(i).c_pointer.contents), ctypes.addressof(tracks[i].c_pointer.contents))
def test_all_frame_ids_multitrack(self): # Across multiple tracks n = 10 t1 = Track(1) for i in range(0, n): t1.append(TrackState(i)) t2 = Track(2) for i in range(n, n + 5): t2.append(TrackState(i)) ts = TrackSet([t1, t2]) nt.assert_equal(ts.all_frame_ids(), set(range(n + 5)))
def test_all_frame_ids_single_track(self): # From a single track n = 10 t = Track(1) for i in range(n): t.append(TrackState(i)) ts = TrackSet([t]) nt.assert_equal( ts.all_frame_ids(), set(range(10)) )
def test_all_frame_ids_multitrack(self): # Across multiple tracks n = 10 t1 = Track(1) for i in range(0, n): t1.append(TrackState(i)) t2 = Track(2) for i in range(n, n+5): t2.append(TrackState(i)) ts = TrackSet([t1, t2]) nt.assert_equal( ts.all_frame_ids(), set(range(n+5)) )
def test_get_track_empty(self): # Empty set ts = TrackSet() nt.assert_raises( IndexError, ts.get_track, 0 )
def triangulate(self, cameras, tracks, landmarks): """ Triangulate the landmark locations given sets of cameras and tracks This function only triangulates the landmarks with indices in the landmark map and which have support in the tracks and cameras :param cameras: cameras viewing the landmarks :type cameras: CameraMap :param tracks: tracks to use as constraints :type tracks: TrackSet :param landmarks: landmarks to triangulate :type landmarks: LandmarkMap :return: New landmarks instance of triangulated landmarks """ # Copy pointer container for reference updating so we don't pollute the # input instance. lmap_ptr = LandmarkMap.c_ptr_type()(landmarks.c_pointer.contents) self._call_cfunc( 'vital_algorithm_triangulate_landmarks_triangulate', [self.C_TYPE_PTR, CameraMap.c_ptr_type(), TrackSet.c_ptr_type(), ctypes.POINTER(LandmarkMap.c_ptr_type())], [self, cameras, tracks, ctypes.byref(landmarks)] ) r_lmap = landmarks if ctypes.addressof(lmap_ptr.contents) != ctypes.addressof(landmarks.c_pointer.contents): r_lmap = LandmarkMap(from_cptr=lmap_ptr) return r_lmap
def test_get_track_missing(self): # test failure to get track from set when set does have contents, but # TID is not present ts = TrackSet([Track(0), Track(1), Track(3)]) nt.assert_raises( IndexError, ts.get_track, 2 )
def test_last_frame(self): # no tracks ts = TrackSet() nt.assert_equal(ts.last_frame(), 0) # one track t = Track(1) t.append(TrackState(1)) t.append(TrackState(2)) ts = TrackSet([t]) nt.assert_equal(ts.last_frame(), 2) # two tracks t2 = Track(2) t2.append(TrackState(3)) ts = TrackSet([t, t2]) nt.assert_equal(ts.last_frame(), 3)
def track(self, prev_tracks, frame_num, image, mask=None): """ Extend a previous set of tracks using the given image. An optional mask image may be provided, where positive valued regions indicate regions of the input image to consider for feature tracking. The mask image must be of the same dimensions as the input image, other wise an exception is raised. :param prev_tracks: the tracks from previous tracking steps :type prev_tracks: TrackSet :param frame_num: the frame number of the current frame :type frame_num: int :param image: the image pixels for the current frame :type image: ImageContainer :param mask: Optional mask image that uses positive values to denote regions of the input image to consider for feature tracking. An empty sptr indicates no mask (default value). :type mask: ImageContainer :return: an updated set a tracks including the current frame :rtype: TrackSet """ tf_track_argtypes = [ self.C_TYPE_PTR, TrackSet.C_TYPE_PTR, ctypes.c_uint, ImageContainer.C_TYPE_PTR ] tf_track_args = [self, prev_tracks, frame_num, image] tf_track_restype = TrackSet.C_TYPE_PTR if mask: tf_track = self.VITAL_LIB['vital_algorithm_track_features_' 'track_with_mask'] tf_track_argtypes.append(ImageContainer.C_TYPE_PTR) tf_track_args.append(mask) else: tf_track = self.VITAL_LIB['vital_algorithm_track_features_track'] tf_track_argtypes.append(VitalErrorHandle.C_TYPE_PTR) tf_track.argtypes = tf_track_argtypes tf_track.restype = tf_track_restype with VitalErrorHandle() as eh: tf_track_args.append(eh) return TrackSet(from_cptr=tf_track(*tf_track_args))
def initialize(self, cmap, lmap, tset): """ Initialize the camera and landmark parameters given a set of tracks :param cmap: Cameras to initialize :type cmap: CameraMap :param lmap: Landmarks to initialize :type lmap: LandmarkMap :param tset: Tracks to use as constraints :type tset: TrackSet :return: New, initialized camera and landmark maps. :rtype: (CameraMap, LandmarkMap) """ # make a separate copy of pointer container in prep for passing by ref cmap_ptr = CameraMap.c_ptr_type()(cmap.c_pointer.contents) lmap_ptr = LandmarkMap.c_ptr_type()(lmap.c_pointer.contents) self._call_cfunc( "vital_algorithm_initialize_cameras_landmarks_initialize", [ self.C_TYPE_PTR, ctypes.POINTER(CameraMap.c_ptr_type()), ctypes.POINTER(LandmarkMap.c_ptr_type()), TrackSet.c_ptr_type() ], [self, ctypes.byref(cmap_ptr), ctypes.byref(lmap_ptr), tset]) # Initialize new objects if "returned" pointers are different from input # objects r_cmap = cmap if ctypes.addressof(cmap_ptr.contents) != ctypes.addressof( cmap.c_pointer.contents): self._log.debug("Creating new CameraMap instance") r_cmap = CameraMap(from_cptr=cmap_ptr) r_lmap = lmap if ctypes.addressof(lmap_ptr.contents) != ctypes.addressof( lmap.c_pointer.contents): self._log.debug("Creating new LandmarkMap instance") r_lmap = LandmarkMap(from_cptr=lmap_ptr) return r_cmap, r_lmap
def optimize(self, cmap, lmap, tset): """ Optimize the camera and landmark parameters given a set of tracks :param cmap: Cameras to optimize :type cmap: CameraMap :param lmap: Landmarks to optimize :type lmap: LandmarkMap :param tset: Tracks to use as constraints :type tset: TrackSet :return: New, optimized Camera and Landmark maps. :rtype: (CameraMap, LandmarkMap) """ # make a separate copy of pointer container in prep for passing by ref cmap_ptr = CameraMap.c_ptr_type()(cmap.c_pointer.contents) lmap_ptr = LandmarkMap.c_ptr_type()(lmap.c_pointer.contents) self._call_cfunc( 'vital_algorithm_bundle_adjust_optimize', [self.C_TYPE_PTR, ctypes.POINTER(CameraMap.c_ptr_type()), ctypes.POINTER(LandmarkMap.c_ptr_type()), TrackSet.c_ptr_type()], [self, ctypes.byref(cmap_ptr), ctypes.byref(lmap_ptr), tset] ) # Initialize new objects if "returned" pointers are different from input # objects r_cmap = cmap if ctypes.addressof(cmap_ptr.contents) != ctypes.addressof(cmap.c_pointer.contents): self._log.debug("Creating new CameraMap instance") r_cmap = CameraMap(from_cptr=cmap_ptr) r_lmap = lmap if ctypes.addressof(lmap_ptr.contents) != ctypes.addressof(lmap.c_pointer.contents): self._log.debug("Creating new LandmarkMap instance") r_lmap = LandmarkMap(from_cptr=lmap_ptr) return r_cmap, r_lmap
def track(self, prev_tracks, frame_num, image, mask=None): """ Extend a previous set of tracks using the given image. An optional mask image may be provided, where positive valued regions indicate regions of the input image to consider for feature tracking. The mask image must be of the same dimensions as the input image, other wise an exception is raised. :param prev_tracks: :param frame_num: :param image: :param mask: :return: """ tf_track_argtypes = [ self.C_TYPE_PTR, TrackSet.C_TYPE_PTR, ctypes.c_uint, ImageContainer.C_TYPE_PTR ] tf_track_args = [self, prev_tracks, frame_num, image] tf_track_restype = TrackSet.C_TYPE_PTR if mask: tf_track = self.VITAL_LIB['vital_algorithm_track_features_' 'track_with_mask'] tf_track_argtypes.append(ImageContainer.C_TYPE_PTR) tf_track_args.append(mask) else: tf_track = self.VITAL_LIB['vital_algorithm_track_features_track'] tf_track_argtypes.append(VitalErrorHandle.C_TYPE_PTR) tf_track.argtypes = tf_track_argtypes tf_track.restype = tf_track_restype with VitalErrorHandle() as eh: tf_track_args.append(eh) return TrackSet(from_cptr=tf_track(*tf_track_args))
def test_tracklist_accessor(self): n = 10 tracks = [Track(i) for i in xrange(n)] ts = TrackSet(tracks) ts_tracks = ts.tracks() nt.assert_equal(len(ts_tracks), n) for i, t in enumerate(ts_tracks): nt.assert_equal(t.id, i) # constructing a new trackset from the returned list of tracks should # yield a trackset whose accessor should return the same list of tracks # (same C/C++ instances). ts2 = TrackSet(ts_tracks) ts2_tracks = ts2.tracks() for i in xrange(n): ctypes.addressof(ts2_tracks[0].c_pointer.contents) \ == ctypes.addressof(ts2_tracks[0].c_pointer.contents)
def triangulate(self, cameras, tracks, landmarks): """ Triangulate the landmark locations given sets of cameras and tracks This function only triangulates the landmarks with indices in the landmark map and which have support in the tracks and cameras :param cameras: cameras viewing the landmarks :type cameras: CameraMap :param tracks: tracks to use as constraints :type tracks: TrackSet :param landmarks: landmarks to triangulate :type landmarks: LandmarkMap :return: New landmarks instance of triangulated landmarks """ # Copy pointer container for reference updating so we don't pollute the # input instance. lmap_ptr = LandmarkMap.c_ptr_type()(landmarks.c_pointer.contents) self._call_cfunc('vital_algorithm_triangulate_landmarks_triangulate', [ self.C_TYPE_PTR, CameraMap.c_ptr_type(), TrackSet.c_ptr_type(), ctypes.POINTER(LandmarkMap.c_ptr_type()) ], [self, cameras, tracks, ctypes.byref(landmarks)]) r_lmap = landmarks if ctypes.addressof(lmap_ptr.contents) != ctypes.addressof( landmarks.c_pointer.contents): r_lmap = LandmarkMap(from_cptr=lmap_ptr) return r_lmap
def subset_tracks(trackset, keep_fraction=0.75): """ randomly drop a fraction of the track states per track in the given set, creating and returning new tracks in a new track-set. :type trackset: TrackSet :type keep_fraction: float """ log = logging.getLogger(__name__) new_tracks = [] for t in trackset.tracks(): nt = Track(t.id) msg = 'track %d:' % t.id, for ts in t: if numpy.random.rand() < keep_fraction: nt.append(ts) msg += '.', else: msg += 'X', log.info(' '.join(msg)) new_tracks.append(nt) return TrackSet(new_tracks)
def projected_tracks(lmap, cmap): """ Use the cameras to project the landmarks back into their images. :type lmap: LandmarkMap :type cmap: CameraMap """ tracks = [] cam_d = cmap.as_dict() landmark_d = lmap.as_dict() for lid, l in landmark_d.iteritems(): t = Track(lid) tracks.append(t) # Sort camera iteration to make sure that we go in order of frame IDs for fid in sorted(cam_d): cam = cam_d[fid] f = Feature(cam.project(l.loc)) t.append(TrackState(fid, f)) assert t.size == len(cam_d) return TrackSet(tracks)
def test_get_track_single(self): # get track when only track t = Track(0) ts = TrackSet([t]) u = ts.get_track(0)
def test_new(self): ts = TrackSet()
def test_empty_len_size(self): ts = TrackSet() l = len(ts) s = ts.size() nt.assert_equal(l, 0) nt.assert_equal(l, s)
def main(): # Same logging format as C++, except for ',' separating milliseconds logging.basicConfig(format="%(asctime)s %(levelname)s %(filename)s(%(lineno)s): %(message)s") logging.getLogger().setLevel(logging.INFO) log = logging.getLogger(__name__) args = parse_args() register_plugins_once() c = default_config_block() # Read in config file if given if args.config: c.read(args.config) # Set algorithm configurations + update config-block image_reader, image_converter, feature_tracker = base_algorithms() image_reader.set_config(c) image_reader.get_config(c) image_converter.set_config(c) image_converter.get_config(c) feature_tracker.set_config(c) feature_tracker.get_config(c) if args.generate_config: check_config(c) c.write(args.generate_config) log.info("Generated configuration: %s", args.generate_config) sys.exit(0) if not check_config(c): raise RuntimeError("Configuration invalid. " "Check above warning messages.") image_list_fp = c.get_value('image_list_file') mask_list_fp = c.get_value('mask_list_file') output_tracks_fp = c.get_value('output_tracks_file') # Read in image files, and optional mask files # iterate over track features function with open(image_list_fp) as f: frame_list = [l.strip() for l in f] if mask_list_fp: with open(mask_list_fp) as f: mask_list = [l.strip() for l in f] else: mask_list = [None] * len(frame_list) assert len(frame_list) == len(mask_list), \ "Image and mask list is not congruent in size (%d images != %d " \ "masks)" % (len(frame_list), len(mask_list)) # Track over frames + masks track_set = TrackSet() for i, (f, m) in enumerate(itertools.izip(frame_list, mask_list)): log.info("Processing frame: %s", f) frame = image_converter.convert(image_reader.load(f)) mask = (m and image_converter.convert(image_reader.load(m))) or None track_set = feature_tracker.track(track_set, i, frame, mask) # TODO: maptk::extract_feature_colors? log.info("Writing tracks file: %s", output_tracks_fp) safe_create_dir(os.path.dirname(output_tracks_fp)) track_set.write_feature_tracks_file(output_tracks_fp)
def test_new_nonempty(self): n = 10 tracks = [Track(i) for i in range(n)] ts = TrackSet(tracks) nt.assert_equal(len(ts), n) nt.assert_equal(ts.size(), n)
def test_new(self): ts = TrackSet() nt.assert_true(ts, "Invalid track set instance constructed")
def main(): # Same logging format as C++, except for ',' separating milliseconds logging.basicConfig( format="%(asctime)s %(levelname)s %(filename)s(%(lineno)s): %(message)s" ) logging.getLogger().setLevel(logging.INFO) log = logging.getLogger(__name__) args = parse_args() register_plugins_once() c = default_config_block() # Read in config file if given if args.config: c.read(args.config) # Set algorithm configurations + update config-block image_reader, image_converter, feature_tracker = base_algorithms() image_reader.set_config(c) image_reader.get_config(c) image_converter.set_config(c) image_converter.get_config(c) feature_tracker.set_config(c) feature_tracker.get_config(c) if args.generate_config: check_config(c) c.write(args.generate_config) log.info("Generated configuration: %s", args.generate_config) sys.exit(0) if not check_config(c): raise RuntimeError("Configuration invalid. " "Check above warning messages.") image_list_fp = c.get_value('image_list_file') mask_list_fp = c.get_value('mask_list_file') output_tracks_fp = c.get_value('output_tracks_file') # Read in image files, and optional mask files # iterate over track features function with open(image_list_fp) as f: frame_list = [l.strip() for l in f] if mask_list_fp: with open(mask_list_fp) as f: mask_list = [l.strip() for l in f] else: mask_list = [None] * len(frame_list) assert len(frame_list) == len(mask_list), \ "Image and mask list is not congruent in size (%d images != %d " \ "masks)" % (len(frame_list), len(mask_list)) # Track over frames + masks track_set = TrackSet() for i, (f, m) in enumerate(itertools.izip(frame_list, mask_list)): log.info("Processing frame: %s", f) frame = image_converter.convert(image_reader.load(f)) mask = (m and image_converter.convert(image_reader.load(m))) or None track_set = feature_tracker.track(track_set, i, frame, mask) # TODO: maptk::extract_feature_colors? log.info("Writing tracks file: %s", output_tracks_fp) safe_create_dir(os.path.dirname(output_tracks_fp)) track_set.write_feature_tracks_file(output_tracks_fp)