Julia version of padarray in matlab

Hello,

I’ve been searching the documentations for some kind of julia alternative to the padarray function in matlab (Pad array - MATLAB padarray) but I did not find anything useful.

TL;DR: what i want to do is given an array u=[1 2; 3 4] pad it with the values on the border of my original array u (corresponding to the keywords 'replicate' and 'both' in the matlab couterpart)

padarray(u, [1, 1]) = [1 1 2 2
                       1 1 2 2
                       3 3 4 4
                       3 3 4 4]

does a function like this exists in julia or do i have to write my own?
In the latter case, any smart way to do it?

Thanks

repeat(u, inner=[2,2])
?repeat

One way is from here:

julia> using Pkg; pkg"add ImageFiltering"

julia> using ImageFiltering

julia> arr = reshape(1:6, (2,3))
2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
 1  3  5
 2  4  6

julia> BorderArray(arr, Pad((1,1)))
4×5 BorderArray{Int64,2,Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}},Pad{2}} with indices 0:3×0:4:
 1  1  3  5  5
 1  1  3  5  5
 2  2  4  6  6
 2  2  4  6  6

Note that this won’t in general agree with the result of repeat, e.g.:

julia> repeat(arr, inner=[2,2])
4×6 Array{Int64,2}:
 1  1  3  3  5  5
 1  1  3  3  5  5
 2  2  4  4  6  6
 2  2  4  4  6  6

Note also that for padding with a constant, but not with the edge values, there is GitHub - JuliaArrays/PaddedViews.jl: Add virtual padding to the edges of an array

Any reason to link to the Pull Request instead of documentation?
Think of the average user, he has no idea what he sees there.

I looked but couldn’t find it in that package’s docs in a few minutes. But if you can, please add a link.

Thanks, i think this is what i am looking for, i’ll look into it!

I looked but couldn’t find it in that package’s docs in a few minutes. But if you can, please add a link.

Sure!

Edit: Found this: https://juliaimages.org/ImageFiltering.jl/stable/function_reference.html#Boundaries-and-padding-1

Oh right, I missed that. The difference is that padarray(arr, Pad((1,1))) creates a new matrix with the padding, vs. BorderArray which is a view of the old one. One of these may be preferred depending on what you do next.

BTW both of them have unconventional indices, axes(A,1) == 0:3 in the above examples, rather than 1:4. Which means that the original pixels are at their original locations.

Great, thanks for pointing that out! That is quite important information.

I must say, the docs of that package are quite lacking.
I’ll probably make a PR to add some of these informations there.

To complement the links to existing solutions, the basic do it yourself implementation would be along these lines:

function padarray(a, p)
    h, w = size(a)
    y = clamp.((1 - p[1]):(h + p[1]), 1, h)
    x = clamp.((1 - p[2]):(w + p[2]), 1, w)
    return a[y, x]
end

(BorderArray is a lot smarter in terms of memory use, though.)

Just to build a bit on this, these are some quick test i made that may be useful depending on the situation on which one would want to use these functions

H = 1000
pad = 2
u = rand(H, H)
@btime padarray($u, Pad((pad, pad))) # 72.718 μs (21 allocations: 7.71 MiB)
@btime BorderArray($u, Pad((pad, pad))) # 193.989 ns (3 allocations: 112 bytes)

function test_access(u)
    for i in eachindex(u)
        u[i]
    end
end

u_pad = padarray(u, Pad((pad, pad)))
u_border = BorderArray(u, Pad((pad, pad)))

@btime test_access($u_pad); # 288.715 μs (0 allocations: 0 bytes)
@btime test_access($u_border); # 3.544 ms (0 allocations: 0 bytes)