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 (https://www.mathworks.com/help/images/ref/padarray.html) 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

1 Like
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 https://github.com/JuliaArrays/PaddedViews.jl

2 Likes

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.

1 Like

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

1 Like

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.

1 Like

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.)

2 Likes

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)