def test_compute_gt(self): level = 3 ds = voc.build_dataset('test/data/VOC2007', im_input_size=(512, 512)) anchors = self.generate_anchors(config.AnchorsConfig(), 512) im, (l, bbs) = next(iter(ds.take(1))) gt_reg, gt_labels = utils.anchors.anchor_targets_bbox( anchors, tf.expand_dims(im, 0), tf.expand_dims(bbs, 0), tf.expand_dims(l, 0), len(voc.IDX_2_LABEL)) nearest_anchors = anchors[gt_reg[0, :, -1] == 1].numpy() im_random = unnormalize_image(im) im_random = visualizer.draw_boxes(im_random, nearest_anchors) im_random = visualizer.draw_boxes(im_random, bbs, colors=[0, 0, 255]) for label in l: print(voc.IDX_2_LABEL[int(label)]) plt.imshow(im_random) plt.show(block=True) print('GT shapes:', gt_labels.shape, gt_reg.shape) print('Found any overlapping anchor?', np.any(gt_labels[:, :, -1] == 1.))
def test_regress_boxes(self): print('Regress anchors test') ds = voc.build_dataset('test/data/VOC2007', im_input_size=(512, 512)) anchors = self.generate_anchors(config.AnchorsConfig(), 512) im, (l, bbs) = next(iter(ds.take(1))) gt_reg, gt_labels = utils.anchors.anchor_targets_bbox( anchors, tf.expand_dims(im, 0), tf.expand_dims(bbs, 0), tf.expand_dims(l, 0), len(voc.IDX_2_LABEL)) near_mask = gt_reg[0, :, -1] == 1 nearest_regressors = tf.expand_dims( tf.boolean_mask(gt_reg[0], near_mask)[:, :-1], 0) nearest_anchors = tf.expand_dims(anchors[near_mask], 0) # apply regression to boxes regressed_boxes = utils.bndbox.regress_bndboxes( nearest_anchors, nearest_regressors) im_random = unnormalize_image(im) im_random = visualizer.draw_boxes(im_random, regressed_boxes[0]) plt.imshow(im_random) plt.show(block=True)
def test_regress_boxes(self): print('Regress anchors test') level = 3 ds = voc.build_dataset('test/data/VOC2007', im_input_size=(512, 512)) anchors = self.generate_anchors(config.AnchorsConfig(), 512) for im, (l, bbs) in ds.take(1): gt_reg, gt_labels = \ utils.anchors.anchor_targets_bbox(anchors.numpy(), im.numpy(), bbs.numpy(), l.numpy(), len(voc.IDX_2_LABEL)) near_mask = gt_reg[0, :, -1] == 1 nearest_regressors = tf.expand_dims(gt_reg[0, near_mask][:, :-1], 0) nearest_anchors = tf.expand_dims(anchors[near_mask], 0) # apply regression to boxes regressed_boxes = utils.bndbox.regress_bndboxes(nearest_anchors, nearest_regressors) im_random = im[0].numpy() for box in regressed_boxes[0].numpy(): box = box.astype('int32') cv2.rectangle(im_random, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 1) cv2.imshow('', im_random) cv2.waitKey()
def __init__(self, num_classes: int, D: int = 0, bidirectional: bool = True, freeze_backbone: bool = False, score_threshold: float = .1, weights: str = 'imagenet'): super(EfficientDet, self).__init__() self.config = config.EfficientDetCompudScaling(D=D) self.anchors_config = config.AnchorsConfig() self.num_classes = num_classes self.score_threshold = score_threshold self.backbone = (models.build_efficient_net_backbone( self.config.B, weights)) self.backbone.trainable = not freeze_backbone if bidirectional: self.neck = models.BiFPN(self.config.Wbifpn, self.config.Dbifpn) else: self.neck = models.FPN(self.config.Wbifpn) self.class_head = models.RetinaNetClassifier(self.config.Wbifpn, self.config.Dclass, num_classes) self.bb_head = models.RetinaNetBBPredictor(self.config.Wbifpn, self.config.Dclass) self.anchors_gen = [ utils.anchors.AnchorGenerator( size=self.anchors_config.sizes[i - 3], aspect_ratios=self.anchors_config.ratios, stride=self.anchors_config.strides[i - 3]) for i in range(3, 8) ] # 3 to 7 pyramid levels
def test_compute_gt(self): level = 3 ds = voc.build_dataset('test/data/VOC2007', im_input_size=(512, 512)) anchors = self.generate_anchors(config.AnchorsConfig(), 512) for im, (l, bbs) in ds.take(1): gt_reg, gt_labels = utils.anchors.anchor_targets_bbox( anchors, im, bbs, l, len(voc.IDX_2_LABEL)) nearest_anchors = anchors[gt_reg[0, :, -1] == 1].numpy() im_random = im[0].numpy() for box in nearest_anchors: box = box.astype('int32') cv2.rectangle(im_random, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 1) for box in bbs.numpy()[0]: box = box.astype('int32') cv2.rectangle(im_random, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 3) for label in l[0]: print(voc.IDX_2_LABEL[int(label)]) plt.imshow(im_random) plt.show(block=True) print('GT shapes:', gt_labels.shape, gt_reg.shape) print('Found any overlapping anchor?', np.any(gt_labels[:, :, -1] == 1.))
def test_compute_gt(self): ds = voc.build_dataset('test/data/VOC2007', im_input_size=(512, 512), shuffle=False) ds = ds.skip(1).batch(1) wrapped_ds = utils.training.wrap_detection_dataset(ds, (512, 512), 20) anchors = self.generate_anchors(config.AnchorsConfig(), 512) im, (regressors, l) = next(iter(wrapped_ds.take(1))) im = unnormalize_image(im[0]) near_mask = regressors[0, :, -1] == 1 nearest_regressors = tf.expand_dims( tf.boolean_mask(regressors[0], near_mask)[:, :-1], 0) nearest_anchors = tf.expand_dims(anchors[near_mask], 0) # apply regression to boxes regressed_boxes = utils.bndbox.regress_bndboxes( nearest_anchors, nearest_regressors) im = utils.visualizer.draw_boxes(im, nearest_anchors[0], colors=[(255, 255, 0)]) im = utils.visualizer.draw_boxes(im, regressed_boxes[0], colors=[(0, 255, 255)]) plt.imshow(im) plt.axis('off') plt.show(block=True) print('GT shapes:', l.shape, regressors.shape) print('Found any overlapping anchor?', tf.reduce_any(tf.equal(l[:, :, -1], 1.)))
def test_compute_gt(self): classes = ['treecko', 'psyduck', 'greninja', 'solgaleo', 'mewtwo'] class2idx = {c: i for i, c in enumerate(classes)} ds = labelme.build_dataset('test/data/pokemon', 'test/data/pokemon', class2idx=class2idx, im_input_size=(512, 512)) anchors = self.generate_anchors(config.AnchorsConfig(), 512) im, (l, bbs) = next(iter(ds.take(1))) im = unnormalize_image(im) gt_reg, gt_labels = utils.anchors.anchor_targets_bbox( anchors, tf.expand_dims(im, 0), tf.expand_dims(bbs, 0), tf.expand_dims(l, 0), len(classes)) nearest_anchors = anchors[gt_reg[0, :, -1] == 1] im = utils.visualizer.draw_boxes(im, nearest_anchors) im = utils.visualizer.draw_boxes(im, bbs, colors=[(255, 0, 0)]) plt.imshow(im) plt.axis('off') plt.show(block=True) print('GT shapes:', gt_labels.shape, gt_reg.shape) print('Found any overlapping anchor?', np.any(gt_labels[:, :, -1] == 1.))
def test_nms(self): anchors_config = config.AnchorsConfig() classes, class2idx = utils.io.read_class_names( 'test/data/pokemon/classes.names') n_classes = len(classes) ds = labelme.build_dataset('test/data/pokemon', 'test/data/pokemon', class2idx=class2idx, im_input_size=(512, 512)) anchors_gen = [ utils.anchors.AnchorGenerator(size=anchors_config.sizes[i - 3], aspect_ratios=anchors_config.ratios, stride=anchors_config.strides[i - 3]) for i in range(3, 8) ] sizes = (80, 40, 20, 10, 5) im, (l, bbs) = next(iter(ds.take(1))) anchors = [ anchor_gen((size, size, 3)) for anchor_gen, size in zip(anchors_gen, sizes) ] anchors = tf.concat(anchors, axis=0) gt_reg, gt_labels = utils.anchors.anchor_targets_bbox( anchors, tf.expand_dims(im, 0), tf.expand_dims(bbs, 0), tf.expand_dims(l, 0), n_classes) box_score = gt_labels[0] true_idx = tf.reshape(tf.where(box_score[:, -1] == 1), [-1]) box_score = tf.gather(box_score, true_idx) anchors = tf.gather(anchors, true_idx) before_nms_shape = anchors.shape anchors = tf.expand_dims(anchors, 0) box_score = tf.expand_dims(box_score[:, :-1], 0) boxes, labels, scores = bb_utils.nms(anchors, box_score) after_nms_shape = boxes[0].shape if anchors.shape[0] != 0: self.assertTrue(after_nms_shape[0] < before_nms_shape[0], 'After nms boxes should be reduced') else: print('No ground truth anchors') im_random = utils.visualizer.draw_boxes(im, boxes[0]) plt.imshow(im_random) plt.axis('off') plt.show(block=True)
def test_tile_anchors(self): level = 3 feature_size = 512 im_random = np.zeros((512, 512, 3)) boxes = self.generate_anchors(config.AnchorsConfig(), im_random.shape[0]) im_random = visualizer.draw_boxes(im_random, boxes) plt.imshow(im_random) plt.show(block=True)
def test_tile_anchors(self): level = 3 feature_size = 512 im_random = np.zeros((512, 512, 3)) boxes = self.generate_anchors(config.AnchorsConfig(), im_random.shape[0]) for box in boxes.numpy(): box = box.astype('int32') cv2.rectangle(im_random, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 1) plt.imshow(im_random) plt.show(block=True)
def test_compute_gt(self): classes = ['treecko', 'psyduck', 'greninja', 'solgaleo', 'mewtwo'] class2idx = {c: i for i, c in enumerate(classes)} ds = labelme.build_dataset('test/data/pokemon', 'test/data/pokemon', class2idx=class2idx, im_input_size=(512, 512)) anchors = self.generate_anchors(config.AnchorsConfig(), 512) for im, (l, bbs) in ds.take(1): gt_reg, gt_labels = \ utils.anchors.anchor_targets_bbox(anchors.numpy(), im.numpy(), bbs.numpy(), l.numpy(), len(classes)) nearest_anchors = anchors[gt_reg[0, :, -1] == 1].numpy() im_random = im[0].numpy()[..., ::-1].copy() for box in nearest_anchors: box = box.astype('int32') cv2.rectangle(im_random, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 1) for box in bbs.numpy()[0]: box = box.astype('int32') cv2.rectangle(im_random, (box[0], box[1]), (box[2], box[3]), (0, 0, 255), 1) for label in l[0]: print(classes[int(label)]) cv2.imshow('', im_random) cv2.waitKey() print('GT shapes:', gt_labels.shape, gt_reg.shape) print('Found any overlapping anchor?', np.any(gt_labels[:, :, -1] == 1.))
import numpy as np import tensorflow as tf import matplotlib.pyplot as plt import efficientdet.data.voc as voc import efficientdet.config as config from efficientdet import utils, visualizer from efficientdet.data.preprocess import unnormalize_image def _get_res_at_level_i(res, i): return int(res / (2**i)) anchors_config = config.AnchorsConfig() class AnchorsTest(unittest.TestCase): def generate_anchors(self, anchors_config: config.AnchorsConfig, im_shape: int) -> tf.Tensor: anchors_gen = [ utils.anchors.AnchorGenerator(size=anchors_config.sizes[i - 3], aspect_ratios=anchors_config.ratios, stride=anchors_config.strides[i - 3]) for i in range(3, 8) ] shapes = [im_shape // (2**x) for x in range(3, 8)]
def __init__(self, num_classes: Optional[int] = None, D : int = 0, bidirectional: bool = True, freeze_backbone: bool = False, score_threshold: float = .1, weights : Optional[str] = 'imagenet', custom_head_classifier: bool = False, training_mode: bool = False) -> None: super(EfficientDet, self).__init__() # Check arguments coherency if custom_head_classifier is True and num_classes is None: raise ValueError('If include_top is False, you must specify ' 'the num_classes') if weights not in _AVAILABLE_WEIGHTS: raise ValueError(f'Weights {weights} not available.\n' f'The available weights are ' f'{list(_AVAILABLE_WEIGHTS)}') if ((weights is 'imagenet' or weights is None) and custom_head_classifier): raise ValueError('Custom Head does not make sense when ' 'training the model from scratch. ' 'Set custom_head_classifier to False or specify ' 'other weights.') # If weights related to efficientdet are set, # update the model hyperparameters according to the checkpoint, # but printing a warning if weights != 'imagenet' and weights is not None: from efficientdet.utils.checkpoint import download_folder checkpoint_path = _WEIGHTS_PATHS[weights] save_dir = Path(download_folder(checkpoint_path)) params = json.load((save_dir / 'hp.json').open()) # If num_classes is specified it must be the same as in the # weights checkpoint except if the custom head classifier is set # to true if (num_classes is not None and not custom_head_classifier and num_classes != params['n_classes']): raise ValueError(f'Weights {weights} num classes are different' 'from num_classes argument, please leave it ' ' as None or specify the correct classes') bidirectional = params['bidirectional'] D = params['efficientdet'] # Declare the model architecture self.config = config.EfficientDetCompudScaling(D=D) # Setup efficientnet backbone backbone_weights = 'imagenet' if weights == 'imagenet' else None self.backbone = (models .build_efficient_net_backbone( self.config.B, backbone_weights)) for l in self.backbone.layers: l.trainable = not freeze_backbone self.backbone.trainable = not freeze_backbone # Setup the feature extractor neck if bidirectional: self.neck = models.BiFPN(self.config.Wbifpn, self.config.Dbifpn, prefix='bifpn/') else: self.neck = models.FPN(self.config.Wbifpn) # Setup the heads if num_classes is None: raise ValueError('You have to specify the number of classes.') self.num_classes = num_classes self.class_head = models.RetinaNetClassifier( self.config.Wbifpn, self.config.Dclass, num_classes=self.num_classes, prefix='class_head/') self.bb_head = models.RetinaNetBBPredictor(self.config.Wbifpn, self.config.Dclass, prefix='regress_head/') self.training_mode = training_mode # Inference variables, won't be used during training self.filter_detections = models.layers.FilterDetections( config.AnchorsConfig(), score_threshold) # Load the weights if needed if weights is not None and weights != 'imagenet': tmp = training_mode self.training_mode = True self.build([None, *self.config.input_size, 3]) self.load_weights(str(save_dir / 'model.h5'), by_name=True, skip_mismatch=custom_head_classifier) self.training_mode = tmp self.training_mode = tmp # Append a custom classifier if custom_head_classifier: self.class_head = models.RetinaNetClassifier( self.config.Wbifpn, self.config.Dclass, num_classes=num_classes, prefix='class_head/')