Подтвердить что ты не робот

Tensorflow считывает изображения с помощью меток

Я создаю стандартную модель классификации изображений с Tensorflow. Для этого у меня есть входные изображения, каждый из которых назначается меткой (число в {0,1}). Поэтому данные могут быть сохранены в списке в следующем формате:

/path/to/image_0 label_0
/path/to/image_1 label_1
/path/to/image_2 label_2
...

Я хочу использовать систему очередей TensorFlow для чтения моих данных и передачи ее моей модели. Игнорируя метки, можно легко достичь этого, используя string_input_producer и wholeFileReader. Здесь код:

def read_my_file_format(filename_queue):
  reader = tf.WholeFileReader()
  key, value = reader.read(filename_queue)
  example = tf.image.decode_png(value)
  return example

#removing label, obtaining list containing /path/to/image_x
image_list = [line[:-2] for line in image_label_list]

input_queue = tf.train.string_input_producer(image_list)                                                     
input_images = read_my_file_format(input_queue)

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

4b9b3361

Ответ 1

Использование slice_input_producer обеспечивает решение, которое намного чище. Slice Input Producer позволяет создавать входную очередь, содержащую произвольно многие разделимые значения. Этот фрагмент вопроса будет выглядеть следующим образом:

def read_labeled_image_list(image_list_file):
    """Reads a .txt file containing pathes and labeles
    Args:
       image_list_file: a .txt file with one /path/to/image per line
       label: optionally, if set label will be pasted after each line
    Returns:
       List with all filenames in file image_list_file
    """
    f = open(image_list_file, 'r')
    filenames = []
    labels = []
    for line in f:
        filename, label = line[:-1].split(' ')
        filenames.append(filename)
        labels.append(int(label))
    return filenames, labels

def read_images_from_disk(input_queue):
    """Consumes a single filename and label as a ' '-delimited string.
    Args:
      filename_and_label_tensor: A scalar string tensor.
    Returns:
      Two tensors: the decoded image, and the string label.
    """
    label = input_queue[1]
    file_contents = tf.read_file(input_queue[0])
    example = tf.image.decode_png(file_contents, channels=3)
    return example, label

# Reads pfathes of images together with their labels
image_list, label_list = read_labeled_image_list(filename)

images = ops.convert_to_tensor(image_list, dtype=dtypes.string)
labels = ops.convert_to_tensor(label_list, dtype=dtypes.int32)

# Makes an input queue
input_queue = tf.train.slice_input_producer([images, labels],
                                            num_epochs=num_epochs,
                                            shuffle=True)

image, label = read_images_from_disk(input_queue)

# Optional Preprocessing or Data Augmentation
# tf.image implements most of the standard image augmentation
image = preprocess_image(image)
label = preprocess_label(label)

# Optional Image and Label Batching
image_batch, label_batch = tf.train.batch([image, label],
                                          batch_size=batch_size)

См. также generic_input_producer из TensorVision примеров для полного ввода-конвейера.

Ответ 2

Существует три основных способа решения этой проблемы:

  • Заполните tf.train.string_input_producer() со списком строк, содержащих исходную строку с разделителями-пробелами, содержащую имя файла и метку.

  • Используйте tf.read_file(filename) вместо tf.WholeFileReader() для чтения ваших файлов изображений. tf.read_file() - это безстоящий режим, который использует одно имя файла и создает одну строку, содержащую содержимое файла. Это имеет то преимущество, что это чистая функция, поэтому легко связывать данные со входом и выходом. Например, ваша функция read_my_file_format станет следующей:

    def read_my_file_format(filename_and_label_tensor):
      """Consumes a single filename and label as a ' '-delimited string.
    
      Args:
        filename_and_label_tensor: A scalar string tensor.
    
      Returns:
        Two tensors: the decoded image, and the string label.
      """
      filename, label = tf.decode_csv(filename_and_label_tensor, [[""], [""]], " ")
      file_contents = tf.read_file(filename)
      example = tf.image.decode_png(file_contents)
      return example, label
    
  • Вызовите новую версию read_my_file_format, передав один из выделенных элементов из input_queue:

    image, label = read_my_file_format(input_queue.dequeue())         
    

Затем вы можете использовать тензоры image и label в остальной части вашей модели.

Ответ 3

В дополнение к предоставленным ответам есть несколько других вещей, которые вы можете сделать:

Кодировать метку в имени файла. Если у вас есть N разных категорий, вы можете переименовать свои файлы на что-то вроде: 0_file001, 5_file002, N_file003. Впоследствии, когда вы читаете данные из reader key, value = reader.read(filename_queue), ваш ключ/значение:

Результатом чтения будет имя файла (ключ) и содержимое этого файла (значение)

Затем проанализируйте свое имя файла, извлеките ярлык и преобразуйте его в int. Это потребует немного предварительной обработки данных.

Используйте TFRecords, который позволит вам хранить данные и метки в одном файле.