예제 #1
0
    def __init__(self,
                 root_dir,
                 coco_dir,
                 set_dir,
                 preproc=None,
                 target_transform=None,
                 dataset_name='COCO'):
        self.root = root_dir
        self.root_dir = root_dir
        self.coco_dir = coco_dir
        self.set_dir = set_dir
        self.coco_name = root_dir.replace("/", "") + "_" + coco_dir.replace(
            "/", "") + "_" + set_dir.replace("/", "")
        self.data_path = os.getcwd()
        self.cache_path = os.path.join(self.data_path, 'coco_cache')
        if (not os.path.isdir(self.cache_path)):
            os.mkdir(self.cache_path)

        self.image_set = set_dir
        self.preproc = preproc

        self.target_transform = target_transform
        self.name = dataset_name
        self.ids = list()
        self.annotations = list()

        annofile = self._get_ann_file(set_dir)
        _COCO = COCO(annofile)
        self._COCO = _COCO

        self._classes = ['__background__']
        self._classes_file = os.path.join(self.root_dir, self.coco_dir,
                                          'annotations', 'classes.txt')
        f = open(self._classes_file)
        lines = f.readlines()
        f.close()
        for i in range(len(lines)):
            self._classes.append(lines[i][:len(lines[i]) - 1])
        self._classes = tuple(self._classes)

        self.num_classes = len(self._classes)
        cats = _COCO.loadCats(_COCO.getCatIds())
        self._class_to_ind = dict(zip(self._classes, range(self.num_classes)))
        self._class_to_coco_cat_id = dict(
            zip([c['name'] for c in cats], _COCO.getCatIds()))

        indexes = _COCO.getImgIds()
        self.image_indexes = indexes
        self.ids.extend(
            [self.image_path_from_index(index) for index in indexes])
        self.annotations.extend(
            self._load_coco_annotations(self.coco_name, indexes, _COCO))
예제 #2
0
    def __init__(self,
                 root,
                 image_sets,
                 preproc=None,
                 target_transform=None,
                 dataset_name='COCO'):
        self.root = root
        # self.data_path = os.path.join(os.path.expanduser("~"),'datasets')
        self.data_path = os.path.join(self.root, "data")
        self.cache_path = os.path.join(self.data_path, 'coco_cache')
        self.image_set = image_sets
        self.preproc = preproc
        self.target_transform = target_transform
        self.name = dataset_name
        self.img_paths = list()
        self.annotations = list()
        self._view_map = {
            'minival2014': 'val2014',  # 5k val2014 subset
            'valminusminival2014': 'val2014',  # val2014 \setminus minival2014
            'test-dev2015': 'test2015',
        }

        for (year, image_set) in image_sets:
            coco_name = image_set + year
            data_name = (self._view_map[coco_name]
                         if coco_name in self._view_map else coco_name)
            annofile = self._get_ann_file(coco_name)
            _COCO = COCO(annofile)
            self._COCO = _COCO
            self.coco_name = coco_name
            cats = _COCO.loadCats(_COCO.getCatIds())
            self._classes = tuple(['__background__'] +
                                  [c['name'] for c in cats])
            self.num_classes = len(self._classes)
            self._class_to_ind = dict(
                zip(self._classes, range(self.num_classes)))
            self._class_to_coco_cat_id = dict(
                zip([c['name'] for c in cats], _COCO.getCatIds()))
            indexes = _COCO.getImgIds()
            self.image_indexes = indexes
            self.img_paths.extend([
                self.image_path_from_index(data_name, index)
                for index in indexes
            ])
            if image_set.find('test') != -1:
                print('test set will not load annotations!')
            else:
                self.annotations.extend(
                    self._load_coco_annotations(coco_name, indexes, _COCO))
