Как говорит @Lev, вы сплющили свои массивы. Вам действительно не нужно делать это, чтобы выполнить среднее значение. Скажем, у вас есть массив из 2 3х4 изображений, то вы бы что-то вроде этого:
In [291]: b = np.random.rand(2,3,4)
In [292]: b.shape
Out[292]: (2, 3, 4)
In [293]: b
Out[293]:
array([[[ 0.18827554, 0.11340471, 0.45185287, 0.47889188],
[ 0.35961448, 0.38316556, 0.73464482, 0.37597429],
[ 0.81647845, 0.28128797, 0.33138755, 0.55403119]],
[[ 0.92025024, 0.55916671, 0.23892798, 0.59253267],
[ 0.15664109, 0.12457157, 0.28139198, 0.31634361],
[ 0.33420446, 0.27599807, 0.40336601, 0.67738928]]])
Perform среднего по первой оси, оставляя форму массивов:
In [300]: b.mean(0)
Out[300]:
array([[ 0.55426289, 0.33628571, 0.34539042, 0.53571227],
[ 0.25812778, 0.25386857, 0.5080184 , 0.34615895],
[ 0.57534146, 0.27864302, 0.36737678, 0.61571023]])
In [301]: b - b.mean(0)
Out[301]:
array([[[-0.36598735, -0.222881 , 0.10646245, -0.0568204 ],
[ 0.10148669, 0.129297 , 0.22662642, 0.02981534],
[ 0.24113699, 0.00264495, -0.03598923, -0.06167904]],
[[ 0.36598735, 0.222881 , -0.10646245, 0.0568204 ],
[-0.10148669, -0.129297 , -0.22662642, -0.02981534],
[-0.24113699, -0.00264495, 0.03598923, 0.06167904]]])
Для многих , это также будет быстрее, чем сохранение ваших изображений в виде списка массивов, поскольку операции numpy выполняются в одном массиве, а не через список массивов. Большинство методов, таких как mean
, cov
и т. Д., Принимают аргумент axis
, и вы можете перечислить все размеры для его выполнения без необходимости сглаживания.
Чтобы применить это в сценарий, я хотел бы сделать что-то вроде этого, сохраняя оригинальные размерности:
images = np.asarray([Image.open(fn).convert('L').resize((90, 90)) for fn in filenames])
# so images.shape = (len(filenames), 90, 90)
m = images.mean(0)
# numpy broadcasting will automatically subract the (90, 90) mean image from each of the `images`
# m.shape = (90, 90)
# shifted_images.shape = images.shape = (len(filenames), 90, 90)
shifted_images = images - m
#Step 7: input image
input_image = Image.open(...).convert('L').resize((90, 90))
T = np.asarray(input_image)
n = T - m
В качестве последнего комментария, если скорость является проблемой, это будет быстрее использовать np.dstack присоединиться изображения:
In [354]: timeit b = np.asarray([np.empty((50,100)) for i in xrange(1000)])
1 loops, best of 3: 824 ms per loop
In [355]: timeit b = np.dstack([np.empty((50,100)) for i in xrange(1000)]).transpose(2,0,1)
10 loops, best of 3: 118 ms per loop
Но это, вероятно, что загрузка изображений занимает большую часть времени, и если это так, вы можете проигнорировать это.
изображения должны быть сплющены, чтобы быть 2D-матрицей вместо 3D, чтобы иметь возможность вычислять среднее, ковариацию, собственные значения и собственные векторы. С другой стороны, если входное изображение будет сплющено, это будет 1D-массив, и я также не смогу вычислить среднее, ковариацию, собственные значения и собственные векторы. – user2229953
@ user2229953 Я не думаю, что это необходимо для любых функций, которые принимают аргумент 'axis', как примечания @askewchan. Во всяком случае, прямо сейчас вы вычитаете массив 8100 1D из массива 90x90, который должен быть исправлен так или иначе. –