Basic Image Processing

PyFibreBundle includes functions for basic processing of bundle images, including locating, cropping and masking the bundle and removing the core pattern using spatial filtering or linear interpolation between cores. Both monochrome and colour images are supported. Monochrome images are stored as 2D numpy arrays and colour images are stored as 3D numpy arrays, with the colour channels along the third axis (any number of colour channels is allowed). Image types explicitly supported are uint8, uint16, float32 and float64.

The recommended way to use this functionality is via the PyBundle class, but it is also possible to use the low level functions directly.

Full examples are available on Github for spatial filtering and linear interpolation.

Getting Started

Begin by importing the PyBundle class:

from pybundle import PyBundle

We then instantiate a PyBundle object:

pyb = PyBundle()

Let’s assume we have an image stored in img, a 2D (monochrome) or 3D (colour) numpy array. If the image is colour then the colour channels are along the third axis.

In general, to process an image we use:

procImage = pyb.process(img)

However, this will do nothing to the raw image unless we first set some processing options, either by passing optional arguments when creating the PyBundle object, or by calling setter methods on the object after creation.

Filtering

First we define what type of core-removal we would like, for example for Gaussian filtering with a sigma of 2.5, we pass:

pyb = PyBundle(coreMethod = PyBundle.FILTER, filterSize = 2.5)

or equivalently:

pyb = PyBundle()
pyb.set_core_method(PyBundle.FILTER)   # Choose to use a Gaussian filter
pyb.set_filter_size(2.5)               # Gaussian filter sigma is 2.5 pixels

If we then call:

procImage = pyb.process(img)

then procImage will be a Gaussian filtered version of img.

The other two options for core removal are PyBundle.TRILIN, for triangular linear interpolation, and PyBundle.EDGE_FILTER to use a custom edge filter.

See the Linear Interpolation page for details on how to perform linear interpolation.

The edge filter is a spatial frequency domain filter that seeks to cut off higher spatial frequencies includes those that correspond to the cores. It is used similarly to the Gaussian filter, except that the filter size is defined by passing edgeFilterSize = (pos, slope) or calling:

set_edge_filter_size(pos, slope)

where pos the defines the position of the cut-off and slope defines the steepness of the cut-off. pos should typically be around twice the core spacing and slope around 10% of this.

As for the Gaussian filter, the best speed is achieved by setting a calibration image and then calling calibrate(); the edge filter will be generated at this point.

Background and Normalisation

We can provide images which will be used for background subtraction and normalisation (flat-fielding). Essentially, an image provided as background will be subtracted from the raw image to be processed, and the raw image will be divided by the normalisation image (the exact implementation depends on the core processing method).

If we have a background image in the numpy array backImg, then to set the background image, pass background = backImg or call:

pyb.set_background(backimg)

To set a normalisation image stored in normImg, pass normaliseImage = normImg or call:

pyb.set_normalise_image(normImg)

Existing backgrounds/normalisations can be cleared by passing None to these functions.

Cropping

If we are using FILTER or EDGE_FILTER core removal methods, we might also want to crop the image to the size of the bundle (this happens intrinsically for TRILIN). Cropping can be set to happen automatically by passing crop = True e.g.

pyb = PyBundle(coreMethod = PyBundle.FILTER, filterSize = 2.5, crop = True)

In this case, when process() is called, PyBundle will attempt to locate the bundle and crop the image to a square just enclosing the bundle.

This is inefficient when processing multiple images from the same imaging setup, as the bundle location routine will run each time we call process(). It is faster to determine the location once from a calibration image, which is ideally an image with uniform illumination of the bundle (although it could also be one of the images to be processed).

Set the calibratation image by passing calibImage = calibImg or by calling:

pyb.set_calib_image(calibImg)

where calibImg is a 2D/3D numpy array containing the calibration image. The calibration image should be the same size as the images to be processed.

Optionally, we can then call:

pyb.calibrate()

and PyBundle will calculate and store the location of the bundle. If calibrate() is not called then the calibration image will still be used to find the bundle for cropping when pyb.process() is called for the first time. The bundle location will then be stored for future use.

Alternatively, we can explicitly tell PyBundle the location of the bundle in advance, either by passing loc = location or by calling:

pyb.set_loc(location)

where location is a tuple of (centre_x, centre_y, radius).

Masking

If we are using FILTER or EDGE_FILTER core removal methods, we might also want to set pixels outside the bundle to 0 (this happens intrinsically for TRILIN). This masking can be set to happen automatically by passing applyMask = True, e.g.

pyb = PyBundle(coreMethod = PyBundle.FILTER, filterSize = 2.5, applyMask = True)

As for cropping, PyBundle will generate a mask automatically each time we call pyb.calibrate() on an image which is generally not efficient. Again, it often better to generate the mask based on a calibration image in the same way as for cropping, i.e. by passing calibImage = calibImg. Calling:

pyb.calibrate()

will then allow the mask to be generated in advance, otherwise it will be created the first time we call pyb.process().

Image Type and Autocontrast

The default image output type is 'float64', this can be changed by passing, for example outputType = 'uint8' when creating the PyBundle object, or by calling

pyb.set_output_type('uint8')      # Output images will be 8 bit

where 'uint8', 'uint16', 'float32' or 'float64' can be used. The output will simply be cast to this format without any scaling, unless we pass autoContrast = True or set:

pyb.set_auto_contrast(True)

in which case the image will be first scaled to between 0 and 255 if an 8 bit output type is set, or between 0 and 65535 if a 16 bit output type is set, or between 0 and 1 if a floating point output type is set.

Examples

Gaussian filtering: examples/filtering_example.py.

Linear interpolation: examples/linear_interp_example.py.

Colour Gaussian filtering: examples/filtering_colour_example.py.

Colouor Linear interpolation: examples/linear_interp_colour_example.py.