Zaczynam od numpy tablicy obrazu.
In[1]:img = cv2.imread('test.jpg')
Kształt jest taki, jakiego można się spodziewać po obrazie 640x480 RGB.
In[2]:img.shape
Out[2]: (480, 640, 3)
Jednak ten obraz, który mam, to klatka wideo, która ma 100 klatek. Idealnie chciałbym mieć pojedynczą tablicę zawierającą wszystkie dane z tego filmu wideo, która img.shape
zwraca (480, 640, 3, 100)
.
Jaki jest najlepszy sposób na dodanie następnej klatki - czyli następnego zestawu danych obrazu, kolejnej tablicy 480 x 640 x 3 - do mojej początkowej tablicy?
numpy.newaxis
jest zdefiniowany jakoNone
(w plikunumeric.py
), więc równoważnie można użyć parametru `image = image [..., None].None
. Użyj,np.newaxis
ponieważ jawne jest lepsze niż niejawne.None
nic nie oznacza. To jest wyraźne. Tak jestNone
. Podane jasno.None
jest rzeczą w Pythonie. Nie ma wątpliwości.None
to ostatni szczegół, głębiej nie można. Z drugiej stronynumpy.newaxis
sugerujeNone
. To jest zasadniczoNone
. Tak jestNone
. Ale jest wNone
domyśle. Nie jest toNone
jednak bezpośrednio wyrażone jakoNone
. Wyraźnie określone jasno i szczegółowo, nie pozostawiając miejsca na zamieszanie lub wątpliwości. Ukryta sugestia, ale nie wyrażona bezpośrednio. Muszę dodać, że z punktu widzenia API jest bezpieczniejszy w użyciunumpy.newaxis
.Alternatywnie do
w odpowiedzi @dbliss możesz również użyć
numpy.expand_dims
likeNa przykład (wzięty z linku powyżej):
x = np.array([1, 2]) print(x.shape) # prints (2,)
Następnie
y = np.expand_dims(x, axis=0)
plony
array([[1, 2]])
i
daje
(1, 2)
źródło
y[1,0]
to zrobię , daje indeks poza granicami błędu.y[0,1]
jest dostępnyMożesz po prostu utworzyć tablicę o odpowiednim rozmiarze z góry i wypełnić ją:
frames = np.empty((480, 640, 3, 100)) for k in xrange(nframes): frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))
jeśli ramki były pojedynczymi plikami jpg, które zostały nazwane w określony sposób (w przykładzie ramka_0.jpg, ramka_1.jpg itd.).
Uwaga
(nframes, 480,640,3)
, zamiast tego możesz rozważyć użycie tablicy shape.źródło
Pythonic
X = X[:, :, None]
co jest równoważne
X = X[:, :, numpy.newaxis]
iX = numpy.expand_dims(X, axis=-1)
Ale ponieważ wyraźnie pytasz o układanie obrazów w stosy, polecam ułożenie
list
obrazównp.stack([X1, X2, X3])
, które być może zebrałeś w pętli.Jeśli nie podoba ci się kolejność wymiarów, możesz zmienić kolejność
np.transpose()
źródło
Możesz
np.concatenate()
określić, które elementyaxis
dołączyć, używającnp.newaxis
:import numpy as np movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)
Jeśli czytasz z wielu plików:
import glob movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)
źródło
W numpy nie ma struktury, która pozwala później dołączyć więcej danych.
Zamiast tego numpy umieszcza wszystkie twoje dane w ciągłej porcji liczb (w zasadzie; tablica C), a każda zmiana rozmiaru wymaga przydzielenia nowej porcji pamięci do jej przechowywania. Szybkość Numpy wynika z możliwości przechowywania wszystkich danych w tablicy numpy w tej samej części pamięci; np. operacje matematyczne można zrównoleglać w celu zwiększenia szybkości i uzyskuje się mniej błędów pamięci podręcznej .
Będziesz więc mieć dwa rodzaje rozwiązań:
images = [] for i in range(100): new_image = # pull image from somewhere images.append(new_image) images = np.stack(images, axis=3)
Zwróć uwagę, że nie ma potrzeby wcześniejszego rozszerzania wymiarów poszczególnych tablic obrazów ani nie musisz wiedzieć, ile obrazów spodziewasz się z wyprzedzeniem.
źródło
Rozważ Podejście 1 z metodą zmiany kształtu i Podejście 2 z metodą np. Newaxis, które dają ten sam wynik:
#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)
W rezultacie otrzymujemy:
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]]]]
źródło
Poszedłem w ten sposób:
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).
źródło