Понимание tf.extract_image_patches для извлечения патчей из изображения

Я нашел следующий метод tf.extract_image_patches в tenorflow API, но я не уверен в его функциональности.

Скажи batch_size = 1и изображение имеет размер 225x225x3и мы хотим извлечь патчи размера 32x32,

Как именно эта функция ведет себя? В частности, в документации упоминается размер выходного тензора, который должен быть [batch, out_rows, out_cols, ksize_rows * ksize_cols * depth], но что out_rows а также out_cols это не упоминается.

В идеале, учитывая тензор размера входного изображения 1x225x225x3 (где 1 - размер партии), я хочу получить Kx32x32x3 как вывод, где K это общее количество патчей и 32x32x3 это размер каждого патча. Есть ли что-то в тензорном потоке, которое уже достигает этого?

3 ответа

Решение

Вот как работает метод:

  • ksizes используется для определения размеров каждого патча или, другими словами, сколько пикселей должно содержать каждый патч.
  • strides обозначает длину промежутка между началом одного патча и началом следующего последовательного патча в исходном изображении.
  • rates это число, которое означает, что наш патч должен прыгнуть rates пикселей в исходном изображении для каждого последовательного пикселя, который заканчивается в нашем патче. (Пример ниже помогает проиллюстрировать это.)
  • padding либо "VALID", что означает, что каждый патч должен полностью содержаться в изображении, либо "SAME", что означает, что патчи могут быть неполными (оставшиеся пиксели будут заполнены нулями).

Вот пример кода с выводом, чтобы помочь продемонстрировать, как он работает:

import tensorflow as tf

n = 10
# images is a 1 x 10 x 10 x 1 array that contains the numbers 1 through 100 in order
images = [[[[x * n + y + 1] for y in range(n)] for x in range(n)]]

# We generate four outputs as follows:
# 1. 3x3 patches with stride length 5
# 2. Same as above, but the rate is increased to 2
# 3. 4x4 patches with stride length 7; only one patch should be generated
# 4. Same as above, but with padding set to 'SAME'
with tf.Session() as sess:
  print tf.extract_image_patches(images=images, ksizes=[1, 3, 3, 1], strides=[1, 5, 5, 1], rates=[1, 1, 1, 1], padding='VALID').eval(), '\n\n'
  print tf.extract_image_patches(images=images, ksizes=[1, 3, 3, 1], strides=[1, 5, 5, 1], rates=[1, 2, 2, 1], padding='VALID').eval(), '\n\n'
  print tf.extract_image_patches(images=images, ksizes=[1, 4, 4, 1], strides=[1, 7, 7, 1], rates=[1, 1, 1, 1], padding='VALID').eval(), '\n\n'
  print tf.extract_image_patches(images=images, ksizes=[1, 4, 4, 1], strides=[1, 7, 7, 1], rates=[1, 1, 1, 1], padding='SAME').eval()

Выход:

[[[[ 1  2  3 11 12 13 21 22 23]
   [ 6  7  8 16 17 18 26 27 28]]

  [[51 52 53 61 62 63 71 72 73]
   [56 57 58 66 67 68 76 77 78]]]]


[[[[  1   3   5  21  23  25  41  43  45]
   [  6   8  10  26  28  30  46  48  50]]

  [[ 51  53  55  71  73  75  91  93  95]
   [ 56  58  60  76  78  80  96  98 100]]]]


[[[[ 1  2  3  4 11 12 13 14 21 22 23 24 31 32 33 34]]]]


[[[[  1   2   3   4  11  12  13  14  21  22  23  24  31  32  33  34]
   [  8   9  10   0  18  19  20   0  28  29  30   0  38  39  40   0]]

  [[ 71  72  73  74  81  82  83  84  91  92  93  94   0   0   0   0]
   [ 78  79  80   0  88  89  90   0  98  99 100   0   0   0   0   0]]]]

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

 *  *  *  4  5  *  *  *  9 10 
 *  *  * 14 15  *  *  * 19 20 
 *  *  * 24 25  *  *  * 29 30 
31 32 33 34 35 36 37 38 39 40 
41 42 43 44 45 46 47 48 49 50 
 *  *  * 54 55  *  *  * 59 60 
 *  *  * 64 65  *  *  * 69 70 
 *  *  * 74 75  *  *  * 79 80 
81 82 83 84 85 86 87 88 89 90 
91 92 93 94 95 96 97 98 99 100 

Как видите, у нас есть 2 строки и 2 столбца патчей, которые out_rows а также out_cols являются.

Вступление

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

Изображение, которое мы будем использовать, имеет размер (256, 256, 3). Патчи, которые мы будем извлекать, будут иметь форму (128, 128, 3). Это означает, что мы извлечем 4 тайла из изображения.

Используемые данные

Я буду использовать набор данных цветов . В связи с тем, что для этого ответа требуется небольшой конвейер данных, я буду связывать здесь свое ядро kaggle, в котором говорится о потреблении набора данных с помощью tf.data.Dataset API.

После того, как мы закончим, мы рассмотрим следующие фрагменты кода.

      images, _ = next(iter(train_ds.take(1)))

image = images[0]
plt.imshow(image.numpy().astype("uint8"))

Здесь мы берем одно изображение из пакета изображений и визуализируем его как есть.

      image = tf.expand_dims(image,0) # To create the batch information
patches = tf.image.extract_patches(images=image,
                                   sizes=[1, 128, 128, 1],
                                   strides=[1, 128, 128, 1],
                                   rates=[1, 1, 1, 1],
                                   padding='VALID')

С помощью этого фрагмента мы извлекаем участки размером (128,128) из изображения размером (256,256). Это напрямую означает, что я хочу, чтобы изображения были разделены на 4 плитки.

Визуализация

      plt.figure(figsize=(10, 10))
for imgs in patches:
    count = 0
    for r in range(2):
        for c in range(2):
            ax = plt.subplot(2, 2, count+1)
            plt.imshow(tf.reshape(imgs[r,c],shape=(128,128,3)).numpy().astype("uint8"))
            count += 1

Чтобы развернуть подробный ответ Нила, есть много тонкостей с заполнением нулями при использовании "ЖЕ", так как extract_image_patches пытается центрировать патчи на изображении, если это возможно. В зависимости от шага, могут быть дополнения сверху и слева или нет, и первый патч не обязательно начинается в верхнем левом углу.

Например, расширяя предыдущий пример:

print tf.extract_image_patches(images, [1, 3, 3, 1], [1, n, n, 1], [1, 1, 1, 1], 'SAME').eval()[0]

С шагом n=1 изображение дополняется нулями, и первый патч начинается с отступа. Другие шаги дополняют изображение только справа и снизу или вообще не. С шагом n=10 одиночное пятно начинается с элемента 34 (в середине изображения).

tf.extract_image_patches реализован собственной библиотекой, в частности, Tensor ImagePatchOp. Вы можете изучить этот код, чтобы увидеть, как именно вычисляются позиции патча и отступы.

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