Example #1
0
print("Number of images in the validation dataset:\t{:>6}".format(
    val_dataset_size))

# 3: Set the batch size.
batch_size = 32

# 4: Define the image processing chain.
data_augmentation_chain = DataAugmentationConstantInputSize(
    random_brightness=(-48, 48, 0.5),
    random_contrast=(0.5, 1.8, 0.5),
    random_saturation=(0.5, 1.8, 0.5),
    random_hue=(18, 0.5),
    random_flip=0.5,
    random_translate=((0.03, 0.5), (0.03, 0.5), 0.5),
    random_scale=(0.5, 2.0, 0.5),
    n_trials_max=3,
    # 这里 clip 的是 gt boxes
    clip_boxes=True,
    overlap_criterion_box_filter='area',
    overlap_criterion_validator='area',
    bounds_box_filter=(0.3, 1.0),
    bounds_validator=(0.5, 1.0),
    n_boxes_min=1,
    background=(0, 0, 0))

# 5: Instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

# The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
# [(img_height // 8, img_width // 8), (img_height // 16, img_width // 16), (img_height // 32, img_width // 32)
#  (img_height // 64, img_width // 64)]
predictor_sizes = [
def main():
    create_new_model = True if args.model_name == 'default' else False

    if create_new_model:
        K.clear_session()  # Clear previous models from memory.
        model = build_model(image_size=(Config.img_height, Config.img_width,
                                        Config.img_channels),
                            n_classes=Config.n_classes,
                            mode='training',
                            l2_regularization=Config.l2_regularization,
                            scales=Config.scales,
                            aspect_ratios_global=Config.aspect_ratios,
                            aspect_ratios_per_layer=None,
                            two_boxes_for_ar1=Config.two_boxes_for_ar1,
                            steps=Config.steps,
                            offsets=Config.offsets,
                            clip_boxes=Config.clip_boxes,
                            variances=Config.variances,
                            normalize_coords=Config.normalize_coords,
                            subtract_mean=Config.intensity_mean,
                            divide_by_stddev=Config.intensity_range)

        # model.load_weights("./weights/"+ args.model_name + ".h5", by_name=True)
        adam = Adam(lr=args.learning_rate,
                    beta_1=0.9,
                    beta_2=0.999,
                    epsilon=1e-08,
                    decay=0.0)
        ssd_loss = SSDLoss(neg_pos_ratio=3, alpha=1.0)
        model.compile(optimizer=adam, loss=ssd_loss.compute_loss)
    else:

        model_path = "weights/" + args.model_name + ".h5"
        # We need to create an SSDLoss object in order to pass that to the model loader.
        ssd_loss = SSDLoss(neg_pos_ratio=3, alpha=1.0)
        K.clear_session()  # Clear previous models from memory.
        model = load_model(model_path,
                           custom_objects={
                               'AnchorBoxes': AnchorBoxes,
                               'compute_loss': ssd_loss.compute_loss
                           })

    # Load the data
    train_dataset = DataGenerator(load_images_into_memory=True,
                                  hdf5_dataset_path=os.getcwd() + "/data/" +
                                  args.dataset + '/polyp_train.h5')
    val_dataset = DataGenerator(load_images_into_memory=True,
                                hdf5_dataset_path=os.getcwd() + "/data/" +
                                args.dataset + '/polyp_val.h5')
    train_dataset_size = train_dataset.get_dataset_size()
    val_dataset_size = val_dataset.get_dataset_size()
    print("Number of images in the training dataset:\t{:>6}".format(
        train_dataset_size))
    print("Number of images in the validation dataset:\t{:>6}".format(
        val_dataset_size))

    batch_size = args.batch_size

    # 4: Define the image processing chain.
    data_augmentation_chain = DataAugmentationConstantInputSize(
        random_brightness=(-48, 48, 0.5),
        random_contrast=(0.5, 1.8, 0.5),
        random_saturation=(0.5, 1.8, 0.5),
        random_hue=(18, 0.5),
        random_flip=0.5,
        random_translate=((0.03, 0.5), (0.03, 0.5), 0.5),
        random_scale=(0.5, 2.0, 0.5),
        n_trials_max=3,
        clip_boxes=True,
        overlap_criterion='area',
        bounds_box_filter=(0.3, 1.0),
        bounds_validator=(0.5, 1.0),
        n_boxes_min=1,
        background=(0, 0, 0))

    # 5: Instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.
    # The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
    predictor_sizes = [
        model.get_layer('classes4').output_shape[1:3],
        model.get_layer('classes5').output_shape[1:3],
        model.get_layer('classes6').output_shape[1:3],
        model.get_layer('classes7').output_shape[1:3]
    ]

    ssd_input_encoder = SSDInputEncoder(
        img_height=Config.img_height,
        img_width=Config.img_width,
        n_classes=Config.n_classes,
        predictor_sizes=predictor_sizes,
        scales=Config.scales,
        aspect_ratios_global=Config.aspect_ratios,
        two_boxes_for_ar1=Config.two_boxes_for_ar1,
        steps=Config.steps,
        offsets=Config.offsets,
        clip_boxes=Config.clip_boxes,
        variances=Config.variances,
        matching_type='multi',
        pos_iou_threshold=0.5,
        neg_iou_limit=0.3,
        normalize_coords=Config.normalize_coords)

    # 6: Create the generator handles that will be passed to Keras' `fit_generator()` function.
    train_generator = train_dataset.generate(
        batch_size=batch_size,
        shuffle=True,
        transformations=[data_augmentation_chain],
        label_encoder=ssd_input_encoder,
        returns={'processed_images', 'encoded_labels'},
        keep_images_without_gt=False)

    val_generator = val_dataset.generate(
        batch_size=batch_size,
        shuffle=False,
        transformations=[],
        label_encoder=ssd_input_encoder,
        returns={'processed_images', 'encoded_labels'},
        keep_images_without_gt=False)
    model_checkpoint = ModelCheckpoint(
        filepath=os.getcwd() +
        '/weights/ssd7_epoch-{epoch:02d}_loss-{loss:.4f}_val_loss-{val_loss:.4f}.h5',
        monitor='val_loss',
        verbose=1,
        save_best_only=True,
        save_weights_only=False,
        mode='auto',
        period=1)

    csv_logger = CSVLogger(filename='ssd7_training_log.csv',
                           separator=',',
                           append=True)
    early_stopping = EarlyStopping(monitor='val_loss',
                                   min_delta=0.0,
                                   patience=10,
                                   verbose=1)
    reduce_learning_rate = ReduceLROnPlateau(monitor='val_loss',
                                             factor=0.2,
                                             patience=8,
                                             verbose=1,
                                             epsilon=0.001,
                                             cooldown=0,
                                             min_lr=0.00001)

    tf_log = keras.callbacks.TensorBoard(log_dir=TF_LOG_PATH + args.tf_logs,
                                         histogram_freq=0,
                                         batch_size=batch_size,
                                         write_graph=True,
                                         write_grads=False,
                                         write_images=False)

    callbacks = [model_checkpoint, csv_logger, reduce_learning_rate, tf_log]

    # If you're resuming a previous training, set `initial_epoch` and `final_epoch` accordingly.
    initial_epoch = 0
    final_epoch = args.final_epoch
    steps_per_epoch = 1000

    # Train/Fit the model
    if args.predict_mode == 'train':
        history = model.fit_generator(generator=train_generator,
                                      steps_per_epoch=steps_per_epoch,
                                      epochs=final_epoch,
                                      callbacks=callbacks,
                                      validation_data=val_generator,
                                      validation_steps=ceil(val_dataset_size /
                                                            batch_size),
                                      initial_epoch=initial_epoch)

    # Prediction Output
    predict_generator = val_dataset.generate(
        batch_size=1,
        shuffle=False,
        transformations=[],
        label_encoder=ssd_input_encoder,
        returns={'processed_images', 'processed_labels', 'filenames'},
        keep_images_without_gt=False)

    i = 0
    for val in range(val_dataset_size):
        batch_images, batch_labels, batch_filenames = next(predict_generator)
        y_pred = model.predict(batch_images)

        y_pred_decoded = decode_detections(
            y_pred,
            confidence_thresh=0.5,
            iou_threshold=0.5,
            top_k=200,
            normalize_coords=Config.normalize_coords,
            img_height=Config.img_height,
            img_width=Config.img_width)

        np.set_printoptions(precision=2, suppress=True, linewidth=90)
        print("Predicted boxes:\n")
        print('   class   conf xmin   ymin   xmax   ymax')
        print(y_pred_decoded[i])

        plt.figure(figsize=(20, 12))
        plt.imshow(batch_images[i])

        current_axis = plt.gca()

        colors = plt.cm.hsv(
            np.linspace(0, 1, Config.n_classes +
                        1)).tolist()  # Set the colors for the bounding boxes
        classes = [
            'background', 'polyps'
        ]  # Just so we can print class names onto the image instead of IDs

        # Draw the ground truth boxes in green (omit the label for more clarity)
        for box in batch_labels[i]:
            xmin = box[1]
            ymin = box[2]
            xmax = box[3]
            ymax = box[4]
            label = '{}'.format(classes[int(box[0])])
            current_axis.add_patch(
                plt.Rectangle((xmin, ymin),
                              xmax - xmin,
                              ymax - ymin,
                              color='green',
                              fill=False,
                              linewidth=2))
            current_axis.text(xmin,
                              ymin,
                              label,
                              size='x-large',
                              color='white',
                              bbox={
                                  'facecolor': 'green',
                                  'alpha': 1.0
                              })

        # Draw the predicted boxes in blue
        for box in y_pred_decoded[i]:
            xmin = box[-4]
            ymin = box[-3]
            xmax = box[-2]
            ymax = box[-1]
            color = colors[int(box[0])]
            label = '{}: {:.2f}'.format(classes[int(box[0])], box[1])
            current_axis.add_patch(
                plt.Rectangle((xmin, ymin),
                              xmax - xmin,
                              ymax - ymin,
                              color=color,
                              fill=False,
                              linewidth=2))
            current_axis.text(xmin,
                              ymin,
                              label,
                              size='x-large',
                              color='white',
                              bbox={
                                  'facecolor': color,
                                  'alpha': 1.0
                              })

        image = plt.gcf()
        # plt.show()
        plt.draw()
        image.savefig(os.getcwd() + "/val_predictions/val_" + str(val) +
                      ".png",
                      dpi=100)
Example #3
0
    def set_generator(self,
                      train_images_dir,
                      train_annotation_path,
                      batch_size,
                      val_images_dir=None,
                      val_annotation_path=None):
        train_dataset = DataGenerator(load_images_into_memory=True,
                                      hdf5_dataset_path=None)
        train_dataset.parse_json(images_dirs=[train_images_dir],
                                 annotations_filenames=[train_annotation_path],
                                 ground_truth_available=True,
                                 include_classes='all',
                                 ret=False,
                                 verbose=True)
        train_dataset_size = train_dataset.get_dataset_size()
        if self.model_name == 'ssd_7':
            # Define the image processing chain.
            ssd_data_augmentation = DataAugmentationConstantInputSize(
                random_brightness=(-48, 48, 0.5),
                random_contrast=(0.5, 1.8, 0.5),
                random_saturation=(0.5, 1.8, 0.5),
                random_hue=(18, 0.5),
                random_flip=0.5,
                random_translate=((0.03, 0.5), (0.03, 0.5), 0.5),
                random_scale=(0.5, 2.0, 0.5),
                n_trials_max=3,
                clip_boxes=True,
                overlap_criterion='area',
                bounds_box_filter=(0.3, 1.0),
                bounds_validator=(0.5, 1.0),
                n_boxes_min=1,
                background=(0, 0, 0))

            # Instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

            # The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
            predictor_sizes = [
                self.model.get_layer('classes4').output_shape[1:3],
                self.model.get_layer('classes5').output_shape[1:3],
                self.model.get_layer('classes6').output_shape[1:3],
                self.model.get_layer('classes7').output_shape[1:3]
            ]

        elif self.model_name == 'ssd_300':
            # For the training generator:
            ssd_data_augmentation = SSDDataAugmentation(
                img_height=self.image_size[0],
                img_width=self.image_size[1],
                background=self.mean_color)

            # 5: Instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

            # The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
            predictor_sizes = [
                self.model.get_layer(
                    'conv4_3_norm_mbox_conf').output_shape[1:3],
                self.model.get_layer('fc7_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv6_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv7_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv8_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv9_2_mbox_conf').output_shape[1:3]
            ]
        elif self.model_name == 'ssd_512':
            # For the training generator:
            ssd_data_augmentation = SSDDataAugmentation(
                img_height=self.image_size[0],
                img_width=self.image_size[1],
                background=self.mean_color)
            # 5: Instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

            # The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
            predictor_sizes = [
                self.model.get_layer(
                    'conv4_3_norm_mbox_conf').output_shape[1:3],
                self.model.get_layer('fc7_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv6_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv7_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv8_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv9_2_mbox_conf').output_shape[1:3],
                self.model.get_layer('conv10_2_mbox_conf').output_shape[1:3]
            ]

        ssd_input_encoder = SSDInputEncoder(
            img_height=self.image_size[0],
            img_width=self.image_size[1],
            n_classes=self.n_classes,
            predictor_sizes=predictor_sizes,
            scales=self.scales,
            aspect_ratios_per_layer=self.aspect_ratios_per_layer,
            two_boxes_for_ar1=self.two_boxes_for_ar1,
            steps=self.steps,
            offsets=self.offsets,
            clip_boxes=self.clip_boxes,
            variances=self.variances,
            matching_type='multi',
            pos_iou_threshold=0.5,
            neg_iou_limit=0.5,
            normalize_coords=self.normalize_coords)

        self.generator = train_dataset.generate(
            batch_size=batch_size,
            shuffle=True,
            transformations=[ssd_data_augmentation],
            label_encoder=ssd_input_encoder,
            returns={'processed_images', 'encoded_labels'},
            keep_images_without_gt=False)
        self.steps_per_epoch = ceil(train_dataset_size / batch_size)

        if val_images_dir is not None and val_annotation_path is not None:
            val_dataset = DataGenerator(load_images_into_memory=True,
                                        hdf5_dataset_path=None)
            val_dataset.parse_json(images_dirs=[val_images_dir],
                                   annotations_filenames=[val_annotation_path],
                                   ground_truth_available=True,
                                   include_classes='all',
                                   ret=False,
                                   verbose=True)
            val_dataset_size = val_dataset.get_dataset_size()

            if self.model_name == 'ssd_300' or self.model_name == 'ssd_512':
                # For the validation generator:
                convert_to_3_channels = ConvertTo3Channels()
                resize = Resize(height=self.image_size[0],
                                width=self.image_size[1])
                transformations = [convert_to_3_channels, resize]
            else:
                transformations = []

            self.validation_data = val_dataset.generate(
                batch_size=batch_size,
                shuffle=False,
                transformations=transformations,
                label_encoder=ssd_input_encoder,
                returns={'processed_images', 'encoded_labels'},
                keep_images_without_gt=False)
            self.validation_steps = ceil(val_dataset_size / batch_size)

        else:
            self.validation_data = None
            self.validation_steps = None
print("Number of images in the test dataset:\t{:>6}".format(test_dataset_size))

###### 5.2. Image processing chain

# Define the image processing chain.
train_data_augmentation_chain = DataAugmentationConstantInputSize(
    random_brightness=(-48, 48, 0.5),
    random_contrast=(0.5, 1.8, 0.5),
    random_saturation=(0.5, 1.8, 0.5),
    random_hue=(18, 0.5),
    random_flip=0.5,
    random_gaussian_noise=(0.5, 0., 10),  # gaussine noise
    random_poisson_noise=(0.5, 20),  # poisson noise
    random_salt_pepper_noise=(0.5, 0.5,
                              0.005),  # salt&pepper or impalse noise 
    random_row_defect=(0.5, 1),  # row defect
    random_col_defect=(0.5, 1),  # col defect
    random_translate=((0.03, 0.5), (0.03, 0.5), 0.5),
    random_scale=(0.5, 2.0, 0.5),
    n_trials_max=3,
    clip_boxes=True,
    overlap_criterion='area',
    bounds_box_filter=(0.3, 1.0),
    bounds_validator=(0.5, 1.0),
    n_boxes_min=1,
    background=(127, 127, 127))

# convert the images into the 3d arrays: (width, height, 1)
from data_generator.object_detection_2d_photometric_ops import ConvertTo1Channel
convertor = ConvertTo1Channel()
Example #5
0
    def create_generator(self, model, train_dataset, val_dataset):
        # 数据扩充链
        data_augmentation_chain = DataAugmentationConstantInputSize(
            random_brightness=(-48, 48, 0.5),
            random_contrast=(0.5, 1.8, 0.5),
            random_saturation=(0.5, 1.8, 0.5),
            random_hue=(18, 0.5),
            random_flip=0.5,
            random_translate=((0.03, 0.5), (0.03, 0.5), 0.5),
            random_scale=(0.5, 2.0, 0.5),
            n_trials_max=3,
            clip_boxes=True,
            overlap_criterion='area',
            bounds_box_filter=(0.3, 1.0),
            bounds_validator=(0.5, 1.0),
            n_boxes_min=1,
            background=(0, 0, 0))

        # 5: Instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

        # The encoder constructor needs the spatial dimensions of the model's
        # predictor layers to create the anchor boxes.
        predictor_sizes = [
            model.get_layer('classes4').output_shape[1:3],
            model.get_layer('classes5').output_shape[1:3],
            model.get_layer('classes6').output_shape[1:3],
            model.get_layer('classes7').output_shape[1:3]
        ]

        ssd_input_encoder = SSDInputEncoder(
            img_height=self.img_height,
            img_width=self.img_width,
            n_classes=self.n_classes,
            predictor_sizes=predictor_sizes,
            scales=self.scales,
            aspect_ratios_global=self.aspect_ratios,
            variances=self.variances,
            matching_type='multi',
            pos_iou_threshold=0.5,
            neg_iou_limit=0.3,
            normalize_coords=self.normalize_coords)

        # 6: Create the generator handles that will be passed to Keras' `fit_generator()` function.

        train_generator = train_dataset.generate(
            batch_size=self.batch_size,
            shuffle=True,
            transformations=[data_augmentation_chain],
            label_encoder=ssd_input_encoder,
            returns={'processed_images', 'encoded_labels'},
            keep_images_without_gt=False)

        val_generator = val_dataset.generate(
            batch_size=self.batch_size,
            shuffle=False,
            transformations=[],
            label_encoder=ssd_input_encoder,
            returns={'processed_images', 'encoded_labels'},
            keep_images_without_gt=False)

        return train_generator, val_generator