Manera más idiomática de mostrar imágenes en una cuadrícula con números.

¿Existe una forma más idiomática de mostrar una cuadrícula de imágenes como en el ejemplo a continuación?

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 

Intenté usar hstack y reshape , etc., pero no pude obtener el comportamiento correcto.

Estoy interesado en usar Numpy para hacer esto porque hay un límite en la cantidad de imágenes que puede trazar con las llamadas matplotlib a imshow e imshow .

Si necesita datos de muestra para probar, puede usar su cámara web así:

 import cv2 import matplotlib.pyplot as plt _, img = cv2.VideoCapture(0).read() plt.imshow(gallery(np.array([img]*6))) 

 import numpy as np import matplotlib.pyplot as plt def gallery(array, ncols=3): nindex, height, width, intensity = array.shape nrows = nindex//ncols assert nindex == nrows*ncols # want result.shape = (height*nrows, width*ncols, intensity) result = (array.reshape(nrows, ncols, height, width, intensity) .swapaxes(1,2) .reshape(height*nrows, width*ncols, intensity)) return result def make_array(): from PIL import Image return np.array([np.asarray(Image.open('face.png').convert('RGB'))]*12) array = make_array() result = gallery(array) plt.imshow(result) plt.show() 

rendimientos introduzca la descripción de la imagen aquí


Tenemos una variedad de formas (nrows*ncols, height, weight, intensity) . Queremos un conjunto de formas (height*nrows, width*ncols, intensity) .

Por lo tanto, la idea aquí es utilizar primero la reshape para dividir el primer eje en dos ejes, uno de longitud de nrows y uno de longitud de ncols :

 array.reshape(nrows, ncols, height, width, intensity) 

Esto nos permite usar swapaxes(1,2) para reordenar los ejes para que la forma se convierta en (nrows, height, ncols, weight, intensity) . Observe que esto coloca las nrows junto a la height y ncols lado de la width .

Dado que la reshape no cambia el orden de los datos, la reshape(height*nrows, width*ncols, intensity) ahora produce la matriz deseada.

Esto es (en espíritu) lo mismo que la idea utilizada en la función de unblockshaped en forma de unblockshaped .

Otra forma es usar view_as_blocks . Entonces evitas intercambiar ejes a mano:

 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