def setUp(self): """Create a simple test project""" self.elements = ProjectObjectDict.example( ) # note: project_type = mesh # Note: We have to create a unique project pathname to pass stress testing # which runs jobs in parallel. self.temp_directory = tempfile.mkdtemp()
def run(self, project, target_type): """ Convert an in-memory project to the target type Inputs: project (ProjectScene) - input project target_type (string) - voxels or bounding_box Return: new_project (ProjectScene) - a project with the target project type Exceptions: ValueError - if target_type is not allowed for the given input project. See above for allowed conversions. """ if (project.project_type, target_type) not in self.allowed_conversions: raise ValueError("Invalid target_type ({}) for \ project with type {}".format(target_type, project.project_type)) new_settings = deepcopy(project.settings) new_elements = ProjectObjectDict() for element in project.elements.values(): new_element = self.convert_element(element, target_type) new_elements[new_element.id] = new_element new_project = ProjectScene(project_type=target_type, elements=new_elements, settings=new_settings) return new_project
def test_object_io(self): """Write to files and then read back in.""" # check that writing meshes creates the directory and stores a glb file there orig_pod = ProjectObjectDict.example() path = self.temp_directory xml = orig_pod.save(path) # FIXME: Disabled check. Only works in Python 3. # ET interface must be different. # self.assertIsInstance(xml, ET.Element) self.assertTrue( os.path.isfile(os.path.join(self.temp_directory, "1.glb"))) # check that reading meshes gives the same as what we started with new_pod = ProjectObjectDict.load("meshes", xml, path) self.assertTrue(new_pod.almost_equal(orig_pod)) for obj in orig_pod.values(): self.assertTrue(obj.almost_equal(new_pod[obj.id]))
def test_insertions(self): """Insert some ProjectObjects into a ProjectObjectDict.""" pod = ProjectObjectDict() self.assertTrue(isinstance(pod, ProjectObjectDict)) pod["a"] = self.pod["1"] pod["b"] = self.pod["2"] pod["c"] = self.pod["3"] self.assertEqual(len(pod), 3)
def load(cls, path, project_name): """ Read project from disk location <path>/<project_name> Returns: Newly created ProjectScene instance. Exceptions: IOError - if project cannot be read ValueError - if xml cannot be parsed """ settings = {} project_type = None project_dir = os.path.join(path, project_name) # Read xml from file xml_tree = ET.parse(os.path.join(project_dir, project_name + ".xml")) # parse xml tree root = xml_tree.getroot() if root.tag != "scene": raise ValueError('Expected root tag to be "scene"') # extract header info for element in root: if element.tag == "categories": for child_element in element: if child_element.tag == "id": settings["categories_id"] = child_element.text elif child_element.tag == "url": settings["categories_url"] = child_element.text elif element.tag == "project_type": project_type = element.text elif element.tag == "version": settings["version"] = element.text # Skip elements tag for now. # Any other tags are silently ignored if project_type is None: raise ValueError("xml is missing project_type tag") # extract elements for element in root: if element.tag == "elements": elements = ProjectObjectDict.load(project_type=project_type, base_elem=element, path=project_dir) # header and any other tags are silently ignored return cls(project_type, elements, settings)
def __init__(self, project_type, elements=None, settings=None): """ Constructor Inputs: project_type (string) - Specifies the project type to construct (valid values are "bounding_box", "voxels", or "meshes") settings (dict) - stores version, categories, etc. elements (ProjectObjectDict) Exceptions: IOError - if scene cannot be read ValueError - if xml cannot be parsed ValueError - if project_type is not one of the allowed options """ if project_type not in ["bounding_box", "voxels", "meshes"]: raise ValueError("Project type ({}) must be one of 'bounding_box', \ 'voxels', or 'mesh'".format(project_type)) self.project_type = project_type self.settings = settings if settings is not None else DEFAULT_SETTINGS self.elements = elements if elements is not None else ProjectObjectDict()
def setUp(self): """Create a few ProjectObjects for use in the ProjectObjectDict.""" self.pod = ProjectObjectDict.example() self.temp_directory = tempfile.mkdtemp()
def _compute_category_data_assoc(self, det_elements, gt_elements, thresholds, categories, sim_cache): """ Computes category-specific data association between the elements in <submission> and <ground_truth> for each similarity threshold in <thresholds>. Inputs: det_elements (ProjectObjectDict) - submitted/detected scene elements gt_elements (ProjectObjectDict) - corresponding ground truth scene elements thresholds (numpy vector of float) - Similarity thresholds to be used. sim_cache (dict of dict of Corrs) - similarity cache - sim_cache[det_id][gt_id] is similarity between det_id and gt_id. Return: data_assoc (dict of dicts of dicts of Corr) - data_assoc[category][thresh][det_id], where thresh is taken from <thresholds> and det_id is a detection ID. If a det_id is not in the dict, it means that no correspondance was found. Algorithm: For each category C in category list (from settings): 1. Get a list of elements in submission and GT belonging to that category; If both lists are empty, we skip the category. 2. Construct submission and ground truth ProjectScenes using only elements with category C. 3. Compute category-agnostic data association using these subsets. """ # Split detections and gt elements by category and store in # dict of ProjectObjectDicts. dets_by_cat = {} gts_by_cat = {} for cat in categories: dets_by_cat[cat] = ProjectObjectDict() gts_by_cat[cat] = ProjectObjectDict() for (id, element) in det_elements.items(): if element.category in categories: dets_by_cat[element.category][id] = element for (id, element) in gt_elements.items(): if element.category in categories: gts_by_cat[element.category][id] = element data_assoc = {} # for storing results (key is category) for cat in categories: dets = dets_by_cat[cat] gts = gts_by_cat[cat] if (len(dets) + len(gts)) == 0: continue # build mini sim_cache just for this category sim_cache_cat = {} for det_id in dets.keys(): sim_cache_cat[det_id] = {} for gt_id in gts.keys(): if gt_id in sim_cache[det_id]: sim_cache_cat[det_id][gt_id] = sim_cache[det_id][gt_id] # do data association data_assoc[cat] = self._compute_agnostic_data_assoc(dets, gts, thresholds, sim_cache_cat) return data_assoc