Kernel interpolation for concentration#

When a dye traces a curved path through colour space as its concentration changes, a linear model is not enough. KernelInterpolation learns the signal-to-concentration map from a handful of labelled samples.

The images come from a water-tracer experiment with a multi-coloured indicator (green ~100 %, blue ~0 %); they have been cropped and down-sampled for storage.

import os

import matplotlib.pyplot as plt
import numpy as np
import skimage

import darsia

folder = os.path.join("..", "images")
baseline = darsia.imread(os.path.join(folder, "kernel_interpolation_example_base.npz"))
image = darsia.imread(os.path.join(folder, "kernel_interpolation_example_test.npz"))

Start with a model-free concentration analysis: just the TV-denoised difference to the baseline.

analysis = darsia.ConcentrationAnalysis(
    base=baseline,
    restoration=darsia.TVD(
        weight=0.025, eps=1e-4, max_num_iter=100, method="isotropic Bregman"
    ),
    **{"diff option": "plain"},
)
/home/runner/work/DarSIA/DarSIA/src/darsia/multi_image_analysis/concentrationanalysis.py:86: UserWarning: The baseline image needed to be converted to float for substraction.
  warn(

Pick a few sample windows with known concentrations. Interactively this would be BoxSelectionAssistant; here the windows are hard-coded.

samples = [
    (slice(15, 40), slice(20, 45)),
    (slice(15, 40), slice(220, 245)),
    (slice(15, 40), slice(420, 445)),
    (slice(15, 40), slice(720, 745)),
]
n = len(samples)
concentrations = 100 * np.append(np.linspace(1, 0.99, n - 1), 0)

Extract the characteristic colour of each sample and fit a Gaussian-kernel interpolation, clipped at 100 %.

  • plot kernel interpolation
  • plot kernel interpolation
/home/runner/work/DarSIA/DarSIA/src/darsia/multi_image_analysis/concentrationanalysis.py:252: UserWarning: The input for concentration analysis needed to be converted to float.
  warn(
/home/runner/work/DarSIA/DarSIA/src/darsia/utils/extractcharacteristicdata.py:173: RuntimeWarning: Assuming data is color data and using RGB as axes.
  warn("Assuming data is color data and using RGB as axes.", RuntimeWarning)

Apply the calibrated analysis and visualise the result.

concentration_image = analysis(image).img

plt.figure("concentration profile")
plt.plot(np.average(concentration_image, axis=0))
plt.xlabel("horizontal pixel")
plt.ylabel("concentration [%]")

fig = plt.figure()
fig.suptitle("image and resulting concentration")
ax = plt.subplot(211)
ax.imshow(skimage.img_as_ubyte(image.img))
ax.set_axis_off()
ax = plt.subplot(212)
im = ax.imshow(concentration_image)
ax.set_axis_off()
fig.colorbar(im, orientation="horizontal", label="concentration [%]")
plt.show()
  • plot kernel interpolation
  • image and resulting concentration

Total running time of the script: (0 minutes 6.586 seconds)

Gallery generated by Sphinx-Gallery