Skip to content

Commit

Permalink
Further developmetn of colour handling
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeHughesKent committed Apr 25, 2023
1 parent 3152c4f commit 8a62f9b
Show file tree
Hide file tree
Showing 21 changed files with 277 additions and 44 deletions.
10 changes: 6 additions & 4 deletions docs/source/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ Instantiate a PyBundle object::

pyb = PyBundle()
To process an image ``img``, a 2D numpy array, we then use::
Let's assume we have an image ``img``, a 2D (monochrome) or 3D (colour) numpy array. If it is a colour images then the colour
channels are along the third axis. We then use::

procImage = pyb.process(img)

However, this will do nothing to the raw image unless we first set some parameters. Parameters can either be
set by passing optional arguments when instantiating the PyBundle object, or by calling setter methods. First we define what type of core-removal we would like, for example by passing arguments::
However, this will do nothing to the raw image unless we first set some processing options. Parameters can either be
set by passing optional arguments when instantiating the PyBundle object, or by calling setter methods.
First we define what type of core-removal we would like, for example by passing arguments::

pyb = PyBundle(coreMethod = pyb.FILTER, filterSize = 2.5)
Expand Down Expand Up @@ -159,7 +161,7 @@ To reconstruct an image ``img``, a 2D numpy array, we then call::

imgRecon = pybundle.recon_tri_interp(img, calib)

This returns a 2D numpy array of size ``(gridSize, gridSize)`` containing the image with the core pattern removed.
This returns a 2D/3D numpy array of size ``(gridSize, gridSize, colour channels)`` containing the image with the core pattern removed.

For all optional parameters refer to the :doc:`function reference<functions>` for ``calib_tri_interp`` and ``recon_tri_interp``.

