How to upsample an array (or image)

question
images
array

#1

I’m wondering how one would go about upsampling an array, I’ve come across interpolations.jl, to interpolate the newly created elements in the scaled array but I’m not certain how this can be used to upscale an array. Is there, by any chance, a package that handles array upsampling?

Thanks,
Jules


#2

You can use interpolations directly and index with real numbers within the range of valid indices (unless you want to use extrapolations as well). See the readme of the package you linked for more details on the parameters

julia> using Interpolations

julia> A = interpolate([1. 2; 3 4], BSpline(Linear()), OnGrid())
2×2 interpolate(::Array{Float64,2}, BSpline(Linear()), OnGrid()) with element type Float64:
 1.0  2.0
 3.0  4.0

julia> A[1:0.5:2, 1:0.5:2]
3×3 Array{Float64,2}:
 1.0  1.5  2.0
 2.0  2.5  3.0
 3.0  3.5  4.0

Images.jl offers a high-level interface for resizing which uses Interpolations.jl under the hood

julia> using Images

julia> A = [1. 2; 3 4]
2×2 Array{Float64,2}:
 1.0  2.0
 3.0  4.0

julia> imresize(A, (3, 3))
3×3 Array{Float64,2}:
 1.0  1.5  2.0
 2.0  2.5  3.0
 3.0  3.5  4.0

You can also use a mid-level interface - if you wish - to have control over the exact transformation. see warp or https://juliaimages.github.io/latest/indexing.html for details


#3

Thank you very much!

I guess Images.jl isn’t suitable since I’m using multi-dimensional arrays?

For the interpolations.jl method, how could you taken an array and, for example, double (or triple) it’s size. Say I want to double the following array: [1. 3 3 4 5 6; 7 8 9 10 11 12] (2x6)

I’ve tried the following:

A = interpolate([1. 3 3 4 5 6; 7 8 9 10 11 12], BSpline(Linear()), OnGrid())
A[1:0.5:2, 1:0.5:6]

instead of a 4x12 array, I end up with the following:

3×11 Array{Float64,2}:
 1.0  2.0   3.0  3.0   3.0  3.5   4.0   4.5   5.0   5.5   6.0
 4.0  4.75  5.5  5.75  6.0  6.5   7.0   7.5   8.0   8.5   9.0
 7.0  7.5   8.0  8.5   9.0  9.5  10.0  10.5  11.0  11.5  12.0

I’m not certain of what I should be doing instead so any help would be welcome!

Thanks in advance,
Jules


#4

You might want to try Images.jl anyway–I don’t think it has any particular restrictions to 2-dimensional arrays (that’s one of it’s best features, in my opinion).

Using interpolations directly, you just need to give the right range indices. 1:0.5:2 is a range with values [1, 1.5, 2], which is why you end up with 3 (instead of 4) rows in the result. If you want 4 elements in your range, you just need to pick the appropriate step size. In this case, it would be exactly 1/3 which you can represent as an exact Rational number in Julia with 1//3:

julia> length(1 : 1//3 : 2)
4

And you can use that range for to index into the interpolation:

julia> A[1:1//3:2, 1]
4-element Array{Float64,1}:
 1.0
 3.0
 5.0
 7.0

you can do the same with the column indices:

julia> A[1:1//3:2, 1:5//11:6]
4×12 Array{Float64,2}:
 1.0  1.90909  2.81818  3.0      3.0      3.27273  3.72727   4.18182   4.63636   5.09091   5.54545   6.0
 3.0  3.75758  4.51515  4.78788  4.93939  5.27273  5.72727   6.18182   6.63636   7.09091   7.54545   8.0
 5.0  5.60606  6.21212  6.57576  6.87879  7.27273  7.72727   8.18182   8.63636   9.09091   9.54545  10.0
 7.0  7.45455  7.90909  8.36364  8.81818  9.27273  9.72727  10.1818   10.6364   11.0909   11.5455   12.0

#5

You can do the following

julia> using Images

julia> A = reshape(1:18, (3,3,2))
3×3×2 Base.ReshapedArray{Int64,3,UnitRange{Int64},Tuple{}}:
[:, :, 1] =
 1  4  7
 2  5  8
 3  6  9

[:, :, 2] =
 10  13  16
 11  14  17
 12  15  18

julia> imresize(A, (5,5,2))
5×5×2 Array{Float64,3}:
[:, :, 1] =
 1.0  2.2  4.0  5.8  7.0
 1.4  2.6  4.4  6.2  7.4
 2.0  3.2  5.0  6.8  8.0
 2.6  3.8  5.6  7.4  8.6
 3.0  4.2  6.0  7.8  9.0

[:, :, 2] =
 10.0  11.2  13.0  14.8  16.0
 10.4  11.6  13.4  15.2  16.4
 11.0  12.2  14.0  15.8  17.0
 11.6  12.8  14.6  16.4  17.6
 12.0  13.2  15.0  16.8  18.0

#6

Thank you!
I think I’ll stick to the Images.jl method for now.


#7

Thanks, it seems that imresize is using bicubic interpolation? There probably is a way to change this?
It’s not really that important though, you guys already solved my problems! :heart:


#8

No it uses linear interpolation, but there is something non-trivial going on. See here for more information: https://github.com/JuliaImages/ImageTransformations.jl/blob/master/src/resizing.jl#L233-L265