def test_set_name(self): algo_name = 'ci' other_name = "other_name" ci = ConvertImage(algo_name) nt.assert_equal(ci.name, algo_name) ci.set_name(other_name) nt.assert_not_equal(ci.name, algo_name) nt.assert_equal(ci.name, other_name)
def test_clone(self): # inst_ptr will be null for both ci1 = ConvertImage('ci') ci2 = ci1.clone() nt.assert_false(ci1) nt.assert_false(ci2) nt.assert_not_equal(ci1.c_pointer, ci2.c_pointer) # They should both be null nt.assert_equal(mem_address(ci1.c_pointer), mem_address(ci2.c_pointer))
def test_get_conf(self): ci = ConvertImage('ci') c = ci.get_config() nt.assert_list_equal(c.available_keys(), ['ci:type']) nt.assert_equal(c.get_value('ci:type'), '') ci = ConvertImage.create('ci', 'bypass') c = ci.get_config() nt.assert_equal(c.get_value('ci:type'), 'bypass')
def test_check_conf(self): ci = ConvertImage('ci') c = ConfigBlock() nt.assert_false(ci.check_config(c)) c.set_value('ci:type', '') nt.assert_false(ci.check_config(c)) c.set_value('ci:type', 'not_an_impl') nt.assert_false(ci.check_config(c))
def test_check_conf(self): ci = ConvertImage('ci') c = config_block() nt.assert_false(ci.check_config(c)) c.set_value('ci:type', '') nt.assert_false(ci.check_config(c)) c.set_value('ci:type', 'not_an_impl') nt.assert_false(ci.check_config(c))
def test_set_conf(self): ci = ConvertImage('ci') nt.assert_false(ci) nt.assert_is_none(ci.impl_name()) c = ConfigBlock() c.set_value('ci:type', 'bypass') ci.set_config(c) nt.assert_true(ci) nt.assert_equal(ci.impl_name(), 'bypass')
def __init__(self): AlgorithmPluginManager.register_plugins() # Algorithms self.algo_convert_img = ConvertImage("convert_image") self.algo_image_io = ImageIo("image_reader") self.algo_track_features = TrackFeatures("feature_tracker") # Other tool variables self.image_list_filepath = None self.mask_list_filepath = None self.invert_masks = False self.expect_multichannel_masks = False self.output_tracks_filepath = None
def base_algorithms(c=ConfigBlock()): """ Determine the algorithms and algorithm names used in this utility :type c: vital.ConfigBlock """ iio = ImageIo('image_reader') iio.set_config(c) ci = ConvertImage('convert_image') ci.set_config(c) tf = TrackFeatures('feature_tracker') tf.set_config(c) return iio, ci, tf
def test_clone(self): ci1 = ConvertImage.create('ci', 'bypass') ci2 = ci1.clone() nt.assert_true(ci1) nt.assert_true(ci2) nt.assert_not_equal(ci1.c_pointer, ci2.c_pointer) nt.assert_not_equal(mem_address(ci1.c_pointer), mem_address(ci2.c_pointer))
def test_from_c_ptr_no_name(self): nt.assert_raises( TypeError, ConvertImage, from_cptr=ConvertImage.C_TYPE_PTR(), ) nt.assert_raises(ValueError, ConvertImage, None)
def test_convert(self): ic1 = ImageContainer(Image()) ci = ConvertImage.create('ci', 'bypass') ic2 = ci.convert(ic1) nt.assert_not_equal(ic1, ic2) nt.assert_not_equal(ic1.c_pointer, ic2.c_pointer) nt.assert_equal(hex(mem_address(ic1.c_pointer)), hex(mem_address(ic2.c_pointer)))
def __init__(self): apm.register_plugins() # Algorithms self.algo_convert_img = ConvertImage("convert_image") self.algo_image_io = ImageIo("image_reader") self.algo_track_features = TrackFeatures("feature_tracker") # Other tool variables self.image_list_filepath = None self.mask_list_filepath = None self.invert_masks = False self.expect_multichannel_masks = False self.output_tracks_filepath = None
def test_clone_empty(self): ci_empty = ConvertImage('ci') ci_empty2 = ci_empty.clone() nt.assert_false(ci_empty) nt.assert_false(ci_empty2)
def test_from_c_ptr_no_name(self): nt.assert_raises( ValueError, ConvertImage.from_c_pointer, ConvertImage.C_TYPE_PTR(), )
def test_from_c_ptr_null(self): ci = ConvertImage.from_c_pointer( ConvertImage.C_TYPE_PTR(), name='ci' ) nt.assert_false(ci.c_pointer)
def test_impl_name(self): ci_empty = ConvertImage('ci') nt.assert_is_none(ci_empty.impl_name()) ci_bypass = ConvertImage.create('ci', 'bypass') nt.assert_equal(ci_bypass.impl_name(), 'bypass')
class TrackFeaturesTool(object): @property def log(self): return logging.getLogger("TrackFeaturesTool") def __init__(self): AlgorithmPluginManager.register_plugins() # Algorithms self.algo_convert_img = ConvertImage("convert_image") self.algo_image_io = ImageIo("image_reader") self.algo_track_features = TrackFeatures("feature_tracker") # Other tool variables self.image_list_filepath = None self.mask_list_filepath = None self.invert_masks = False self.expect_multichannel_masks = False self.output_tracks_filepath = None def get_configuration(self): """ :return: the current tool configuration :rtype: ConfigBlock """ c = ConfigBlock("track_features") c.set_value( "image_list_file", self.image_list_filepath or "", "Path to an input file containing new-line separated paths " "to sequential image files") c.set_value( "mask_list_file", self.mask_list_filepath or "", "Optional path to an input file containing new-line " "separated paths to mask images. This list should be " "parallel in association to files specified in " "``image_list_file``. Mask image must be the same size as " "the image they are associated with.\n" "\n" "Leave this blank if no image masking is desired.") c.set_value( "invert_masks", str(self.invert_masks).lower(), "If true, all mask images will be inverted after loading. " "This is useful if mask images read in use positive " "values to indicated masked areas instead of non-masked " "areas.") c.set_value( "expect_multichannel_masks", str(self.expect_multichannel_masks).lower(), "A majority of the time, mask images are a single channel, " "however it is feasibly possible that certain " "implementations may use multi-channel masks. If this is " "true we will expect multiple-channel mask images, " "warning when a single-channel mask is provided. If this " "is false we error upon seeing a multi-channel mask " "image.") c.set_value( "output_tracks_file", self.output_tracks_filepath or "", "Path to a file to write output tracks to. If this " "file exists, it will be overwritten.") # Required algorithm does not have an implemented interface yet # c.set_value("output_homography_file", # self.output_homography_filepath or "", # "Optional path to a file to write source-to-reference " # "homographies for each frame. Leave blank to disable this " # "output. The output_homography_generator algorithm type " # "only needs to be set if this is set.") self.algo_convert_img.get_config(c) self.algo_image_io.get_config(c) self.algo_track_features.get_config(c) return c def set_configuration(self, config): """ Set the tool configuration :param config: The configuration to set :type config: ConfigBlock """ self.algo_convert_img.set_config(config) self.algo_image_io.set_config(config) self.algo_track_features.set_config(config) abspath = lambda p: os.path.abspath(os.path.expanduser(p)) self.image_list_filepath = config.get_value('image_list_file', self.image_list_filepath) if self.image_list_filepath: self.image_list_filepath = abspath(self.image_list_filepath) self.mask_list_filepath = config.get_value('mask_list_file', self.mask_list_filepath) if self.mask_list_filepath: self.mask_list_filepath = abspath(self.mask_list_filepath) self.invert_masks = config.get_value_bool('invert_masks', self.invert_masks) self.expect_multichannel_masks = \ config.get_value_bool('expect_multichannel_masks', self.expect_multichannel_masks) self.output_tracks_filepath = \ config.get_value('output_tracks_file', self.output_tracks_filepath) if self.output_tracks_filepath: self.output_tracks_filepath = abspath(self.output_tracks_filepath) def validate_configuration(self): """ Check the current configuration for validity :return: True if valid, false if not. :type: bool """ if not self.image_list_filepath: self.log.error("No image list file provided") return False if not os.path.isfile(self.image_list_filepath): self.log.error( "Path given for image list does not refer to a file") return False if not self.output_tracks_filepath: self.log.error("No output tracks file privided") return False if self.mask_list_filepath and not os.path.isfile( self.mask_list_filepath): self.log.error("Specified a mask list filepath, but path did not " "refer to an existing file.") return False return ( # Algorithms should check out valid self.algo_convert_img.check_config( self.algo_convert_img.get_config()) and self.algo_image_io.check_config(self.algo_image_io.get_config()) and self.algo_track_features.check_config( self.algo_track_features.get_config())) def track_images(self): # Create list of input filepaths self.log.info("Reading input image list file...") with open(self.image_list_filepath, 'r') as image_list_file: input_filepaths = \ [line.strip() for line in image_list_file.readlines()] # Create a list of mask images if we were given a list file mask_filepaths = None if self.mask_list_filepath: self.log.info("Reading mask image list file...") with open(self.mask_list_filepath) as mask_list_file: mask_filepaths = \ [line.strip() for line in mask_list_file.readlines()] if len(input_filepaths) != len(mask_filepaths): self.log.error("Input and Mask image lists were not congruent " "in size.") return False # Check that the output tracks file is open-able and that the containing # directory exists. if not os.path.isdir(os.path.dirname(self.output_tracks_filepath)): self.log.info( "Creating containing directory for output tracks " "file: %s", os.path.dirname(self.output_tracks_filepath)) os.mkdir(os.path.dirname(self.output_tracks_filepath)) self.log.info("Testing that output tracks file is open-able...") test_f = open(self.output_tracks_filepath, 'w') test_f.close() tracks = TrackSet() for frame_num in xrange(len(input_filepaths)): input_img = self.algo_convert_img.convert( self.algo_image_io.load(input_filepaths[frame_num])) mask_img = None if mask_filepaths: mask_img = self.algo_convert_img.convert( self.algo_image_io.load(mask_filepaths[frame_num])) self.log.info("Processing frame %d...", frame_num) tracks = self.algo_track_features.track(tracks, frame_num, input_img, mask_img) self.log.info("Frame processing complete, writing out track set...") tracks.write_tracks_file(self.output_tracks_filepath)
def test_get_conf(self): ci = ConvertImage('ci') c = ci.get_config() nt.assert_list_equal(c.available_keys(), ['ci:type']) nt.assert_true(c.has_value('ci:type')) nt.assert_equal(c.get_value('ci:type'), '')
def test_create(self): ci = ConvertImage.create('ci', 'bypass') nt.assert_equal(ci.impl_name(), 'bypass')
def test_new(self): ci = ConvertImage('ci') nt.assert_false(ci) nt.assert_false(ci.c_pointer)
def test_set_conf(self): ci = ConvertImage('ci') nt.assert_false(ci) nt.assert_is_none(ci.impl_name())
def test_registered_names(self): nt.assert_in('bypass', ConvertImage.registered_names())
def test_impl_name(self): ci_empty = ConvertImage('ci') nt.assert_is_none(ci_empty.impl_name())
def test_typename(self): ci = ConvertImage('ci') nt.assert_equal(ci.type_name(), "convert_image")
def test_from_c_ptr_null(self): ci = ConvertImage.from_c_pointer(ConvertImage.C_TYPE_PTR(), name='ci') nt.assert_false(ci.c_pointer)
def test_from_c_ptr_copy(self): ci = ConvertImage('ci') ci_new = ConvertImage.from_c_pointer(ci.c_pointer, ci) nt.assert_is(ci.c_pointer, ci_new.c_pointer) nt.assert_equal(ci_new.name, ci.name)
def test_name(self): name = 'algo_name' ci = ConvertImage(name) nt.assert_equal(ci.name, name)
class TrackFeaturesTool (object): @property def log(self): return logging.getLogger("TrackFeaturesTool") def __init__(self): apm.register_plugins() # Algorithms self.algo_convert_img = ConvertImage("convert_image") self.algo_image_io = ImageIo("image_reader") self.algo_track_features = TrackFeatures("feature_tracker") # Other tool variables self.image_list_filepath = None self.mask_list_filepath = None self.invert_masks = False self.expect_multichannel_masks = False self.output_tracks_filepath = None def get_configuration(self): """ :return: the current tool configuration :rtype: ConfigBlock """ c = ConfigBlock("track_features") c.set_value("image_list_file", self.image_list_filepath or "", "Path to an input file containing new-line separated paths " "to sequential image files") c.set_value("mask_list_file", self.mask_list_filepath or "", "Optional path to an input file containing new-line " "separated paths to mask images. This list should be " "parallel in association to files specified in " "``image_list_file``. Mask image must be the same size as " "the image they are associated with.\n" "\n" "Leave this blank if no image masking is desired.") c.set_value("invert_masks", str(self.invert_masks).lower(), "If true, all mask images will be inverted after loading. " "This is useful if mask images read in use positive " "values to indicated masked areas instead of non-masked " "areas.") c.set_value("expect_multichannel_masks", str(self.expect_multichannel_masks).lower(), "A majority of the time, mask images are a single channel, " "however it is feasibly possible that certain " "implementations may use multi-channel masks. If this is " "true we will expect multiple-channel mask images, " "warning when a single-channel mask is provided. If this " "is false we error upon seeing a multi-channel mask " "image.") c.set_value("output_tracks_file", self.output_tracks_filepath or "", "Path to a file to write output tracks to. If this " "file exists, it will be overwritten.") # Required algorithm does not have an implemented interface yet # c.set_value("output_homography_file", # self.output_homography_filepath or "", # "Optional path to a file to write source-to-reference " # "homographies for each frame. Leave blank to disable this " # "output. The output_homography_generator algorithm type " # "only needs to be set if this is set.") self.algo_convert_img.get_config(c) self.algo_image_io.get_config(c) self.algo_track_features.get_config(c) return c def set_configuration(self, config): """ Set the tool configuration :param config: The configuration to set :type config: ConfigBlock """ self.algo_convert_img.set_config(config) self.algo_image_io.set_config(config) self.algo_track_features.set_config(config) abspath = lambda p: os.path.abspath(os.path.expanduser(p)) self.image_list_filepath = config.get_value('image_list_file', self.image_list_filepath) if self.image_list_filepath: self.image_list_filepath = abspath(self.image_list_filepath) self.mask_list_filepath = config.get_value('mask_list_file', self.mask_list_filepath) if self.mask_list_filepath: self.mask_list_filepath = abspath(self.mask_list_filepath) self.invert_masks = config.get_value_bool('invert_masks', self.invert_masks) self.expect_multichannel_masks = \ config.get_value_bool('expect_multichannel_masks', self.expect_multichannel_masks) self.output_tracks_filepath = \ config.get_value('output_tracks_file', self.output_tracks_filepath) if self.output_tracks_filepath: self.output_tracks_filepath = abspath(self.output_tracks_filepath) def validate_configuration(self): """ Check the current configuration for validity :return: True if valid, false if not. :type: bool """ if not self.image_list_filepath: self.log.error("No image list file provided") return False if not os.path.isfile(self.image_list_filepath): self.log.error("Path given for image list does not refer to a file") return False if not self.output_tracks_filepath: self.log.error("No output tracks file privided") return False if self.mask_list_filepath and not os.path.isfile(self.mask_list_filepath): self.log.error("Specified a mask list filepath, but path did not " "refer to an existing file.") return False return ( # Algorithms should check out valid self.algo_convert_img.check_config(self.algo_convert_img.get_config()) and self.algo_image_io.check_config(self.algo_image_io.get_config()) and self.algo_track_features.check_config(self.algo_track_features.get_config()) ) def track_images(self): # Create list of input filepaths self.log.info("Reading input image list file...") with open(self.image_list_filepath, 'r') as image_list_file: input_filepaths = \ [line.strip() for line in image_list_file.readlines()] # Create a list of mask images if we were given a list file mask_filepaths = None if self.mask_list_filepath: self.log.info("Reading mask image list file...") with open(self.mask_list_filepath) as mask_list_file: mask_filepaths = \ [line.strip() for line in mask_list_file.readlines()] if len(input_filepaths) != len(mask_filepaths): self.log.error("Input and Mask image lists were not congruent " "in size.") return False # Check that the output tracks file is open-able and that the containing # directory exists. if not os.path.isdir(os.path.dirname(self.output_tracks_filepath)): self.log.info("Creating containing directory for output tracks " "file: %s", os.path.dirname(self.output_tracks_filepath)) os.mkdir(os.path.dirname(self.output_tracks_filepath)) self.log.info("Testing that output tracks file is open-able...") test_f = open(self.output_tracks_filepath, 'w') test_f.close() tracks = TrackSet() for frame_num in xrange(len(input_filepaths)): input_img = self.algo_convert_img.convert( self.algo_image_io.load(input_filepaths[frame_num]) ) mask_img = None if mask_filepaths: mask_img = self.algo_convert_img.convert( self.algo_image_io.load(mask_filepaths[frame_num]) ) self.log.info("Processing frame %d...", frame_num) tracks = self.algo_track_features.track(tracks, frame_num, input_img, mask_img) self.log.info("Frame processing complete, writing out track set...") tracks.write_tracks_file(self.output_tracks_filepath)