How to best reshape this array

I have a vector of matrices:

julia> n = 4
4

julia> sz = (5,6)
(5, 6)

julia> imgs = [i*ones(Int, sz...) for i in 1:n]
4-element Array{Array{Int64,2},1}:
 [1 1 … 1 1; 1 1 … 1 1; … ; 1 1 … 1 1; 1 1 … 1 1]
 [2 2 … 2 2; 2 2 … 2 2; … ; 2 2 … 2 2; 2 2 … 2 2]
 [3 3 … 3 3; 3 3 … 3 3; … ; 3 3 … 3 3; 3 3 … 3 3]
 [4 4 … 4 4; 4 4 … 4 4; … ; 4 4 … 4 4; 4 4 … 4 4]

I want to keep this form, but I also need another form: a matrix where each cell is a vector containing all the equivalent elements of the matrices from before:

julia> noise = [[imgs[j][i] for j in 1:n] for i in CartesianIndices(sz)]
5×6 Array{Array{Int64,1},2}:
 [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]
 [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]
 [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]
 [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]
 [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]  [1, 2, 3, 4]

julia> noise[2,3] # for example
4-element Array{Int64,1}:
 1
 2
 3
 4

Because I won’t need every single one of those vector-of-elements I’m using MappedArrays on the noise matrix to save time. I’m looking however into using some @view wizardry or some such for the reshaping step (turning the vector of matrices into a matrix of vectors)… Anyone knows a cool trick I can use?

For context: this is a vector of images (1440x1080 pixels) and can be 5000 images long. I’m accessing ~5000 pixels in this 10^10 soup.

You can first lay out the data then view into it in 2 different ways. Based on which access pattern will be used more often, you can also permute the dims of the data array to make it more cache-friendly.

julia> n = 4;

julia> sz = (5, 6);

julia> imgs = [i for I in CartesianIndices(sz), i in 1:n];

julia> imgs[:,:,1]
5×6 Array{Int64,2}:
 1  1  1  1  1  1
 1  1  1  1  1  1
 1  1  1  1  1  1
 1  1  1  1  1  1
 1  1  1  1  1  1

julia> imgs[:,:,2]
5×6 Array{Int64,2}:
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2

julia> getimgview(imgs, i) = @view imgs[:,:,i]
getimgview (generic function with 1 method)

julia> getpixelview(imgs, i, j) = @view imgs[i,j,:]
getpixelview (generic function with 1 method)

julia> getimgview(imgs, 1)
5×6 view(::Array{Int64,3}, :, :, 1) with eltype Int64:
 1  1  1  1  1  1
 1  1  1  1  1  1
 1  1  1  1  1  1
 1  1  1  1  1  1
 1  1  1  1  1  1

julia> getimgview(imgs, 2)
5×6 view(::Array{Int64,3}, :, :, 2) with eltype Int64:
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2
 2  2  2  2  2  2

julia> getpixelview(imgs, 1, 2)
4-element view(::Array{Int64,3}, 1, 2, :) with eltype Int64:
 1
 2
 3
 4

More elegantly, you can probably define a wrapper around imgs and overload getindex for 1 and 2 indices.

1 Like

This worked nicely, thanks!