Preprocessing images#

There are two main methods to preprocess images with Fluidimage:

  1. with user-defined preprocessing functions or classes, or

  2. with pre-defined preprocessing classes.

For both methods, we use a Work class to try parameters and a Topology class to apply this work in parallel on a large serie of images. See the Overview of the package for an explanation about this terminology.

1. User-defined preprocessing#

Let’s assume that you have a function or a class which gets an image as argument and returns a new image. If it is importable, you can use Fluidimage to first investigate which are the better parameters for your case:

from fluidimage.image2image import Work

params = Work.create_default_params()

# for a function:
# params.im2im = 'fluidimage.image2image.im2im_func_example'

# for a class (with one argument for the function init):
params.im2im = "fluidimage.image2image.Im2ImExample"
params.args_init = ((1024, 2048), "clip")

params.images.path = "../../image_samples/Jet/Images/c*"
params.images.str_subset = "60:,:"

work = Work(params)

work.display()

and then process a large serie of images in parallel with the class fluidimage.image2image.Topology.

"""This example shows how to plug user-defined functions or classes that
process an image with a fluidimage topology (which process several images).

The user has to write an importable function (or class) processing one image
(see {mod}`fluidimage.image2image`).

Here, we use a class defined in fluidimage
(`fluidimage.image2image.Im2ImExample`), but it can be any
importable class!

"""

from fluidimage.image2image import Topology

params = Topology.create_default_params()

# for a function:
# params.im2im = 'fluidimage.image2image.im2im_func_example'

# for a class (with one argument for the function init):
params.im2im = "fluidimage.image2image.Im2ImExample"
params.args_init = ((1024, 2048), "clip")

params.images.path = "../../image_samples/Jet/Images/c*"

params.saving.postfix = "im2im_example"
params.saving.how = "recompute"

topo = Topology(params)

topo.compute()

assert len(topo.results) == 4

2. Pre-defined preprocessing classes#

Fluidimage also provides pre-defined preprocessing classes to apply many standard preprocessing to images.

Preprocessing one serie#

To find the good parameter, you can use the class fluidimage.preproc.Work (see also fluidimage.preproc).

from fluidimage.preproc import Work

params = Work.create_default_params()

params.series.path = "../../image_samples/Karman/Images"
print("Available preprocessing tools: ", params.tools.available_tools)

params.tools.sequence = ["sliding_median", "global_threshold"]
params.tools.sliding_median.enable = True
params.tools.sliding_median.window_size = 25

params.tools.global_threshold.enable = True
params.tools.global_threshold.minima = 0.0
params.tools.global_threshold.maxima = 255.0

preproc = Work(params)

preproc.display(1, hist=False)

Preprocessing large series of images#

To apply the preprocessing to a large serie of images in parallel, use fluidimage.preproc.Topology.

from fluidimage import get_path_image_samples
from fluidimage.preproc import Topology

params = Topology.create_default_params()

params.series.path = get_path_image_samples() / "Jet/Images"
params.series.str_subset = "i,:"

p_tools = params.tools

print("Available preprocessing tools: ", p_tools.available_tools)
p_tools.sequence = ["temporal_median", "sliding_median", "global_threshold"]
print("Enabled preprocessing tools: ", p_tools.sequence)

p_tools.sliding_median.enable = True
p_tools.sliding_median.weight = 0.5
p_tools.sliding_median.window_size = 10

p_tools.temporal_median.enable = False
p_tools.temporal_median.weight = 0.5
p_tools.temporal_median.window_shape = (5, 2, 2)

p_tools.global_threshold.enable = True
p_tools.global_threshold.minima = 0.0

params.saving.how = "recompute"
params.saving.postfix = "pre_example"

topology = Topology(params, logging_level="info", nb_max_workers=4)

# Compute in parallel
topology.compute()

# Compute in sequential (for debugging)
# topology.compute(sequential=True)

assert len(topology.results) == 2