Estoy comenzando con una gran variedad de imágenes.
In[1]:img = cv2.imread('test.jpg')
La forma es la que cabría esperar de una imagen RGB de 640x480.
In[2]:img.shape
Out[2]: (480, 640, 3)
Sin embargo, esta imagen que tengo es un fotograma de un video, que tiene 100 fotogramas de largo. Idealmente, me gustaría tener una sola matriz que contenga todos los datos de este video de manera que img.shape
regrese (480, 640, 3, 100)
.
¿Cuál es la mejor manera de agregar el siguiente fotograma, es decir, el siguiente conjunto de datos de imagen, otra matriz de 480 x 640 x 3, a mi matriz inicial?
numpy.newaxis
se define comoNone
(en archivonumeric.py
), por lo que, de manera equivalente, podría usar `image = image [..., None].None
. Úselonp.newaxis
porque explícito es mejor que implícito.None
no implica nada. Es explícito. Lo esNone
. Dicho claramente.None
es una cosa en Python. No hay duda.None
es el último detalle, no se puede profundizar. Por otro lado,numpy.newaxis
implicaNone
. Es, en esencia,None
. Lo esNone
. Pero esNone
implícitamente. SeNone
aunque no expresa directamente comoNone
. Expresado explícitamente de forma clara y detallada, sin dejar lugar a confusión o duda. Implícito sugerido pero no expresado directamente. Debo agregar que, desde la perspectiva de la API, es más seguro de usarnumpy.newaxis
.Alternativamente a
en la respuesta de @dbliss , también puedes usar
numpy.expand_dims
likePor ejemplo (tomado del enlace anterior):
x = np.array([1, 2]) print(x.shape) # prints (2,)
Entonces
y = np.expand_dims(x, axis=0)
rendimientos
array([[1, 2]])
y
da
(1, 2)
fuente
y[1,0]
, da un error de índice fuera de los límites.y[0,1]
es accesiblePuede crear una matriz del tamaño correcto por adelantado y llenarla:
frames = np.empty((480, 640, 3, 100)) for k in xrange(nframes): frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))
si los marcos eran archivos jpg individuales que se nombraron de alguna manera en particular (en el ejemplo, frame_0.jpg, frame_1.jpg, etc.).
Solo una nota, en su lugar, podría considerar usar una
(nframes, 480,640,3)
matriz con forma.fuente
Pitónico
X = X[:, :, None]
que es equivalente a
X = X[:, :, numpy.newaxis]
yX = numpy.expand_dims(X, axis=-1)
Pero como está preguntando explícitamente acerca de apilar imágenes, le recomendaría apilar las
list
imágenesnp.stack([X1, X2, X3])
que puede haber recopilado en un bucle.Si no le gusta el orden de las dimensiones, puede reorganizarlo con
np.transpose()
fuente
Puede usar
np.concatenate()
especificando cuálaxis
agregar, usandonp.newaxis
:import numpy as np movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)
Si está leyendo de muchos archivos:
import glob movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)
fuente
No hay una estructura en numpy que le permita agregar más datos más adelante.
En su lugar, numpy coloca todos sus datos en una parte contigua de números (básicamente, una matriz de C), y cualquier cambio de tamaño requiere asignar una nueva parte de memoria para contenerla. La velocidad de Numpy proviene de poder mantener todos los datos en una matriz numerosa en la misma porción de memoria; por ejemplo, las operaciones matemáticas se pueden paralelizar para aumentar la velocidad y se obtienen menos errores de caché .
Entonces tendrás dos tipos de soluciones:
images = [] for i in range(100): new_image = # pull image from somewhere images.append(new_image) images = np.stack(images, axis=3)
Tenga en cuenta que no es necesario expandir primero las dimensiones de las matrices de imágenes individuales, ni tampoco es necesario saber cuántas imágenes espera de antemano.
fuente
Considere el enfoque 1 con el método de remodelación y el enfoque 2 con el método np.newaxis que producen el mismo resultado:
#Lets suppose, we have: x = [1,2,3,4,5,6,7,8,9] print('I. x',x) xNpArr = np.array(x) print('II. xNpArr',xNpArr) print('III. xNpArr', xNpArr.shape) xNpArr_3x3 = xNpArr.reshape((3,3)) print('IV. xNpArr_3x3.shape', xNpArr_3x3.shape) print('V. xNpArr_3x3', xNpArr_3x3) #Approach 1 with reshape method xNpArrRs_1x3x3x1 = xNpArr_3x3.reshape((1,3,3,1)) print('VI. xNpArrRs_1x3x3x1.shape', xNpArrRs_1x3x3x1.shape) print('VII. xNpArrRs_1x3x3x1', xNpArrRs_1x3x3x1) #Approach 2 with np.newaxis method xNpArrNa_1x3x3x1 = xNpArr_3x3[np.newaxis, ..., np.newaxis] print('VIII. xNpArrNa_1x3x3x1.shape', xNpArrNa_1x3x3x1.shape) print('IX. xNpArrNa_1x3x3x1', xNpArrNa_1x3x3x1)
Tenemos como resultado:
I. x [1, 2, 3, 4, 5, 6, 7, 8, 9] II. xNpArr [1 2 3 4 5 6 7 8 9] III. xNpArr (9,) IV. xNpArr_3x3.shape (3, 3) V. xNpArr_3x3 [[1 2 3] [4 5 6] [7 8 9]] VI. xNpArrRs_1x3x3x1.shape (1, 3, 3, 1) VII. xNpArrRs_1x3x3x1 [[[[1] [2] [3]] [[4] [5] [6]] [[7] [8] [9]]]] VIII. xNpArrNa_1x3x3x1.shape (1, 3, 3, 1) IX. xNpArrNa_1x3x3x1 [[[[1] [2] [3]] [[4] [5] [6]] [[7] [8] [9]]]]
fuente
Seguí este enfoque:
import numpy as np import cv2 ls = [] for image in image_paths: ls.append(cv2.imread('test.jpg')) img_np = np.array(ls) # shape (100, 480, 640, 3) img_np = np.rollaxis(img_np, 0, 4) # shape (480, 640, 3, 100).
fuente