Изменение размера изображений переменного размера для обнаружения объектов

Я использую набор данных обнаружения объектов KITTI для обучения Faster R-CNN с ResNet 101, предварительно обученного на MS COCO. Изображения KITTI "в основном" размером 375x1242

Когда у меня был batch_size: 1, все было идеально. Мой keep_aspect_ratio_resizer выглядел так, как показано ниже, как это было предложено самим TensorFlow.

min_dimension: 600
max_dimension: 1987

Но теперь я хочу использовать batch_size: 5, но продолжаю получать ошибки несоответствия размеров. Потому что некоторые изображения имеют немного меньший размер, например 370x1224 и т. Д.

Я не могу найти общие keep_aspect_ratio_resizervalues. Я попробовал следующие значения, основанные на значениях, которые я видел в сообщениях об ошибках, но я не могу сделать все изображения одинакового размера на самом деле

min_dimension: 600
max_dimension: 1985

min_dimension: 599
max_dimension: 1985

person kneazle    schedule 14.03.2019    source источник
comment
вы пробовали tf.image.crop_and_resize? Как устроен входной конвейер?   -  person Sharky    schedule 14.03.2019
comment
Я тренируюсь с legacy / train.py. Я там ничего не менял, да и в конфиге тоже. Честно говоря, я не знаю, куда поместить tf.image.crop_and_resize ... Я пробовал поставить fixed_shape_resizer перед keep_aspect_ratio_resizer в файле конфигурации, но это не сработало   -  person kneazle    schedule 14.03.2019
comment
Подумайте о добавлении кода или ссылки на github   -  person Sharky    schedule 14.03.2019
comment
Вместо этого я использовал tf.image.resize_image_with_crop_or_pad. выглядел как лучший вариант для моего случая. Большое спасибо за совет!   -  person kneazle    schedule 14.03.2019


Ответы (2)


Вы можете изменить размер изображений самостоятельно, чтобы обойти ошибку округления здесь или, вы можете попытаться сгруппировать элементы одинакового размера вместе в партии.

Предполагая, что у вас есть генератор изображений и что изображения имеют атрибут размера, вы можете создать генератор, который будет выдавать пакеты изображений одного размера, как показано ниже:

from itertools import groupby
from collections import deque, defaultdict


def same_size_batches(images, batch_size=5):
    image_cache = defaultdict(deque)

    # We assume the image object has a size parameter we can group by
    for size, images in groupby(images, key=lambda image: image.size):
        for image in images:
            image_cache[size].append(image)

            # Everytime our batch gets big enough, yield it and reset
            if len(image_cache[size]) == batch_size:
                yield iter(image_cache[size])
                image_cache[size].clear()

Основная часть здесь - это группа, которая группирует последовательные элементы по одному и тому же ключу и возвращает этот ключ и генератор элементов, соответствующих этому ключу. В нашем случае ключевым является размер изображения.

Затем мы сохраняем кеш элементов одного и того же размера, и каждый раз, когда один из размеров достигает желаемого размера пакета, мы генерируем генератор для этого пакета.

Мы можем продемонстрировать эту работу с фальшивым объектом изображения, у которого есть требуемый параметр размера:

import random


class FakeImage(object):
    def __init__(self, _id):
        self.id = _id
        self.size = (370, 1224) if random.random() < 0.25 else (375, 1242)

    def __repr__(self):
        return "<Image {} {}>".format(self.id, self.size)


images = (FakeImage(_id) for _id in range(100))
for batch in same_size_batches(images, batch_size=5):
    print(list(batch))

В результате получается что-то вроде:

[<Image 0 (375, 1242)>, <Image 2 (375, 1242)>, <Image 3 (375, 1242)>, <Image 4 (375, 1242)>, <Image 6 (375, 1242)>]
[<Image 7 (375, 1242)>, <Image 8 (375, 1242)>, <Image 9 (375, 1242)>, <Image 10 (375, 1242)>, <Image 12 (375, 1242)>]
[<Image 1 (370, 1224)>, <Image 5 (370, 1224)>, <Image 11 (370, 1224)>, <Image 14 (370, 1224)>, <Image 16 (370, 1224)>]
[<Image 13 (375, 1242)>, <Image 15 (375, 1242)>, <Image 18 (375, 1242)>, <Image 19 (375, 1242)>, <Image 20 (375, 1242)>]
[<Image 21 (375, 1242)>, <Image 23 (375, 1242)>, <Image 24 (375, 1242)>, <Image 25 (375, 1242)>, <Image 26 (375, 1242)>]
...

У нас нет гарантии, что мы создадим все изображения, если мы не получим достаточно, чтобы заполнить блок размера пакета, но если входом является бесконечный генератор, это не проблема.

person Jon Betts    schedule 14.03.2019
comment
Большое спасибо за подробное объяснение. Сначала я устал от другого решения, и оно сработало. - person kneazle; 14.03.2019

Исправлено добавлением tf.image.resize_image_with_crop_or_pad(images, max_height, max_width) в create_input_queue() в https://github.com/tensorflow/models/blob/master/research/object_detection/legacy/trainer.py.

person kneazle    schedule 14.03.2019