示例#1
0
def read_class_csv(csv_class_file):
    """
    function that reads in a class csv file that is used as an input to the retinanet training routine, and outputs
    a list of class names which is the format required by Keras ImageGenerator
    :param csv_class_file: the filename of the csv containing class names and indices
    :return: list of classnames
    """
    try:
        with csv_generator._open_for_csv(csv_class_file) as file:
            classes = csv_generator._read_classes(
                csv.reader(file, delimiter=','))
            class_list = list(classes.keys())
            for c in classes:
                class_idx = classes[c]
                class_list[class_idx] = c
            return class_list
    except ValueError as e:
        raise_from(
            ValueError('invalid CSV class file: {}: {}'.format(
                csv_class_file, e)), None)
示例#2
0
def main(args=None):
    # parse arguments
    if args is None:
        args = sys.argv[1:]
    args = parse_args(args)

    # make sure keras is the minimum required version
    check_keras_version()

    # optionally choose specific GPU
    if args.gpu:
        os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu
    keras.backend.tensorflow_backend.set_session(get_session())

    # make save path if it doesn't exist
    if args.save_path is not None and not os.path.exists(args.save_path):
        os.makedirs(args.save_path)

    # optionally load config parameters
    if args.config:
        args.config = read_config_file(args.config)

    # create the generator
    #generator = create_generator(args)

    # optionally load anchor parameters
    anchor_params = None
    if args.config and 'anchor_parameters' in args.config:
        anchor_params = parse_anchor_parameters(args.config)

    # load the model
    print('Loading model, this may take a second...')
    model = models.load_model(args.model, backbone_name=args.backbone)

    # optionally convert the model
    if args.convert_model:
        model = models.convert_model(model, anchor_params=anchor_params)

    # print model summary
    print(model.summary())

    print("annotations", args.annotations)
    print("classes", args.classes)
    print("min", args.image_min_side)
    print("max", args.image_max_side)
    print("configs", args.config)
    iou_threshold = args.iou_threshold
    score_threshold = args.score_threshold
    max_detections = args.max_detections

    image_names = []
    image_data = {}

    # Take base_dir from annotations file if not explicitly specified.

    # parse the provided class file
    try:
        with _open_for_csv(args.classes) as file:
            classes = _read_classes(csv.reader(file, delimiter=','))
    except ValueError as e:
        raise_from(
            ValueError('invalid CSV class file: {}: {}'.format(
                args.classes, e)), None)

    labels = {}
    for key, value in classes.items():
        labels[value] = key

    # csv with img_path, x1, y1, x2, y2, class_name
    try:
        with _open_for_csv(args.annotations) as file:
            file_annotations = _read_annotations(
                csv.reader(file, delimiter=','), classes)
    except ValueError as e:
        raise_from(
            ValueError('invalid CSV annotations file: {}: {}'.format(
                args.annotations, e)), None)
    image_names = list(file_annotations.keys())

    num_classes = len(labels)

    all_detections = [[None for i in range(num_classes) if i in labels]
                      for j in range(len(image_names))]
    for image_index in range(len(image_names)):
        """ Load annotations for an image_index.
		"""
        path = file_annotations[image_names[image_index]]
        annotations = {'labels': np.empty((0, )), 'bboxes': np.empty((0, 4))}

        for idx, annot in enumerate(
                file_annotations[image_names[image_index]]):
            for key, value in classes.items():
                if annot['class'] == key:
                    break

            annotations['labels'] = np.concatenate(
                (annotations['labels'], [value]))
            annotations['bboxes'] = np.concatenate((annotations['bboxes'], [[
                float(annot['x1']),
                float(annot['y1']),
                float(annot['x2']),
                float(annot['y2']),
            ]]))

    f = []
    for label in range(num_classes):
        for cls in classes:
            if classes[cls] == label:
                print('class', cls)
                break
        f.append(
            open(
                "results/comp4_det_" +
                args.annotations.split("/")[-1].split(".")[0] + "_" + cls +
                ".txt", 'w'))

    for i in range(0, len(image_names)):
        print('image num', i)
        file_name = image_names[i]

        # load image
        image = read_image_bgr(file_name)
        image = preprocess_image(image)
        image, scale = resize_image(image)
        boxes, scores, labels = model.predict_on_batch(
            np.expand_dims(image, axis=0))
        boxes /= scale

        # select indices which have a score above the threshold
        indices = np.where(scores[0, :] > score_threshold)[0]

        # select those scores
        scores = scores[0][indices]

        # find the order with which to sort the scores
        scores_sort = np.argsort(-scores)[:max_detections]

        # select detections
        image_boxes = boxes[0, indices[scores_sort], :]
        image_scores = scores[scores_sort]
        image_labels = labels[0, indices[scores_sort]]
        image_detections = np.concatenate([
            image_boxes,
            np.expand_dims(image_scores, axis=1),
            np.expand_dims(image_labels, axis=1)
        ],
                                          axis=1)
        # copy detections to all_detections
        for label in range(num_classes):
            if not label in labels:
                continue
            dets = image_detections[image_detections[:, -1] == label, :-1]
            for cls in classes:
                if classes[cls] == label:
                    print('class', cls)
                    break
            for scr in dets:
                f[label].write(
                    file_name.split("/")[-1].split(".")[0] + " " +
                    str(scr[4]) + " " + str(scr[0]) + " " + str(scr[1]) + " " +
                    str(scr[2]) + " " + str(scr[3]) + "\n")

    for label in range(num_classes):
        f[label].close()