예제 #3
0
class COCODetection(data.Dataset):
    """VOC Detection Dataset Object

    input is image, target is annotation

    Arguments:
        root (string): filepath to VOCdevkit folder.
        image_set (string): imageset to use (eg. 'train', 'val', 'test')
        transform (callable, optional): transformation to perform on the
            input image
        target_transform (callable, optional): transformation to perform on the
            target `annotation`
            (eg: take in caption string, return tensor of word indices)
        dataset_name (string, optional): which dataset to load
            (default: 'VOC2007')
    """
    def __init__(self,
                 root,
                 image_sets,
                 preproc=None,
                 target_transform=None,
                 dataset_name='COCO'):
        self.root = root
        self.cache_path = os.path.join(self.root, 'cache')
        self.image_set = image_sets
        self.preproc = preproc
        self.target_transform = target_transform
        self.name = dataset_name
        self.ids = list()
        self.annotations = list()

        for (year, image_set) in image_sets:
            coco_name = image_set + year
            image_root = os.path.join(root, 'images',
                                      _PREDEFINED_SPLITS_COCO[coco_name][0])
            annofile = os.path.join(root,
                                    _PREDEFINED_SPLITS_COCO[coco_name][1])
            self._COCO = COCO(annofile)
            self.coco_name = coco_name
            self.class_name = self._get_coco_instances_meta()
            self.num_classes = len(self.class_name)
            self.img_ids = sorted(self._COCO.imgs.keys())
            imgs = self._COCO.loadImgs(self.img_ids)
            self.ids.extend(
                [os.path.join(image_root, img["file_name"]) for img in imgs])
            self.annotations.extend(
                self._load_coco_annotations(coco_name, self.img_ids,
                                            self._COCO))

    def _load_coco_annotations(self, coco_name, indexes, _COCO):
        cache_file = os.path.join(self.cache_path, coco_name + '_gt_roidb.pkl')
        if os.path.exists(cache_file):
            with open(cache_file, 'rb') as fid:
                roidb = pickle.load(fid)
            print('{} gt roidb loaded from {}'.format(coco_name, cache_file))
            return roidb

        gt_roidb = [
            self._annotation_from_index(index, _COCO) for index in indexes
        ]
        if not os.path.exists(os.path.dirname(cache_file)):
            os.makedirs(os.path.dirname(cache_file))
        with open(cache_file, 'wb') as fid:
            pickle.dump(gt_roidb, fid, pickle.HIGHEST_PROTOCOL)
        print('wrote gt roidb to {}'.format(cache_file))
        return gt_roidb

    def _get_coco_instances_meta(self):
        thing_ids = self._COCO.getCatIds()
        cats = self._COCO.loadCats(thing_ids)
        cats_name = [c['name'] for c in cats]
        self._class_to_coco_cat_id = dict(zip(cats_name, thing_ids))

        voc_inds = (0, 1, 2, 3, 4, 5, 6, 8, 14, 15, 16, 17, 18, 19, 39, 56, 57,
                    58, 60, 62)
        nonvoc_inds = tuple([i for i in range(80) if i not in voc_inds])
        if 'nonvoc' in self.coco_name:
            self.id_map = nonvoc_inds
            thing_ids = [thing_ids[i] for i in self.id_map]
            thing_classes = [cats_name[k] for k in self.id_map]
        elif 'voc' in self.coco_name:
            self.id_map = voc_inds
            thing_ids = [thing_ids[i] for i in self.id_map]
            thing_classes = [cats_name[k] for k in self.id_map]
        self._thing_dataset_id_to_contiguous_id = {
            k: i
            for i, k in enumerate(thing_ids, 1)
        }
        return thing_classes

    def _annotation_from_index(self, index, _COCO):
        """
        Loads COCO bounding-box instance annotations. Crowd instances are
        handled by marking their overlaps (with all categories) to -1. This
        overlap value means that crowd "instances" are excluded from training.
        """
        im_ann = _COCO.loadImgs(index)[0]
        width = im_ann['width']
        height = im_ann['height']

        annIds = _COCO.getAnnIds(imgIds=index, iscrowd=None)
        objs = _COCO.loadAnns(annIds)
        # Sanitize bboxes -- some are invalid
        valid_objs = []
        for obj in objs:
            x1 = np.max((0, obj['bbox'][0]))
            y1 = np.max((0, obj['bbox'][1]))
            x2 = np.min((width - 1, x1 + np.max((0, obj['bbox'][2] - 1))))
            y2 = np.min((height - 1, y1 + np.max((0, obj['bbox'][3] - 1))))
            if obj['area'] > 0 and x2 >= x1 and y2 >= y1:
                obj['clean_bbox'] = [x1, y1, x2, y2]
                valid_objs.append(obj)
        objs = valid_objs
        num_objs = len(objs)

        res = np.zeros((num_objs, 5))

        # Lookup table to map from COCO category ids to our internal class
        # indices
        for ix, obj in enumerate(objs):
            cls = self._thing_dataset_id_to_contiguous_id[obj['category_id']]
            res[ix, 0:4] = obj['clean_bbox']
            res[ix, 4] = cls

        return res

    def __getitem__(self, index):
        img_id = self.ids[index]
        target = self.annotations[index]
        img = cv2.imread(img_id, cv2.IMREAD_COLOR)
        height, width, _ = img.shape

        if self.target_transform is not None:
            target = self.target_transform(target)

        if self.preproc is not None:
            img, target = self.preproc(img, target)

        # in order to be compatible with mixup
        weight = np.ones((target.shape[0], 1))
        target = np.hstack((target, weight))

        return img, target

    def __len__(self):
        return len(self.ids)

    def pull_image(self, index):
        '''Returns the original image object at index in PIL form

        Note: not using self.__getitem__(), as any transformations passed in
        could mess up this functionality.

        Argument:
            index (int): index of img to show
        Return:
            PIL img
        '''
        img_id = self.ids[index]
        return cv2.imread(img_id, cv2.IMREAD_COLOR)

    def pull_tensor(self, index):
        '''Returns the original image at an index in tensor form

        Note: not using self.__getitem__(), as any transformations passed in
        could mess up this functionality.

        Argument:
            index (int): index of img to show
        Return:
            tensorized version of img, squeezed
        '''
        return torch.Tensor(self.pull_image(index)).unsqueeze_(0)

    def _do_detection_eval(self, res_file):
        coco_dt = self._COCO.loadRes(res_file)
        coco_eval = COCOeval(self._COCO, coco_dt, 'bbox')
        coco_eval.evaluate()
        coco_eval.accumulate()
        coco_eval.summarize()
        results = OrderedDict()
        results['bbox'] = self._derive_coco_results(
            coco_eval, 'bbox', class_names=self.class_name)
        print_csv_format(results)

    def _coco_results_one_category(self, boxes, cat_id):
        results = []
        for im_ind, index in enumerate(self.img_ids):
            dets = boxes[im_ind].astype(np.float)
            if dets == []:
                continue
            scores = dets[:, -1]
            xs = dets[:, 0]
            ys = dets[:, 1]
            ws = dets[:, 2] - xs + 1
            hs = dets[:, 3] - ys + 1
            results.extend([{
                'image_id': index,
                'category_id': cat_id,
                'bbox': [xs[k], ys[k], ws[k], hs[k]],
                'score': scores[k]
            } for k in range(dets.shape[0])])
        return results

    def _write_coco_results_file(self, all_boxes, res_file):
        # [{"image_id": 42,
        #   "category_id": 18,
        #   "bbox": [258.15,41.29,348.26,243.78],
        #   "score": 0.236}, ...]
        results = []
        for cls_ind, cls in enumerate(self.class_name, 1):
            print('Collecting {} results ({:d}/{:d})'.format(
                cls, cls_ind, self.num_classes))
            coco_cat_id = self._class_to_coco_cat_id[cls]
            results.extend(
                self._coco_results_one_category(all_boxes[cls_ind],
                                                coco_cat_id))
        print('Writing results json to {}'.format(res_file))
        with open(res_file, 'w') as fid:
            json.dump(results, fid)
            fid.flush()

    def evaluate_detections(self, all_boxes, output_dir):
        res_file = os.path.join(output_dir,
                                'detections_' + self.coco_name + '_results')
        res_file += '.json'
        self._write_coco_results_file(all_boxes, res_file)
        # Only do evaluation on non-test sets
        if self.coco_name.find('test') == -1:
            self._do_detection_eval(res_file)

    def _derive_coco_results(self, coco_eval, iou_type, class_names=None):
        """
        Derive the desired score numbers from summarized COCOeval.

        Args:
            coco_eval (None or COCOEval): None represents no predictions from model.
            iou_type (str):
            class_names (None or list[str]): if provided, will use it to predict
                per-category AP.

        Returns:
            a dict of {metric name: score}
        """

        metrics = {
            "bbox": ["AP", "AP50", "AP75", "APs", "APm", "APl"],
            "segm": ["AP", "AP50", "AP75", "APs", "APm", "APl"],
            "keypoints": ["AP", "AP50", "AP75", "APm", "APl"],
        }[iou_type]

        if coco_eval is None:
            print("No predictions from the model! Set scores to -1")
            return {metric: -1 for metric in metrics}

        # the standard metrics
        results = {
            metric: float(coco_eval.stats[idx] * 100)
            for idx, metric in enumerate(metrics)
        }
        print("Evaluation results for {}: \n".format(iou_type) +
              create_small_table(results))

        if class_names is None or len(class_names) <= 1:
            return results
        # Compute per-category AP
        # from https://github.com/facebookresearch/Detectron/blob/a6a835f5b8208c45d0dce217ce9bbda915f44df7/detectron/datasets/json_dataset_evaluator.py#L222-L252 # noqa
        precisions = coco_eval.eval["precision"]
        # precision has dims (iou, recall, cls, area range, max dets)
        # assert len(class_names) == precisions.shape[2]

        results_per_category = []
        for idx, name in zip(self.id_map, class_names):
            # area range index 0: all area ranges
            # max dets index -1: typically 100 per image
            precision = precisions[:, :, idx, 0, -1]
            precision = precision[precision > -1]
            ap = np.mean(precision) if precision.size else float("nan")
            results_per_category.append(("{}".format(name), float(ap * 100)))

        # tabulate it
        N_COLS = min(6, len(results_per_category) * 2)
        results_flatten = list(itertools.chain(*results_per_category))
        results_2d = itertools.zip_longest(
            *[results_flatten[i::N_COLS] for i in range(N_COLS)])
        table = tabulate(
            results_2d,
            tablefmt="pipe",
            floatfmt=".3f",
            headers=["category", "AP"] * (N_COLS // 2),
            numalign="left",
        )
        print("Per-category {} AP: \n".format(iou_type) + table)

        results.update({"AP-" + name: ap for name, ap in results_per_category})
        return results
예제 #4
0
def coco_to_roidb(annotation_path,
                  save_roidb_path,
                  task='det',
                  data_dir='',
                  need_mask=True):
    assert task in ['det', 'kps']
    coco = COCO(annotation_path)
    image_ids = coco.getImgIds()

    cats = [cat['name'] for cat in coco.loadCats(coco.getCatIds())]
    classes = ['__background__'] + cats
    num_classes = len(classes)
    class_to_ind = dict(zip(classes, xrange(num_classes)))
    class_to_coco_ind = dict(zip(cats, coco.getCatIds()))
    coco_ind_to_class_ind = dict([(class_to_coco_ind[cls], class_to_ind[cls])
                                  for cls in classes[1:]])

    roidb = []
    for i, image_id in enumerate(image_ids):
        if i % 1000 == 0:
            print('{}/{}'.format(i, len(image_ids)))
        im_ann = coco.loadImgs(image_id)[0]
        width = im_ann['width']
        height = im_ann['height']

        annIds = coco.getAnnIds(imgIds=image_id, iscrowd=None)
        objs = coco.loadAnns(annIds)

        # sanitize bboxes
        valid_objs = []
        areas_ = []
        for obj in objs:
            if task == 'kps':
                assert obj['category_id'] == 1
            assert obj['area'] > 0

            x, y, w, h = obj['bbox']
            x1 = np.max((0, x))
            y1 = np.max((0, y))
            x2 = np.min((width - 1, x1 + np.max((0, w - 1))))
            y2 = np.min((height - 1, y1 + np.max((0, h - 1))))
            if obj['area'] > 0 and x2 >= x1 and y2 >= y1:
                obj['clean_bbox'] = [x1, y1, x2, y2]
                valid_objs.append(obj)
                areas_.append(obj['area'])

            # x, y, w, h = obj['bbox']
            # x1 = x
            # y1 = y
            # x2 = x1 + w - 1
            # y2 = y1 + h - 1
            # assert 0 <= x1 < width
            # assert 0 <= y1 < height
            # assert 0 <= x2 < width
            # assert 0 <= y2 < height
            # assert x2 >= x1 and y2 >= y1
            # obj['clean_bbox'] = [x1, y1, x2, y2]
            # valid_objs.append(obj)
            # areas_.append(obj['area'])

        objs = valid_objs
        num_objs = len(objs)

        boxes = np.zeros((num_objs, 4), dtype=np.float32)
        gt_classes = np.zeros((num_objs, ), dtype=np.int32)
        keypoints = np.zeros((num_objs, 51), dtype=np.float32)

        areas = np.array(areas_, dtype=np.float32)

        iscrowd = []
        for ix, obj in enumerate(objs):
            cls = -coco_ind_to_class_ind[obj['category_id']]\
                 if obj['iscrowd'] else coco_ind_to_class_ind[obj['category_id']]
            iscrowd.append(obj['iscrowd'])
            boxes[ix, :] = obj['clean_bbox']
            gt_classes[ix] = cls
            if task == 'kps':
                keypoints[ix, :] = obj['keypoints']

        roi_rec = {
            'image': data_dir + im_ann['file_name'],
            'id': im_ann['id'],
            'height': height,
            'width': width,
            'boxes': boxes,
            'area': areas,
            'iscrowd': np.array(iscrowd, dtype=np.float32),
            'gt_classes': gt_classes
        }
        if task == 'kps':
            roi_rec['keypoints'] = keypoints
        if need_mask:
            roi_rec['gt_masks'] = [x['segmentation'] for x in objs]
        roidb.append(roi_rec)

    with open(save_roidb_path, 'wb') as fid:
        cPickle.dump(roidb, fid, cPickle.HIGHEST_PROTOCOL)
예제 #5
0
from data import VOCroot, COCOroot, VOC_300, VOC_512, COCO_300, COCO_512, COCO_mobile_300, AnnotationTransform, \
    COCODetection, VOCDetection, detection_collate, BaseTransform, preproc

train_sets = [('2014', 'valminusminival')]


# dataset = COCODetection(COCOroot, train_sets, preproc( 300, (104, 117, 123), 0.6))
# epoch_size = len(dataset)
# iiter = data.DataLoader(dataset, 32,shuffle=True, num_workers=2, collate_fn=detection_collate)

dirname = "/media/trans/mnt/data/coco/"
annodir = "annotations"
annofile = "instances_valminusminival2014.json"
_COCO = COCO(os.path.join(dirname, annodir, annofile))

catids = _COCO.getCatIds()
imgids = _COCO.getImgIds()
annids = _COCO.getAnnIds(imgids[0])

cats = _COCO.loadCats(_COCO.getCatIds())
print("# ------------------------------------- # ")
# print(cats)
print(len(cats))
print("# ------------------------------------- # ")
print("catids:", catids)
print("# ------------------------------------- # ")
print("annids: ", annids)
print("# ------------------------------------- # ")
print("imgids: ", imgids[:30])

# ids2 = list()
예제 #6
0
    def __init__(self,
                 root,
                 image_sets,
                 preproc=None,
                 target_transform=None,
                 dataset_name='COCO',
                 classes=None,
                 box_num=1000000000):
        self.root = root
        self.cache_path = os.path.join(self.root, 'cache')
        self.image_set = image_sets
        self.preproc = preproc
        self.target_transform = target_transform
        self.name = dataset_name
        self.classes = classes
        self.ids = list()
        self.annotations = list()
        self.box_num = int(box_num)
        self._view_map = {
            'minival2014': 'val2014',  # 5k val2014 subset
            'valminusminival2014': 'val2014',  # val2014 \setminus minival2014
            'test-dev2015': 'test2015',
        }

        for (year, image_set) in image_sets:
            coco_name = image_set + year
            data_name = (self._view_map[coco_name]
                         if coco_name in self._view_map else coco_name)
            annofile = self._get_ann_file(coco_name)
            _COCO = COCO(annofile)
            self._COCO = _COCO
            self.coco_name = coco_name

            if self.classes == "youtube_bb":
                cats = _COCO.loadCats(
                    _COCO.getCatIds(catNms=classes_youtubebb))
            elif self.classes == "youtube_bb_sub":
                cats = _COCO.loadCats(
                    _COCO.getCatIds(catNms=classes_youtubebb_sub))
            else:
                cats = _COCO.loadCats(_COCO.getCatIds())

            self._classes = tuple(['__background__'] +
                                  [c['name'] for c in cats])
            self._classesids = tuple([0] + [c['id'] for c in cats])
            self.num_classes = len(self._classes)
            self._class_to_ind = dict(
                zip(self._classes, range(self.num_classes)))

            if self.classes == "youtube_bb":
                self._class_to_coco_cat_id = dict(
                    zip([c['name'] for c in cats],
                        _COCO.getCatIds(catNms=classes_youtubebb)))
            elif self.classes == "youtube_bb_sub":
                self._class_to_coco_cat_id = dict(
                    zip([c['name'] for c in cats],
                        _COCO.getCatIds(catNms=classes_youtubebb_sub)))
            else:
                self._class_to_coco_cat_id = dict(
                    zip([c['name'] for c in cats], _COCO.getCatIds()))

            indexes = []
            self.indexes_limit = []

            for cat in cats:
                indexes.extend(_COCO.getImgIds(catIds=cat["id"]))
            indexes = set(indexes)
            indexes = list(indexes)
            random.seed(box_num)
            random.shuffle(indexes)

            if image_set.find('test') != -1:
                print('test set will not load annotations!')
            else:
                self.annotations.extend(
                    self._load_coco_annotations(coco_name, indexes, _COCO,
                                                self.box_num))

            self.image_indexes = self.indexes_limit
            self.ids.extend([
                self.image_path_from_index(data_name, index)
                for index in self.indexes_limit
            ])