Animation images and dataframe content

I have multiple images stacked into an array:

using CairoMakie
using Images
using DataFrames
using DataFramesMeta

# Load cow
img_orig = load(Makie.assetpath("cow.png"))
img_filt1 = imfilter(img_orig, Kernel.gaussian(3))
img_filt2 = imfilter(img_orig, Kernel.gaussian(30))
img_filt3 = imfilter(img_orig, Kernel.gaussian(300))
img_bw = Gray.(img_orig)

# Combine
img_array = [img_orig;;; img_filt1;;; img_filt2;;; img_filt3;;; img_bw]

and a data frame with x and y coordinates as well as a colour and a frame column s.t.

df = DataFrame(x=rand(1:400, 10), y=rand(1:300, 10), c=rand(10), f=rand(1:5, 10))

Now, I want to create an animation (i.e. time lapse movie) where each frame corresponds to an image in the array overlayed with dots defined by the dataframe. So far I have the following but cannot figure out how to properly animate, record and save it.

frame_i = Observable(1)

df_i = @lift(@rsubset(df, :f == $frame_i))
img_i = @lift(img_array[:, :, $frame_i])

# Plot
function _plt_fig(frame)

    frame_i[] = frame
    fig = Figure()
    ax = CairoMakie.Axis(fig[1, 1])

    image!(ax, rotr90(img_i.val))
    scatter!(ax, df_i.val.x, df_i.val.y, color=df_i.val.c, markersize=30)

    return fig
end

Any help would be greatly appreciated.

For saving as a video I think VideoIO.jl would help

1 Like

Thanks @johnh. With VideoIO.save I could save an image stack to .mp4 for instance.
Which brings me to another way to approach this problem.

I could also flatten the dataframe data into the image such that I get one new image from this and save these to a new stack and write them out to a video. I, however, also do not know how to do this “flattening”.

Alright… I’ve figured it out:

using CairoMakie
using Images
using DataFrames
using DataFramesMeta

# Load cow
img_orig = load(Makie.assetpath("cow.png"))
img_filt1 = imfilter(img_orig, Kernel.gaussian(3))
img_filt2 = imfilter(img_orig, Kernel.gaussian(30))
img_filt3 = imfilter(img_orig, Kernel.gaussian(300))
img_bw = Gray.(img_orig)

# Combine
img_array = [img_orig;;; img_filt1;;; img_filt2;;; img_filt3;;; img_bw]

# Data
df = DataFrame(x=rand(1:400, 10), y=rand(1:300, 10), c=rand(10), f=rand(1:5, 10))

frame_i = Observable(1)

df_i = @lift(@rsubset(df, :f == $frame_i))
img_i = @lift(img_array[:, :, $frame_i])

fig = Figure()
ax = CairoMakie.Axis(fig[1, 1])

# Plot
function _plt_fig!(frame)

    frame_i[] = frame
    image!(ax, rotr90(img_i.val))
    scatter!(ax, df_i.val.x, df_i.val.y, color=df_i.val.c, markersize=30)
    return fig
end

frames = 1:5
record(fig, "video.mp4", frames; framerate=1) do i
        _plt_fig!(i)
end