# How to use dilate in Julia

Hi! I am looking for something similar to python’s dilation function in skimage.morphology. I want to achieve precisely the following functionality:

``````>>> import numpy as np
>>> from skimage.morphology import dilation
>>> from skimage.morphology import disk

>>> bright_pixel = np.array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]], dtype=np.uint8)
>>> dilation(bright_pixel, disk(1))
array([[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0]], dtype=uint8)
``````

Can you suggest how to implement the same in Julia?

Images.jl’s morphology tools currently only allow operations on rectangular windows (see https://github.com/JuliaImages/ImageMorphology.jl/issues/11). If a rectangular window is acceptable,

``````julia> using Images

julia> bright_pixel = zeros(Gray{N0f8}, 5, 5); bright_pixel[3,3] = 1;

julia> dilate(bright_pixel)
5×5 Array{Gray{N0f8},2} with eltype Gray{Normed{UInt8,8}}:
Gray{N0f8}(0.0)  Gray{N0f8}(0.0)  …  Gray{N0f8}(0.0)  Gray{N0f8}(0.0)
Gray{N0f8}(0.0)  Gray{N0f8}(1.0)     Gray{N0f8}(1.0)  Gray{N0f8}(0.0)
Gray{N0f8}(0.0)  Gray{N0f8}(1.0)     Gray{N0f8}(1.0)  Gray{N0f8}(0.0)
Gray{N0f8}(0.0)  Gray{N0f8}(1.0)     Gray{N0f8}(1.0)  Gray{N0f8}(0.0)
Gray{N0f8}(0.0)  Gray{N0f8}(0.0)     Gray{N0f8}(0.0)  Gray{N0f8}(0.0)

julia> Int.(ans)
5×5 Array{Int64,2}:
0  0  0  0  0
0  1  1  1  0
0  1  1  1  0
0  1  1  1  0
0  0  0  0  0
``````
1 Like

I tried using the same function but I couldn’t find how to specify squares for dilation. For instance, can you tell me how do I modify the above code to get dilation of mode than one pixel on each side?

Sorry, I assumed it allowed rectangular windows, but all you can do is include/exclude dimensions from dilation:

``````help?> dilate

imgd = dilate(img, [region])

perform a max-filter over nearest-neighbors. The default is 8-connectivity
in 2d, 27-connectivity in 3d, etc. You can specify the list of dimensions
that you want to include in the connectivity, e.g., region = [1,2] would
exclude the third dimension from filtering.
``````

You could instead use `mapwindow` as follows:

``````julia> mapwindow(maximum, bright_pixel, (3, 5))
5×5 Array{Gray{N0f8},2} with eltype Gray{Normed{UInt8,8}}:
Gray{N0f8}(0.0)  Gray{N0f8}(0.0)  …  Gray{N0f8}(0.0)  Gray{N0f8}(0.0)
Gray{N0f8}(1.0)  Gray{N0f8}(1.0)     Gray{N0f8}(1.0)  Gray{N0f8}(1.0)
Gray{N0f8}(1.0)  Gray{N0f8}(1.0)     Gray{N0f8}(1.0)  Gray{N0f8}(1.0)
Gray{N0f8}(1.0)  Gray{N0f8}(1.0)     Gray{N0f8}(1.0)  Gray{N0f8}(1.0)
Gray{N0f8}(0.0)  Gray{N0f8}(0.0)     Gray{N0f8}(0.0)  Gray{N0f8}(0.0)

julia> Int.(ans)
5×5 Array{Int64,2}:
0  0  0  0  0
1  1  1  1  1
1  1  1  1  1
1  1  1  1  1
0  0  0  0  0
``````
1 Like

Thanks for your pointer. I think I can work with this for now. However, do you have an idea how to implement the max filter in case I want to implement it myself? Any pointer in that direction will be helpful.

You can always inspect how Julia’s functions are implemented with `@edit`, e.g. `@edit dilate(bright_pixel)`. You may want to look at `StaticKernels.jl` or `LoopVectorization.jl` if you need a particular dilation region.

``````julia> using StaticKernels

julia> k = StaticKernels.Kernel{(-1:1, -2:2)}(w -> maximum(Tuple(w)))
Kernel{(-1:1, -2:2)} with window function #13

julia> map(k, extend(bright_pixel, StaticKernels.ExtensionNothing())) .|> Int
5×5 Array{Int64,2}:
0  0  0  0  0
1  1  1  1  1
1  1  1  1  1
1  1  1  1  1
0  0  0  0  0
``````

Can you post a MWE? It works fine for me:

``````julia> bright_pixel = zeros(N0f8, 5300, 3050); bright_pixel[3,3] = 1;

julia> mapwindow(maximum, bright_pixel, (3, 5))
5300×3050 Array{N0f8,2} with eltype Normed{UInt8,8}:
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  1.0  1.0  1.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  1.0  1.0  1.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
1.0  1.0  1.0  1.0  1.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
⋮                        ⋮              ⋱            ⋮
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0
0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0``````

I did not assign the value to any variable and was losing the progress. I thought mapwindow changed the array in place. My bad.

If you have binary images you can emulate dilation with linear filtering.

``````using ImageFiltering
kernel = centered([0 1 0;1 1 1;0 1 0])
dilated = imfilter(bright_pixel, kernel) .> 0
``````
1 Like

There is a `dilate` function doing exactly what you need in `LocalFilters.jl`: `dilate(array, 5)` for a rectangular kernel of size 5, or `dilate(array, kernel)` for an arbitrary kernel that is represented as an array.

1 Like