Python 使用numpy以更惯用的方式在网格中显示图像

Python 使用numpy以更惯用的方式在网格中显示图像,python,python-3.x,numpy,image-processing,Python,Python 3.x,Numpy,Image Processing,是否有一种更惯用的方式来显示下面示例中的图像网格 import numpy as np def gallery(array, ncols=3): nrows = np.math.ceil(len(array)/float(ncols)) cell_w = array.shape[2] cell_h = array.shape[1] channels = array.shape[3] result = np.zeros((cell_h*nrows, cel

是否有一种更惯用的方式来显示下面示例中的图像网格

import numpy as np

def gallery(array, ncols=3):
    nrows = np.math.ceil(len(array)/float(ncols))
    cell_w = array.shape[2]
    cell_h = array.shape[1]
    channels = array.shape[3]
    result = np.zeros((cell_h*nrows, cell_w*ncols, channels), dtype=array.dtype)
    for i in range(0, nrows):
        for j in range(0, ncols):
            result[i*cell_h:(i+1)*cell_h, j*cell_w:(j+1)*cell_w, :] = array[i*ncols+j]
    return result
我尝试使用
hstack
重塑
等,但无法获得正确的行为

我对使用numpy来实现这一点很感兴趣,因为使用matplotlib调用
subplot
imshow
可以打印多少图像是有限制的

如果您需要样本数据进行测试,您可以像这样使用网络摄像头:

import cv2
import matplotlib.pyplot as plt
_, img = cv2.VideoCapture(0).read()

plt.imshow(gallery(np.array([img]*6)))
屈服


我们有一系列的形状
(nrows*ncols、身高、体重、强度)
。 我们需要一个形状数组
(高度*nrows,宽度*ncols,强度)

因此,这里的想法是首先使用
重塑
将第一个轴拆分为两个轴,一个是长度
nrows
,另一个是长度
ncols

array.reshape(nrows, ncols, height, width, intensity)
这允许我们使用
swapaxes(1,2)
对轴进行重新排序,以使形状成为
(nrows、身高、ncols、体重、强度)
。请注意,这将
nrows
放在
height
旁边,而
ncols
放在
width
旁边

由于数据的复杂性,
重塑(高度*nrows,宽度*ncols,强度)
现在生成所需的数组

这(在精神上)与中使用的想法相同。

另一种方法是使用。然后避免手动交换轴:

from skimage.util import view_as_blocks
import numpy as np

def refactor(im_in,ncols=3):
    n,h,w,c = im_in.shape
    dn = (-n)%ncols # trailing images
    im_out = (np.empty((n+dn)*h*w*c,im_in.dtype)
           .reshape(-1,w*ncols,c))
    view=view_as_blocks(im_out,(h,w,c))
    for k,im in enumerate( list(im_in) + dn*[0] ):
        view[k//ncols,k%ncols,0] = im 
    return im_out

这个答案是基于@unutbu的,但它涉及
HWC
有序张量。此外,它还为未均匀分解到给定行/列的任何通道显示黑色分幅

def tile(arr, nrows, ncols):
    """
    Args:
        arr: HWC format array
        nrows: number of tiled rows
        ncols: number of tiled columns
    """
    h, w, c = arr.shape
    out_height = nrows * h
    out_width = ncols * w
    chw = np.moveaxis(arr, (0, 1, 2), (1, 2, 0))

    if c < nrows * ncols:
        chw = chw.reshape(-1).copy()
        chw.resize(nrows * ncols * h * w)

    return (chw
        .reshape(nrows, ncols, h, w)
        .swapaxes(1, 2)
        .reshape(out_height, out_width))

数组的形状是什么?它的4个维度(索引、行、列、强度)。其中强度=3。我无法运行它。你能在你这边发布一个样本/测试它吗?如果我想从4*4阵列中保存的图像中选择16个不同的图像,我该怎么做?这里您使用的是相同的图像问题:
convert('RGB')
是否返回三通道图像?这是如何形成最终形状的
(nrows*ncols、身高、体重、强度)
?不知何故,3个通道
R
G
B
似乎变成了一个
强度
通道?
def tile(arr, nrows, ncols):
    """
    Args:
        arr: HWC format array
        nrows: number of tiled rows
        ncols: number of tiled columns
    """
    h, w, c = arr.shape
    out_height = nrows * h
    out_width = ncols * w
    chw = np.moveaxis(arr, (0, 1, 2), (1, 2, 0))

    if c < nrows * ncols:
        chw = chw.reshape(-1).copy()
        chw.resize(nrows * ncols * h * w)

    return (chw
        .reshape(nrows, ncols, h, w)
        .swapaxes(1, 2)
        .reshape(out_height, out_width))
def detile(arr, nrows, ncols, c, h, w):
    """
    Args:
        arr: tiled array
        nrows: number of tiled rows
        ncols: number of tiled columns
        c: channels (number of tiles to keep)
        h: height of tile
        w: width of tile
    """
    chw = (arr
        .reshape(nrows, h, ncols, w)
        .swapaxes(1, 2)
        .reshape(-1)[:c*h*w]
        .reshape(c, h, w))

    return np.moveaxis(chw, (0, 1, 2), (2, 0, 1)).reshape(h, w, c)