Я начинаю с массива изображений.
In[1]:img = cv2.imread('test.jpg')
Форма - это то, что вы могли ожидать от изображения RGB 640x480.
In[2]:img.shape
Out[2]: (480, 640, 3)
Однако это изображение, которое у меня есть, представляет собой кадр видео длиной 100 кадров. В идеале я хотел бы иметь один массив, содержащий все данные из этого видео, которые img.shape
возвращаются (480, 640, 3, 100)
.
Как лучше всего добавить следующий кадр - то есть следующий набор данных изображения, еще один массив 480 x 640 x 3 - в мой исходный массив?
numpy.newaxis
определяется какNone
(в файлеnumeric.py
), поэтому вы можете использовать `image = image [..., None].None
. Используйте,np.newaxis
потому что явное лучше, чем неявное.None
ничего не подразумевает. Это явно. Это такNone
. Сказано четко.None
это вещь в питона. Нет сомнений.None
это последняя деталь, вы не можете углубиться. С другой стороны,numpy.newaxis
подразумеваетNone
. По сути, этоNone
. Это такNone
. Но этоNone
безоговорочно. ОнNone
хотя и не непосредственно выражаетсяNone
. Явная заявил четко и в деталях, не оставляя места для путаницы или сомнений. Неявно предлагается, но прямо не выражается. Я должен добавить, что с точки зрения API его безопаснее использоватьnumpy.newaxis
.Альтернативно
в ответе @dbliss вы также можете использовать
numpy.expand_dims
какНапример (взято по ссылке выше):
x = np.array([1, 2]) print(x.shape) # prints (2,)
потом
y = np.expand_dims(x, axis=0)
дает
array([[1, 2]])
и
дает
(1, 2)
источник
y[1,0]
это дает ошибку индекса за пределами границ.y[0,1]
доступноВы можете просто заранее создать массив нужного размера и заполнить его:
frames = np.empty((480, 640, 3, 100)) for k in xrange(nframes): frames[:,:,:,k] = cv2.imread('frame_{}.jpg'.format(k))
если кадры были отдельными jpg-файлами, которые были названы определенным образом (в примере, frame_0.jpg, frame_1.jpg и т. д.).
Просто примечание:
(nframes, 480,640,3)
вместо этого вы можете рассмотреть возможность использования фигурного массива.источник
Питонический
X = X[:, :, None]
что эквивалентно
X = X[:, :, numpy.newaxis]
иX = numpy.expand_dims(X, axis=-1)
Но поскольку вы явно спрашиваете о штабелировании изображений, я бы порекомендовал сложить
list
изображенияnp.stack([X1, X2, X3])
которые вы, возможно, собрали, в цикле.Если вам не нравится порядок размеров, вы можете изменить его с помощью
np.transpose()
источник
Вы можете
np.concatenate()
указать, чтоaxis
нужно добавить, используяnp.newaxis
:import numpy as np movie = np.concatenate((img1[:,np.newaxis], img2[:,np.newaxis]), axis=3)
Если вы читаете из большого количества файлов:
import glob movie = np.concatenate([cv2.imread(p)[:,np.newaxis] for p in glob.glob('*.jpg')], axis=3)
источник
В numpy нет структуры, которая позволила бы вам добавить больше данных позже.
Вместо этого numpy помещает все ваши данные в непрерывный фрагмент чисел (в основном, массив C), и любое изменение размера требует выделения нового фрагмента памяти для его хранения. Скорость Numpy зависит от возможности хранить все данные в массиве numpy в одном и том же фрагменте памяти; например, математические операции могут быть распараллелены для увеличения скорости, и вы получите меньше промахов в кэше .
Итак, у вас будет два вида решений:
images = [] for i in range(100): new_image = # pull image from somewhere images.append(new_image) images = np.stack(images, axis=3)
Обратите внимание, что нет необходимости сначала расширять размеры отдельных массивов изображений, и вам не нужно знать, сколько изображений вы ожидаете заранее.
источник
Рассмотрим подход 1 с методом изменения формы и подход 2 с методом np.newaxis, которые дают тот же результат:
#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)
В результате имеем:
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]]]]
источник
Я последовал такому подходу:
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).
источник