Making voxels isotropic in (x,y,z) images

Hi everyone,

I’ve started using Julia for processing microscopy data very recently (switching over from Python). My data tend to be 3D in space (meaning vertical stacks of images) and anisotropic (resolution in z is lower than in xy, due to, among other things, sampling). In Python, I make these stacks isotropic using scipy’s affine_transform function (scipy.ndimage.affine_transform — SciPy v1.12.0 Manual); if one knows the necessary shape of the image after interpolation (i.e., with isotropic coordinates), then this can be applied straightforwardly. I have not been able to find a similar functionality in Julia. Does anyone have any suggestions? Maybe something similar is already implemented? I couldn’t find anything similar in the Images packages. Thanks!

1 Like

Perhaps you want to visualize a 3D grid with well-defined spacing. Check the GDSJL book for more info on how to create grids and visualize properties over it with Makie.jl:

https://juliaearth.github.io/geospatial-data-science-with-julia

1 Like

If you are looking for affine transforms, CoordinateTransformations.jl or ImageTransformations.jl may be what you need.

https://juliaimages.org/ImageTransformations.jl/stable/

Also see this recording of the image processing workshop from JuliaCon 2023:

@tim.holy , the presenter, also happens to be a microscopist. You might find some of his lab’s packages useful as well.

@RainerHeintzmann and his lab group also have some microscopy utilities available:

2 Likes

Here is practical example:

julia> using Meshes

julia> grid = CartesianGrid(10,10,10)
10×10×10 CartesianGrid{3,Float64}
  minimum: Point(0.0, 0.0, 0.0)
  maximum: Point(10.0, 10.0, 10.0)
  spacing: (1.0, 1.0, 1.0)

julia> sgrid = grid |> Scale(1,2,3)
10×10×10 CartesianGrid{3,Float64}
  minimum: Point(0.0, 0.0, 0.0)
  maximum: Point(10.0, 20.0, 30.0)
  spacing: (1.0, 2.0, 3.0)

julia> import GLMakie as Mke

julia> viz(grid, color = 1:1000)

image

julia> viz(sgrid, color = 1:1000)

image

1 Like

You could take a look at GitHub - SciML/DataInterpolations.jl: A library of data interpolation and smoothing functions, which ought to give you what you need. I believe this should also handle irregular z sampling (1, 2, 4, 5, 8, …) but you could then interpolate in a pretty straightforward way.

1 Like

Thanks for the responses everyone! I’ll post here if I find a solution using any of the suggested packages.

A convenient solution is the imresize function in the ImageTransformations package; it can perform the necessary upsampling along z given the aspect ratio of xy to z.

1 Like

You might also want to look into WarpedView. Instead of upsampling the entire volume eagerly, you just upsample on demand. This may be useful if you are dealing with large images with limited memory.

Just for reference, how large are your image stacks? I’m just trying to understand the scale of the problem.

1 Like

thanks for the suggestion! That indeed looks interesting. I’ll have to think about whether memory allocation is necessary for all the downstream analyses after making the voxels isotropic. The images aren’t that massive (at least compared to some other datasets I’ve seen) – at the most the dimensions would be something like 500x500x100 (anisotropic) voxels per image. But the data are also coming from a timelapse of up to 100 frames, so memory can occasionally be an issue.

Also I wanted to point out that we do have a forum section over at image.sc: Topics tagged juliaimages in case you wanted to discuss this in a software agnostic fashion. I deal with problem a fairly frequently since I work with many people who with ImageJ and FIJI.