在张力流中以网格(即带有包装纸)的图像铺平图像



我想做的就是以格式(h,w,num_images(绘制一堆图像,并在网格中瓷砖以产生单个图像可以轻松绘制,但是我想将它们放在网格中,即用包裹(我想在Tensorflow中执行此操作(,即图形输出一个网格图像,准备绘制(。

通过输入:

a。(列数(即单行上的最大图像数(

b。(最大宽度(例如屏幕宽度(。并且它计算上述自动

我有一个numpy代码可以做到的,但是它很慢,我认为在GPU上执行此操作更有意义。

我的TensorFlow图形代码是此(t是卷积层的输出,因此最后一个轴包含图像的堆栈(:

act = tf.squeeze(t) # batch size is 1, so remove it
act = tf.unstack(act, num=num_filters, axis=-1) # split last axis (filters) into list of (h, w)
act = tf.stack(act) # re-stack on first axis

这给了我(num_filters,h,w(,我将其输入我编写的更通用的numpy代码中,该代码将其放在网格中(我的numpy代码很长,因为它更通用,并且可以使用可变大小的图像,所以我在下面不包括它(。

这可以直接在Tensorflow中进行?

(请注意,如果我要做tf.concat而不是tf.stack。

已将函数添加到tensorflow中,该函数确实如此:tf.contrib.gan.eval.image_grid。它接受形状[batch, width, height, channels]的输入张量,以及图像网格的形状,每个图像的尺寸以及图像通道的数量。它运行良好,易于使用。

对于具有形状的图像[批处理,宽度,高度,通道],可以使用

在Tensorflow中完成此操作
def image_grid(x, size=6):
    t = tf.unstack(x[:size * size], num=size*size, axis=0)
    rows = [tf.concat(t[i*size:(i+1)*size], axis=0) 
            for i in range(size)]
    image = tf.concat(rows, axis=1)
    return image[None]

我的numpy代码在少于20行中可以做到这一点,并且非常快。当我铺平10000x10000x3的图像时,情况非常快。如果图像不足,它将用零填充最后几个瓷砖。

def reshape_row(arr):
    return reduce(lambda x, y: np.concatenate((x,y), axis=1), arr)
def reshape_col(arr):
    return reduce(lambda x, y: np.concatenate((x,y), axis=0), arr)
def arbitrary_rows_cols(arr, num_rows, num_cols, gray=False):
    num_images, height, width, depth, = arr.shape
    rows = []
    for i in range(num_rows):
        row_image = arr[i*num_cols:i*num_cols+num_cols]
        r_n, r_h, r_w, r_d = row_image.shape
        if row_image.shape[0] != num_cols:
            for _ in range(num_cols - row_image.shape[0]):
                row_image = np.concatenate((row_image, np.expand_dims(np.zeros((height, width, depth)), axis=0)), axis=0)
        row_image = reshape_row(row_image)
        rows.append(row_image)
    mosaic = reshape_col(rows)
    return mosaic

您可以将此代码转换为TensorFlow代码,并且可能更快。看到性能比较会很有趣。

实际上我只是通过输入行数(这不是理想的,但现在足够好(。

def make_grid(t, num_images, num_rows=2):
    '''takes stack of images as (1, w, h, num_images) and tiles them into a grid'''
    t = tf.squeeze(t) # remove single batch, TODO make more flexible to work with higher batch size
    t = tf.unstack(t, num=num_images, axis=-1) # split last axis (num_images) into list of (h, w)
    t = tf.concat(t, axis=1) # tile all images horizontally into single row
    t = tf.split(t, num_rows, axis=1) # split into desired number of rows
    t = tf.concat(t, axis=0) # tile rows vertically
    return t

我的函数,如果您不指定想要多少个柱面,则可以构成方形网格,否则用N_COLS

网格
def tf_batch_to_canvas(X, cols: int = None):
"""
reshape a batch of images into a grid canvas to form a single image.
Parameters
----------
X: Tensor
    Batch of images to format. [N, H, W, C]-shaped
cols: int
    how many columns the grid should have. If None, a square grid will be created.
Returns
-------
image_grid: Tensor
    Tensor representing the image grid. [1, HH, WW, C]-shaped
Raises
------
    ValueError: The input tensor must be 4 dimensional
Examples
--------
x = np.ones((9, 100, 100, 3))
x = tf.convert_to_tensor(x)
canvas = batches.tf_batch_to_canvas(x)
assert canvas.shape == (1, 300, 300, 3)
canvas = batches.tf_batch_to_canvas(x, cols=5)
assert canvas.shape == (1, 200, 500, 3)
"""
if len(X.shape.as_list()) > 4:
    raise ValueError("input tensor has more than 4 dimensions.")
N, H, W, C = X.shape.as_list()
rc = math.sqrt(N)
if cols is None:
    rows = cols = math.ceil(rc)
else:
    cols = max(1, cols)
    rows = math.ceil(N / cols)
n_gray_tiles = cols * rows - N
if n_gray_tiles > 0:
    gray_tiles = tf.zeros((n_gray_tiles, H, W, C), X.dtype)
    X = tf.concat([X, gray_tiles], 0)
image_shape = (H, W)
n_channels = C
return image_grid(X, (rows, cols), image_shape, n_channels)

基本上,您现在可以使用tf.contrib.gan.eval.image_grid,具体取决于您的TensorFlow版本。https://www.tensorflow.org/api_docs/python/tf/contrib/gan/gan/eval/image_grid

https://github.com/tensorflow/tensorflow/blob/r1.14/tensorflow/contrib/contrib/gan/gan/python/eval/python/python/eval_impl.py.py#l34-l34-l80

最新更新