Reputation: 258
I have image in a numpy array of shape (3, height, width) and I want to create an of subimage views. I know exactly how many subimages I will have and can create each ones in cycle. That's how I did it:
result_array = np.empty(
shape=(
int((res_img.shape[WIDTH] - SUB_IMG_WIDTH + 1) / step * (
res_img.shape[HEIGHT] - SUB_IMG_HEIGHT + 1) / step),
SUB_IMG_LAYERS, SUB_IMG_HEIGHT, SUB_IMG_WIDTH),
dtype=np.dtype(float))
for i in range(0, img.shape[WIDTH] - sub_img_shape[WIDTH], step):
for ii in range(0, img.shape[HEIGHT] - sub_img_shape[HEIGHT], step):
result_array[index] = img[:, i:i + sub_img_shape[WIDTH], ii:ii + sub_img_shape[HEIGHT]]
But instead of array of views I get array of copies. It's not problem by itself, I don't need to modify them, just use them simultaneously on GPU, but it's consume terrible amount of memory: My images have size about 1000x600 and I have roughly 100 000 subimages. So my array of subimages consume 3-4 Gb of my RAM. I tried to store views in python list, like that:
for i in range(0, img.shape[WIDTH] - sub_img_shape[WIDTH], step):
for ii in range(0, img.shape[HEIGHT] - sub_img_shape[HEIGHT], step):
result_array.append(img[:, i:i + sub_img_shape[WIDTH], ii:ii + sub_img_shape[HEIGHT]])
And it worked, but I doubt that it's a good method. Any way I can do this with a numpy array and not a python list?
Upvotes: 1
Views: 530
Reputation: 18668
You can do it using the as_strided
function:
import numpy as np
from numpy.lib.stride_tricks import as_strided
N=10
L=4*N
H=3*N
step=5
a=(np.arange(3*H*L)%256).reshape(3,H,L)
(k,j,i)=a.strides
b=as_strided (a,shape=(H/step,L/step,3,step,step),strides=(j*step,i*step,k,j,i))
b
then address each bloc without copy.
In [29]: np.all(b[1,2]==a[:,5:10,10:15])
Out[29]: True
In [30]: a[:,5,10]=0 # modification of a
In [31]: np.all(b[1,2]==a[:,5:10,10:15])
Out[31]: True # b also modified
Upvotes: 3