def __init__(self, backend, input_size, labels, max_box_per_image, anchors, gray_mode = False): self.input_size = input_size self.gray_mode = gray_mode self.labels = list(labels) self.nb_class = len(self.labels) self.nb_box = len(anchors)//2 self.class_wt = np.ones(self.nb_class, dtype='float32') self.anchors = anchors self.max_box_per_image = max_box_per_image ########################## # Make the model ########################## # make the feature extractor layers if self.gray_mode: self.input_size = (self.input_size[0], self.input_size[1], 1) input_image = Input(shape=self.input_size) else: self.input_size = (self.input_size[0], self.input_size[1], 3) input_image = Input(shape=self.input_size) self.true_boxes = Input(shape=(1, 1, 1, max_box_per_image , 4), name="GT_boxes") self.feature_extractor = import_feature_extractor(backend, self.input_size) print(self.feature_extractor.get_output_shape()) self.grid_h, self.grid_w = self.feature_extractor.get_output_shape() features = self.feature_extractor.extract(input_image) # make the object detection layer output = Conv2D(self.nb_box * (4 + 1 + self.nb_class), (1,1), strides=(1,1), padding='same', name='DetectionLayer', kernel_initializer='he_normal')(features) output = Reshape((self.grid_h, self.grid_w, self.nb_box, 4 + 1 + self.nb_class), name="YOLO_output")(output) output = Lambda(lambda args: args[0], name="Insert_GT_Boxes")([output, self.true_boxes]) self.model = Model([input_image, self.true_boxes], output) self.model.summary()
def main(argv): config_path = args.conf num_anchors = args.anchors with open(config_path) as config_buffer: config = json.loads(config_buffer.read()) if config['parser_annotation_type'] == 'xml': # parse annotations of the training set train_imgs, train_labels = parse_annotation_xml( config['train']['train_annot_folder'], config['train']['train_image_folder'], config['model']['labels']) elif config['parser_annotation_type'] == 'csv': # parse annotations of the training set train_imgs, train_labels = parse_annotation_csv( config['train']['train_csv_file'], config['model']['labels'], config['train']['train_csv_base_path']) input_size = (config['model']['input_size_h'], config['model']['input_size_w'], 3) feature_extractor = import_feature_extractor(config['model']['backend'], input_size) grid_w = config['model'][ 'input_size_w'] / feature_extractor.get_output_shape()[1] grid_h = config['model'][ 'input_size_h'] / feature_extractor.get_output_shape()[0] # run k_mean to find the anchors annotation_dims = [] for image in train_imgs: cell_w = image['width'] / grid_w cell_h = image['height'] / grid_h for obj in image['object']: relative_w = (float(obj['xmax']) - float(obj['xmin'])) / cell_w relative_h = (float(obj["ymax"]) - float(obj['ymin'])) / cell_h annotation_dims.append(tuple(map(float, (relative_w, relative_h)))) annotation_dims = np.array(annotation_dims) centroids = run_kmeans(annotation_dims, num_anchors) # write anchors to file print('\naverage IOU for', num_anchors, 'anchors:', '%0.2f' % avg_IOU(annotation_dims, centroids)) print_anchors(centroids)
def _main_(args): config_path = args.conf with open(config_path) as config_buffer: config = json.loads(config_buffer.read()) if config['backup']['create_backup']: config = create_backup(config) keras.backend.tensorflow_backend.set_session(get_session()) #path for the training and validation dataset datasetTrainPath = os.path.join(args.folder, "train") datasetValPath = os.path.join(args.folder, "val") for folder in [datasetTrainPath, datasetValPath]: if not os.path.isdir(folder): raise Exception("{} doesn't exist!".format(folder)) classesTrain = next(os.walk(datasetTrainPath))[1] classesVal = next(os.walk(datasetValPath))[1] if not classesVal == classesTrain: raise Exception( "The training and validation classes must be the same!") else: folders = classesTrain #training configuration epochs = config['train']['nb_epochs'] batchSize = config['train']['batch_size'] width = config['model']['input_size_w'] height = config['model']['input_size_h'] depth = 3 if config['model']['gray_mode'] == False else 1 #config keras generators if len( folders ) == 2: #if just have 2 classes, the model will have a binary output classes = 1 else: classes = len(folders) #count all samples imagesTrainPaths = [] imagesValPaths = [] for folder in folders: imagesTrainPaths += list( list_images(os.path.join(datasetTrainPath, folder))) imagesValPaths += list( list_images(os.path.join(datasetValPath, folder))) generator_config = { 'IMAGE_H': height, 'IMAGE_W': width, 'IMAGE_C': depth, 'BATCH_SIZE': batchSize } #callbacks model_name = config['train']['saved_weights_name'] checkPointSaverBest = ModelCheckpoint(model_name, monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1) ckp_model_name = os.path.splitext(model_name)[1] + "_ckp.h5" checkPointSaver = ModelCheckpoint(ckp_model_name, verbose=1, save_best_only=False, save_weights_only=False, period=10) tb = TensorBoard(log_dir=config['train']['tensorboard_log_dir'], histogram_freq=0, batch_size=batchSize, write_graph=True, write_grads=False, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None) #create the classification model # make the feature extractor layers if depth == 1: input_size = (height, width, 1) input_image = Input(shape=input_size) else: input_size = (height, width, 3) input_image = Input(shape=input_size) feature_extractor = import_feature_extractor(config['model']['backend'], input_size) train_generator = BatchGenerator(imagesTrainPaths, generator_config, norm=feature_extractor.normalize, jitter=True) val_generator = BatchGenerator(imagesValPaths, generator_config, norm=feature_extractor.normalize, jitter=False) features = feature_extractor.extract(input_image) # make the model head output = Conv2D(classes, (1, 1), padding="same")(features) output = BatchNormalization()(output) output = LeakyReLU(alpha=0.1)(output) output = GlobalAveragePooling2D()(output) output = Activation("sigmoid")(output) if classes == 1 else Activation( "softmax")(output) if config['train']['pretrained_weights'] != "": model = load_model(config['model']['pretrained_weights']) else: model = Model(input_image, output) opt = Adam() model.compile(loss="binary_crossentropy" if classes == 1 else "categorical_crossentropy", optimizer=opt, metrics=["accuracy"]) model.summary() model.fit_generator(train_generator, steps_per_epoch=len(imagesTrainPaths) // batchSize, epochs=epochs, validation_data=val_generator, validation_steps=len(imagesValPaths) // batchSize, callbacks=[checkPointSaverBest, checkPointSaver, tb], workers=12, max_queue_size=40)