14 changes: 7 additions & 7 deletions docs/source/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ A list of core functions is available below. Methods for the `Mosaic <mosaicing.

The pybundle class implements most of the functionality of the package and is the preferred approach for most applications.

PyFibreBundle uses numpy arrays as images throughout, wherever 'image' is specified this refers to a 2D numpy array.
PyFibreBundle uses numpy arrays as images throughout, wherever 'image' is specified this refers to a 2D (monochrome) or 3D (colour) numpy array. For colour images, the colour channels are along the third axis. There can be as many colour channels as needed.


^^^^^^^^^^^^^^
Expand All @@ -20,7 +20,7 @@ Instantiates an object of the PyBundle class. There are a large number of option

.. py:function:: process(img)

Process a raw image ``Img`` which should be a 2D numpy array. Returns a processed image as a 2D numpy array.
Process a raw image ``Img`` which should be a 2D/3D numpy array. Returns a processed image as a 2D/3D numpy array.

.. py:function:: calibrate()
Expand Down Expand Up @@ -48,15 +48,15 @@ Sets to automatically create a mask using the previously determined bundle locat

.. py:function:: set_background(background)
Stores an image to be used for background subtraction. ``background`` should be a 2D numpy array, the same size as the raw images to be processed.
Stores an image to be used for background subtraction. ``background`` should be a 2D/3D numpy array, the same size as the raw images to be processed.

.. py:function:: set_bundle_loc(loc)
Sets the stored location of the fibre bundle. ``loc`` is a tuple of (centreX, centreY, radius).

.. py:function:: set_calib_image(calibImg)
Stores the image to be used for calibration for TRILIN method. ``calibImg`` should be a 2D numpy array of the same size as images to be processed, ideally showing the bundle with uniform illumination.
Stores the image to be used for calibration for TRILIN method. ``calibImg`` should be a 2D/3D numpy array of the same size as images to be processed, ideally showing the bundle with uniform illumination.

.. py:function:: set_core_method(coreMethod)
Expand Down Expand Up @@ -88,7 +88,7 @@ Sets the mask to applied during processing to set areas outside bundle to 0. ``M

.. py:function:: set_normalise_image(normaliseImage)
Stores an image to be used for normalisation if TRILIN method is being used. ``normaliseImage`` should be a 2D numpy array, the same size as the raw images to be processed.
Stores an image to be used for normalisation if TRILIN method is being used. ``normaliseImage`` should be a 2D/3D numpy array, the same size as the raw images to be processed.

.. py:function:: set_output_type(outputType)
Expand All @@ -100,7 +100,7 @@ Enables super-resolution if ``superRes`` is ``True``, disables if ``False``.

.. py:function:: set_sr_calib_images(calibImages)
Provides the calibration images, a stack of shifted images used to determine shifts between images for super-resolution. ``calibImages`` is a 2D numpy array (x,y,nImages).
Provides the calibration images, a stack of shifted images used to determine shifts between images for super-resolution. ``calibImages`` is a 3D numpy array (x,y,nImages).

.. py:function:: set_sr_norm_to_images(normToImages)
Expand Down Expand Up @@ -226,7 +226,7 @@ Calibration for triangular linear interpolation between cores. This returns a Bu

Required arguments:

* ``img`` calibraton image (2D numpy array)
* ``img`` calibraton image (2D/3D numpy array)
* ``coreSize`` estimate core spacing to help with core finding.
* ``gridSize`` size of output image (square)

Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The package was originally developed for applications in endoscopic microscopy,
holographic endomicroscopy, but there are also potential applications in endoscopy.

The package supports fibre core pattern removal by filtering and triangular linear interpolation, background correction and
flat fielding, as well as automatic bundle location, cropping and masking.
flat fielding, as well as automatic bundle location, cropping and masking. Both monochrome and colour images can be processed.
The :doc:`PyBundle<pybundle_class>` class is the preferred way to access this functionality,
but the lower level functions can also be used directly for greater customisation.
The :doc:`Mosaic<mosaicing>` class provides mosaicing via normalised cross correlation,
Expand Down
11 changes: 8 additions & 3 deletions docs/source/linear_interp.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Linear Interpolation
====================================
Triangular linear interpolation can be used to remove the fibre bundle core pattern. Using a calibration image, usually acquired with no object in view (i.e. a flat field), the location of each core is determined. A Delaunay triangulation is performed over the core locations. A reconstruction grid is then defined, and the enclosing triangle for each pixel is determined. Images can then be processed by interpolating the value of each pixel from the brightness of the three surrounding cores. Although calibration can take a few seconds, processing of images can then be at video rate.
Triangular linear interpolation can be used to remove the fibre bundle core pattern.
Using a calibration image, usually acquired with no object in view (i.e. a flat field),
the location of each core is determined. A Delaunay triangulation is performed over the core locations.
A reconstruction grid is then defined, and the enclosing triangle for each pixel is determined.
Images can then be processed by interpolating the value of each pixel from the brightness of the three surrounding cores.
Although calibration can take a few seconds, processing of images can then be at video rate.


^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -16,7 +21,7 @@ Set the core removal method to triangular linear interpolation::

pyb.set_core_method(pyb.TRILIN)

Set both the calibration and normalisation images to be ``calibImg``, a 2D numpy array::
Set both the calibration and normalisation images to be ``calibImg``, a 2D/3D numpy array::

pyb.set_calib_image(calibImg)
pyb.set_normalise_image(calibImg)
Expand Down Expand Up @@ -58,7 +63,7 @@ The ``gridSize`` is the number of pixels in each dimensions of the reconstructed

Finally, we have specified to use the ``calibImg`` for normalisation. This means that the intensity extracted from each core during imaging will be normalised with respect to the intensity from the calibration image, removing effects due to non-uniform cores. If this is not done (i.e. normalise is left as the default ``None``) then images may appear grainy.

To reconstruct an image ``img``, a 2D numpy array, we then call::
To reconstruct an image ``img``, a 2D/3D numpy array, we then call::

imgRecon = pybundle.recon_tri_interp(img, calib)

Expand Down
11 changes: 8 additions & 3 deletions docs/source/mosaicing.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Mosaicing
====================================
The Mosaic class allows high speed mosaicing using normalised cross correlation to detect shifts between image frames, and either dead-leaf or alpha-blended insertion of images into a mosaic. The easiest way to use this functionality is to create an instance of ``Mosaic`` class and then use ``Mosaic.add(img)`` to sequentially register and add image ``img`` to the mosaic, and ``Mosaic.getMosaic()`` to get the latest mosaic image. Both ``img`` and the ``mosaic`` are 2D numpy arrays.
The Mosaic class allows high speed mosaicing using normalised cross correlation to detect shifts between image frames,
and either dead-leaf or alpha-blended insertion of images into a mosaic.
The easiest way to use this functionality is to create an instance of ``Mosaic`` class and then use ``Mosaic.add(img)`` to
sequentially register and add image ``img`` to the mosaic, and ``Mosaic.getMosaic()`` to get the latest mosaic image.
Both ``img`` and the ``mosaic`` are 2D (monochrome) or 3D (colour) numpy arrays.

^^^^^^^^^^^^^^^
Getting Started
Expand All @@ -17,7 +21,8 @@ Add an image ``img`` to the mosaic::
Request the latest mosaic image::

mosaicImage = mMosaic.getMosaic()

The ``mosaicImage`` will be a 2D numpy array if ``img`` is 2D and a 3D numpy array if ``img`` is 3D, in which case the third channel represents the colour channels.


^^^^^^^^^^^^^
Expand Down Expand Up @@ -57,7 +62,7 @@ Function Reference
Adds an image ``img`` to the current mosaic.

.. py:function:: get_mosaic()
Returns a copy of the current mosaic as a 2D numpy array.
Returns a copy of the current mosaic as a 2D/3D numpy array.

^^^^^^^^^^^^^^^^^^^^
Usage Notes
Expand Down
8 changes: 5 additions & 3 deletions docs/source/pybundle_class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
PyBundle class
----------------------
The PyBundle class is the recommended way to use most functionality of the package (other than Mosaicing which has its own class.)
The following gives a basic introduction to core removal using the class, to use the class for linear interpolation between cores, see the `Linear Interpolation Section <linear_interp.html>`_
The following gives a basic introduction to core removal using the class, to use the class for linear interpolation between cores,
see the `Linear Interpolation Section <linear_interp.html>`_
and to use it for Super Resolution processing see the `Super Resolution Section <super_res.html>`_

Import the class using::
Expand All @@ -17,7 +18,8 @@ The processing parameters are then set, before calling::

procImage = pyb.process(img)
to process an image ``img``, a 2D numpy array. This function returns a 2D numpy array as the processed image.
to process an image ``img``, a 2D/3D numpy array. This function returns a 2D/3D numpy array as the processed image. If 3D ararys are
used then the third axis represents the (typically 3) colour channels.

The processing parameters can be set using optional argument in the PyBundle constructor,
or using various setter methods. For example, if we want the processing to apply a Gaussian filter with a sigma of 2 pixels, we can use::
Expand All @@ -36,7 +38,7 @@ All methods support a background subtraction by specifying a background image, e

pyb.set_background(backgroundImg)
or including ``backgroundImage = backgroundImg`` in the constructor, where ``backgroundImg`` is a 2D numpy array the same size as ``img``.
or including ``backgroundImage = backgroundImg`` in the constructor, where ``backgroundImg`` is a 2D/3D numpy array the same size as ``img``.

Further examples of the settings relevant for filtering are in :doc:`Basic Processing<core>` and for TRILIN in :doc:`Linear Interpolation<linear_interp>`.

Expand Down
3 changes: 2 additions & 1 deletion docs/source/super_res.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ multiple images, with the object slightly shifted with respect to the fibre patt
sub-package of PyFibreBundle provides the ability to combine multiple images and generate an enhanced resolution
using triangular linear interpolation. As with single image triangular linear interpolation, calibation takes
several seconds, but reconstruction is fast. For most applications this functionality is best accessed via the
:doc:`PyBundle<pybundle_class>` class as shown below.
:doc:`PyBundle<pybundle_class>` class as shown below. This functionality is currently only available for
monochrome images.

^^^^^^^^^^^^^^^^
Getting Started
Expand Down
65 changes: 65 additions & 0 deletions examples/linear_interp_colour_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
"""
Example of removal of fibre bundle core pattern from colour images by
Delaunay triangulation and triangular linear interpolation.
@author: Mike Hughes
Applied Optics Group
University of Kent
"""

from matplotlib import pyplot as plt
import numpy as np
import time

from PIL import Image

import context # Add relative path to get PyBundle

import os
import pybundle
from pybundle import PyBundle

# We load in two images, an image with uniform illumination for calibation
# and a image of letters to demonstrate core removal
img = np.array(Image.open(r"..\test\data\bundle_colour_1.tif"))
calibImg = np.array(Image.open(r"..\test\data\bundle_colour_1_background.tif"))


# Parameters for reconstruction
coreSize = 3 # Estimated core size used when searching for cores
gridSize = 512 # Number of pixels in reconstructed image
filterSize = None # Pre-Gaussian filter sigma


pyb = pybundle.PyBundle(coreMethod = PyBundle.TRILIN,
calibImage = calibImg,
normaliseImage = calibImg,
coreSize = 3,
gridSize = 512)

# One-time calibration
t1 = time.perf_counter()
pyb.calibrate()
t2 = time.perf_counter()
print('Calibration took:', round(t2-t1,3),'s')

# Image reconstruction without Numba
imgRecon = pyb.process(img)
t1 = time.perf_counter()
imgRecon = pyb.process(img)
t2 = time.perf_counter()
print('Reconstruction took:', round(t2-t1,4),'s')

# Display reconstructed image
plt.figure(dpi = 300)
plt.imshow(img, cmap='gray')
plt.title('Raw Image')
plt.show()

# Display reconstructed image
plt.figure(dpi = 300)
plt.imshow(imgRecon / 1024, cmap='gray')
plt.title('Reconstruction by interpolation')
plt.show()

2 changes: 1 addition & 1 deletion examples/linear_interp_example.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
Simple example of how to use PyFibreBundle to remove core pattern.
Simple example of how to use PyBundle class f PyFibreBundle to remove core pattern.
@author: Mike Hughes
Applied Optics Group
Expand Down
Loading

0 comments on commit 8a62f9b

Please sign in to comment.