def object_init_data(self, frame_num=None) -> dict: """ :param frame_num: 0 :return: {'init_object_ids', 'init_mask', 'object_ids', 'sequence_object_ids'} """ if frame_num is None: frame_num = 0 if frame_num not in self.init_data: # 不是第0帧就返回空dictionary return dict() init_data = dict() # 把self.init_data的东西移到init_data中,keys以'init_'开头 for key, val in self.init_data[frame_num].items(): if val is None: continue init_data['init_' + key] = val if 'init_mask' in init_data and init_data['init_mask'] is not None: # read mask image to numpy array anno = imread_indexed(init_data['init_mask']) if not self.multiobj_mode and self.object_ids is not None: assert len(self.object_ids) == 1 anno = (anno == int(self.object_ids[0])).astype(np.uint8) init_data['init_mask'] = anno if self.object_ids is not None: # self.object_ids = sequence_info['object_ids'] init_data['object_ids'] = self.object_ids init_data['sequence_object_ids'] = self.object_ids # init_object_ids == object_ids == sequence_object_ids return init_data
def get_image_info(self, im_id): mask = imread_indexed( os.path.join(self.root, 'Imgs', '{}.png'.format(self.image_list[im_id]))) mask = torch.Tensor(mask == 255) bbox = masks_to_bboxes(mask, fmt='t').view(4, ) valid = (bbox[2] > 0) & (bbox[3] > 0) visible = valid.clone().byte() return {'bbox': bbox, 'mask': mask, 'valid': valid, 'visible': visible}
def _load_dataset(self, min_area=None): files_list = os.listdir(os.path.join(self.root, 'Imgs')) image_list = [f[:-4] for f in files_list if f[-3:] == 'jpg'] images = [] for f in image_list: a = imread_indexed( os.path.join(self.root, 'Imgs', '{}.png'.format(f))) if min_area is None or (a > 0).sum() > min_area: images.append(f) return images
def _load_dataset(self, min_area=None): files_list = os.listdir(os.path.join(self.root, 'imgs')) image_list = [f[:-4] for f in files_list] images = [] annos = [] for f in image_list: a = imread_indexed( os.path.join(self.root, 'gt', '{}.png'.format(f))) if min_area is None or (a > 0).sum() > min_area: im = opencv_loader( os.path.join(self.root, 'imgs', '{}.png'.format(f))) images.append(im) annos.append(a) return images, annos
def object_init_data(self, frame_num=None) -> dict: if frame_num is None: frame_num = 0 if frame_num not in self.init_data: return dict() init_data = dict() for key, val in self.init_data[frame_num].items(): if val is None: continue init_data['init_' + key] = val if 'init_mask' in init_data and init_data['init_mask'] is not None: anno = imread_indexed(init_data['init_mask']) if not self.multiobj_mode and self.object_ids is not None: assert len(self.object_ids) == 1 anno = (anno == int(self.object_ids[0])).astype(np.uint8) init_data['init_mask'] = anno if self.object_ids is not None: init_data['object_ids'] = self.object_ids init_data['sequence_object_ids'] = self.object_ids return init_data
def generate(cls, dset_name: str, dset_images_path: Path, dset_annos_path: Path): """ Count the annotation mask pixels per object, per frame, in all sequences in a dataset :param dset_name: Dataset name, for printing the progress bar. :param dset_annos_path: Path to annotations directory, containing sequence directories, with annotation frames in them. :return: Dataset meta dict: {'sequence0': { 'shape': (height, width) 'obj_sizes': # Object pixels per frame {'frame0': {'object0': px_count, 'object1': px_count, ...}, 'frame1': {'object0': px_count, 'object1': px_count, ...}, ... }, 'bboxes': # Bounding boxes per frame {'frame0': {'object0': bbox, 'object1': bbox, ...}, 'frame1': {'object0': bbox, 'object1': bbox, ...}, ... }, ... } """ assert (dset_annos_path.exists()) dset_meta = OrderedDict() sequences = [ p.stem for p in sorted(dset_annos_path.glob("*")) if p.is_dir() ] try: from tqdm import tqdm except: def tqdm(x, *args, **kwargs): return x for seq in tqdm(sequences, desc=dset_name, unit="seq"): obj_sizes2 = defaultdict(OrderedDict) bboxes = defaultdict(OrderedDict) shape = None frame_names = [ file.stem for file in sorted((dset_images_path / seq).glob("*.jpg")) ] anno_paths = list(sorted((dset_annos_path / seq).glob("*.png"))) # Extract information from the given label frames for path in anno_paths: f_id = path.stem # Count label-pixels per frame labels = imread_indexed(path) # labels = np.array(Image.open(path)) obj_ids, obj_sizes = np.unique(labels, return_counts=True) obj_ids = [str(oid) for oid in obj_ids] obj_sizes = obj_sizes.tolist() if '0' in obj_ids: # Remove background id obj_ids = obj_ids[1:] obj_sizes = obj_sizes[1:] obj_sizes2[f_id] = OrderedDict(zip(obj_ids, obj_sizes)) # Generate per-label bounding boxes for obj_id in obj_ids: bboxes[f_id][obj_id] = cls._mask_to_bbox( labels == int(obj_id)) if shape is None: shape = labels.shape[:2] # Format result dset_meta[seq] = dict(shape=shape, obj_sizes=obj_sizes2, bboxes=bboxes, frame_names=frame_names) return VOSMeta(dset_meta)
def _load_anno(path): if not path.exists(): return None # im = np.atleast_3d(np.array(Image.open(path))) im = imread_indexed(path) return im
def evaluate_dataset(results_path, dset_name, measure='J', to_file=True, scores=False, sequences=None, quiet=False): dset = get_dataset(dset_name) results = OrderedDict() dset_scores = [] dset_decay = [] dset_recall = [] if to_file: f = open(results_path / ("evaluation-%s.txt" % measure), "w") def _print(msg): if not quiet: print(msg) if to_file: print(msg, file=f) if sequences is not None: sequences = [sequences] if not isinstance(sequences, (list, tuple)) else sequences target_names = [] for j, sequence in enumerate(dset): if (sequences is not None) and (sequence.name not in sequences): continue # Load all frames frames = sequence.ground_truth_seg annotations = OrderedDict() segmentations = OrderedDict() for f in frames: if f is None: continue file = Path(f) annotations[file.name] = imread_indexed(file) if not scores: segmentations[file.name] = imread_indexed( os.path.join(results_path, sequence.name, file.name)) else: raise NotImplementedError # Find object ids and starting frames object_info = dict() for f_id, d in sequence.init_data.items(): for obj_id in d['object_ids']: object_info[int(obj_id)] = Path(d['mask']).name if 0 in object_info: # Remove background object_info.pop(0) # Evaluate n_seqs = len(dset) n_objs = len(object_info) seq_name = sequence.name _print("%d/%d: %s: %d object%s" % (j + 1, n_seqs, seq_name, n_objs, "s" if n_objs > 1 else "")) r = evaluate_sequence(seq_name, segmentations, annotations, object_info, measure=measure) results[seq_name] = r # Print scores, per frame and object, ignoring NaNs per_obj_score = [] # Per-object accuracies, averaged over the sequence per_frame_score = [] # Per-frame accuracies, averaged over the objects for obj_id, score in r['raw'].items(): target_names.append('{}_{}'.format(seq_name, obj_id)) per_frame_score.append(score) s = utils.mean(score) # Sequence average for one object per_obj_score.append(s) if n_objs > 1: _print("joint {obj}: acc {score:.3f} ┊{apf}┊".format( obj=obj_id, score=s, apf=utils.text_bargraph(score))) # Print mean object score per frame and final score dset_decay.extend(r['decay']) dset_recall.extend(r['recall']) dset_scores.extend(per_obj_score) seq_score = utils.mean(per_obj_score) # Final score seq_mean_score = utils.nanmean(np.array(per_frame_score), axis=0) # Mean object score per frame # Print sequence results _print("final : acc {seq:.3f} ({dset:.3f}) ┊{apf}┊".format( seq=seq_score, dset=np.mean(dset_scores), apf=utils.text_bargraph(seq_mean_score))) _print("%s: %.3f, recall: %.3f, decay: %.3f" % (measure, utils.mean(dset_scores), utils.mean(dset_recall), utils.mean(dset_decay))) if to_file: f.close() return target_names, dset_scores, dset_recall, dset_decay