Чтение данных из файла TFRecord, используемого в API обнаружения объектов

Я хочу прочитать данные, хранящиеся в файле TFRecord, который я использовал в качестве записи поезда в API обнаружения объектов TF.

Тем не менее, я получаю InvalidArgumentError: Input to reshape is a tensor with 91090 values, but the requested shape has 921600, Я не понимаю, в чем причина ошибки, хотя расхождение кажется в 10 раз больше.

Вопрос: Как я могу прочитать файл без этой ошибки?

  • Я не могу исключить, что ошибка связана с созданием записи или с тем, как я ее читаю. Поэтому я включил свой код для обоих.
  • Я могу запустить object_detection/train.py с данными И сгенерировать замороженный график из обученной модели.
  • Из этого ответа (и упомянутой проблемы с GitHub) я понял, что мне нужно конвертировать изображения PNG в JPG, поэтому as_jpg-часть (см. мой код ниже).
  • Я использовал код из этого ответа в качестве отправной точки для чтения файла.
  • Я использую Tensorflow 1.7.0, Python 3.5

Есть только один класс: "Человек". Запись имеет 1000 изображений; Каждое изображение может иметь одну ограничивающую рамку или несколько. (Один для каждого человека на соответствующем изображении.)

Как я читаю TFRecord: Как уже упоминалось выше: я использовал код из этого ответа в качестве отправной точки для чтения файла:

train_record = 'train.record'

def read_and_decode(filename_queue):
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)
    features = tf.parse_single_example(
        serialized_example,
        # Defaults are not specified since both keys are required.
        features={
            'image/height': tf.FixedLenFeature([], tf.int64),
            'image/width': tf.FixedLenFeature([], tf.int64),
            'image/source_id': tf.FixedLenFeature([], tf.string),
            'image/encoded': tf.FixedLenFeature([], tf.string),
            'image/format': tf.FixedLenFeature([], tf.string),
            'image/object/bbox/xmin': tf.VarLenFeature(tf.float32),
            'image/object/bbox/xmax': tf.VarLenFeature(tf.float32),
            'image/object/bbox/ymin': tf.VarLenFeature(tf.float32),
            'image/object/bbox/ymax': tf.VarLenFeature(tf.float32),
            'image/object/class/text': tf.VarLenFeature(tf.string),
            'image/object/class/label': tf.VarLenFeature(tf.int64)
        })
    image = tf.decode_raw(features['image/encoded'], tf.uint8)
    # label = tf.cast(features['image/object/class/label'], tf.int32)
    height = tf.cast(features['image/height'], tf.int32)
    width = tf.cast(features['image/width'], tf.int32)
    return image, height, width

def get_all_records(FILE):
    with tf.Session() as sess:
        filename_queue = tf.train.string_input_producer([ FILE ])
        image, height, width = read_and_decode(filename_queue)
        image = tf.reshape(image, tf.stack([height, width, 3]))
        image.set_shape([640,480,3])
        init_op = tf.initialize_all_variables()
        sess.run(init_op)
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(coord=coord)
        for i in range(1):
            example, l = sess.run([image])
            img = Image.fromarray(example, 'RGB')
            img.save( "output/" + str(i) + '-train.png')

            print (example,l)
        coord.request_stop()
        coord.join(threads)


get_all_records(train_record)

Создание:

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

Соответствующая часть может быть get_bytes()-метод, который является более оберткой для использования PIL Image.open(file_path):

class Image:

    # ... rest of class 


    def open_img(self):
        if self.file_path is not None:
            return Image.open(self.file_path)

    def get_bytes(self, as_jpg=False):
        if self.file_path is None:
             return None
        if as_jpg:
            # Convert to jpg:
            with BytesIO() as f:
                self.open_img().convert('RGB').save(f, format='JPEG', quality=95)
                return f.getvalue()
        else:  # Assume png
            return np.array(self.open_img().convert('RGB')).tobytes()

Как я создал Примеры:

use_jpg = True

def create_tf_example(img):
    image_format= b'jpg' if use_jpg else b'png'
    encoded_image_data = img.get_bytes(as_jpg=use_jpg) # Encoded image bytes

    relative_path = img.get_file_path()
    if relative_path is None or not img.has_person():
        return None  # Ignore images without humans or image data
    else:
        filename = str(Path(relative_path).resolve()) # Absolute filename of the image. Empty if image is not from file

    xmins = []  # List of normalized left x coordinates in bounding box (1 per box)
    xmaxs = []  # List of normalized right x coordinates in bounding box (1 per box)
    ymins = []  # List of normalized top y coordinates in bounding box (1 per box)
    ymaxs = []  # List of normalized bottom y coordinates in bounding box (1 per box)
    classes_text = []  # List of string class name of bounding box (1 per box)
    classes = []  # List of integer class id of bounding box (1 per box)

    for rect in img.rects:
        if not rect.is_person:
            continue  # For now, ignore negative samples as TF does this by default
        else:
            xmin, xmax, ymin, ymax = rect.get_normalized_xy_min_max()
            xmins.append(xmin)
            xmaxs.append(xmax)
            ymins.append(ymin)
            ymaxs.append(ymax)
            # Human class:
            classes.append(1)
            classes_text.append('Human'.encode())

    return tf.train.Example(features=tf.train.Features(feature={
        'image/height': dataset_util.int64_feature(height),
        'image/width': dataset_util.int64_feature(width),
        #  'image/filename': dataset_util.bytes_feature(filename.encode()),
        'image/source_id': dataset_util.bytes_feature(filename.encode()),
        'image/encoded': dataset_util.bytes_feature(encoded_image_data),
        'image/format': dataset_util.bytes_feature(image_format),
        'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
        'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
        'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
        'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
        'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
        'image/object/class/label': dataset_util.int64_list_feature(classes),
    }))

Как я создал TFRecord:

def convert_to_tfrecord(imgs, output_file_path):
    with tf.python_io.TFRecordWriter(output_file_path) as writer:
        for img in imgs:
            tf_example = create_tf_example(img)
            if tf_example is not None:
                writer.write(tf_example.SerializeToString())


convert_to_tfrecord(train_imgs, 'train.record')
convert_to_tfrecord(validation_imgs, 'validate.record')
convert_to_tfrecord(test_imgs, 'test.record')

От dataset_util модуль:

def int64_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))


def int64_list_feature(value):
    return tf.train.Feature(int64_list=tf.train.Int64List(value=value))


def bytes_feature(value):
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))


def bytes_list_feature(value):
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))


def float_list_feature(value):
    return tf.train.Feature(float_list=tf.train.FloatList(value=value))

1 ответ

Я решил проблему, расшифровав данные в формате JPEG с tf.image.decode_jpeg,

Вместо:

def read_and_decode(filename_queue):
    # ...

    image = tf.decode_raw(features['image/encoded'], tf.uint8)

    # ...

Я сделал:

def read_and_decode(filename_queue):
    # ...

    image = tf.image.decode_jpeg(features['image/encoded'])

    # ...

Это объясняет причину, по которой разница между ожидаемым размером и заданным размером была такой большой: данные (считанные) байты были "только" сжатыми данными JPEG, а не "полным" растровым изображением полного размера.

Другие вопросы по тегам