def anchors_optimize(
        annotations,
        ratios=3,
        scales=3,
        objective='focal',
        popsize=15,
        mutation=0.5,
        image_min_side=512,
        image_max_side=512,
        # default SIZES values
        SIZES=[32, 64, 128, 256, 512],
        # default STRIDES values
        STRIDES=[8, 16, 32, 64, 128],
        include_stride=False,
        resize=False,
        threads=1,
        verbose=False,
        seed=None):
    """
    Important Note: The python "anchors_optimize" function is meant to be used from the command line (from within a Python console it gives incorrect results)    
    """

    if ratios % 2 != 1:
        raise Exception('The number of ratios has to be odd.')

    entries = np.zeros((0, 4))
    max_x = 0
    max_y = 0

    updating = 'immediate'
    if threads > 1:
        # when the number of threads is > 1 then 'updating' is set to 'deferred' by default (see the documentation of "scipy.optimize.differential_evolution())
        updating = 'deferred'

    if seed is None:
        seed = np.random.RandomState()
    else:
        seed = np.random.RandomState(seed)

    if verbose:
        print('Loading object dimensions.')

    with _open_for_csv(annotations) as file:
        for line, row in enumerate(csv.reader(file, delimiter=',')):
            x1, y1, x2, y2 = list(map(lambda x: int(x), row[1:5]))

            if not x1 or not y1 or not x2 or not y2:
                continue

            if resize:
                # Concat base path from annotations file follow retinanet
                base_dir = os.path.split(annotations)[0]
                relative_path = row[0]
                image_path = os.path.join(base_dir, relative_path)
                img = Image.open(image_path)

                if hasattr(img, "shape"):
                    image_shape = img.shape
                else:
                    image_shape = (img.size[0], img.size[1], 3)

                scale = compute_resize_scale(image_shape,
                                             min_side=image_min_side,
                                             max_side=image_max_side)
                x1, y1, x2, y2 = list(map(lambda x: int(x) * scale, row[1:5]))

            max_x = max(x2, max_x)
            max_y = max(y2, max_y)

            if include_stride:
                entry = np.expand_dims(np.array([x1, y1, x2, y2]), axis=0)
                entries = np.append(entries, entry, axis=0)
            else:
                width = x2 - x1
                height = y2 - y1
                entry = np.expand_dims(np.array(
                    [-width / 2, -height / 2, width / 2, height / 2]),
                                       axis=0)
                entries = np.append(entries, entry, axis=0)

    image_shape = [max_y, max_x]

    if verbose:
        print('Optimising anchors.')

    bounds = []

    for i in range(int((ratios - 1) / 2)):
        bounds.append((1, 4))

    for i in range(scales):
        bounds.append((0.4, 2))

    update_state = None
    if threads == 1:
        update_state = state

    ARGS = (
        entries,
        image_shape,
        objective,
        ratios,
        include_stride,
        SIZES,
        STRIDES,
        verbose,
        update_state,
        # return a single value ('to_tuple' parameter is set to False)
        False,
        threads)

    result = scipy.optimize.differential_evolution(
        func=average_overlap,
        # pass the '*args' as a tuple (see: https://stackoverflow.com/q/32302654)
        args=ARGS,
        mutation=mutation,
        updating=updating,
        workers=threads,
        bounds=bounds,
        popsize=popsize,
        seed=seed)

    if hasattr(result, 'success') and result.success:
        print('Optimization ended successfully!')
    elif not hasattr(result, 'success'):
        print('Optimization ended!')
    else:
        print('Optimization ended unsuccessfully!')
        print('Reason: {}'.format(result.message))

    values = result.x
    anchor_params = calculate_config(values, ratios, SIZES, STRIDES)

    (avg, not_matched) = average_overlap(
        values,
        entries,
        image_shape,
        'avg',
        ratios,
        include_stride,
        SIZES,
        STRIDES,
        verbose,
        # pass a specific value to the 'set_state' parameter
        {'best_result': 0},
        # return a 'tuple'  ('to_tuple' parameter is set to True)
        True,
        # set the 'threads' parameter to 1
        1)

    # as 'end_state' set the 'avg' value
    end_state = np.round(avg, 5)
    RATIOS_result = sorted(np.round(anchor_params.ratios, 3))
    SCALES_result = sorted(np.round(anchor_params.scales, 3))

    print()
    print('Final best anchor configuration')
    print('State: {}'.format(end_state))
    print('Ratios: {}'.format(RATIOS_result))
    print('Scales: {}'.format(SCALES_result))

    dict_out = {
        'ratios': RATIOS_result,
        'scales': SCALES_result,
        'not_matched': not_matched,
        'end_state': end_state
    }

    if include_stride:
        STRIDE = np.round(1 - avg, 3)
        print('Average overlap: {}'.format(STRIDE))
        dict_out['stride'] = STRIDE

    print("Number of labels that don't have any matching anchor: {}".format(
        not_matched))

    return dict_out
示例#4
0
    if args.ratios % 2 != 1:
        raise Exception('The number of ratios has to be odd.')

    entries = np.zeros((0, 4))
    max_x = 0
    max_y = 0

    if args.seed:
        seed = np.random.RandomState(args.seed)
    else:
        seed = np.random.RandomState()

    print('Loading object dimensions.')

    with _open_for_csv(args.annotations) as file:
        for line, row in enumerate(csv.reader(file, delimiter=',')):
            x1, y1, x2, y2 = list(map(lambda x: int(x), row[1:5]))

            if not x1 or not y1 or not x2 or not y2:
                continue

            if args.resize:
                img = Image.open(row[0])

                if hasattr(img, "shape"):
                    image_shape = img.shape
                else:
                    image_shape = (img.size[0], img.size[1], 3)

                scale = compute_resize_scale(image_shape,