Image stitching with ImageStitcher
Fordyce Lab, 2020
Author: Daniel Mokhtari
ImageStitcher is a simple package for flat-field correcting, stitching, and background subtracting rastered image tiles acquired via MicroManager or RunPack.
This guide assumes that you have (1) set up a anaconda virtual environment with Python ≥ 3.6), (2) installed the iPython kernel and Jupyter, and (3) registered your environment with your installation of jupyter. Instructions on how to do this can be found here, here, and here.
i. Activate a Conda virtual environment configured with an iPython kernel registered with Jupyter in a terminal session
- Download the ImageStitcher zip (private) from the FordyceLab Github
- Change directory to unzipped package path
$ cd /repo-download-dir
- PIP install the package in place and make editable
$ pip install -e .
iii. Launch the example notebook from your Jupyter session
First, we need to define parameters to desribe what the images look like, how the raster was acquired (which corner of the rastered region did the imaging start at?), and load any necessary flat-field correction images and parameters. Reference free flat-field corrections are also possible, but not implemented here.1
a. Define any needed flat-field images and parameters
# Flat field image path
setup_eGFP_ffPath = '/Setup2_FF_eGFP_500ms_2x2.tif'
# Flat-field fit parameters {channel_1: {exposure_t_1: (D, m), exposure_t_2: (D, m), ...},
# channel_2: {exposure_t_1: (D, m), exposure_t_2: (D, m), ...}
# }
# With empirically fit parameters
# D = fit dark field value (flat)
# m = image average of F-D where F = flat-field image
setup_ffParams = {'4egfp': {500: (-150, 16665)}}
Note:
- Flat-field image must be the same dimension (binning) as target images to be corrected
- Exposure times for FF parameters are in ms, and must match the target images
b. Instantiate a StitchingSettings object
settings = stitcher.StitchingSettings(ffPaths = {'4egfp': setup_eGFP_ffPath},
ffParams = setup_ffParams,
setupNum= 2,
tileDim = 1024
)
# Or if no flat-field images/parameters
settings = stitcher.StitchingSettings(setupNum= 2, tileDim = 1024)
Note:
- The setupNum defines the raster origin and pattern, as this differs among setups
- tileDim is the width or height of the target image. ImageStitcher assumes that the images are
RunPack derived images are flat rasters (not stacked) with embedded metadata including acquisition time, raster position, etc.. These images are either collected as single scans ("single"), or kinetic time series ("kinetic"). ImageStitcher treats these classes of imaging slightly differently when stitching (saves the images at different levels of the hierarchy) to facilitate pipelining in downstream applications. The structure of these images, common to both scans and kinetic acquisitions, is shown below
Structure
parent-root
+-- channel-1
» +-- YYYYmmdd-HHMMSS_Description_channel-1
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- ...
» +-- 1-Pos_XXX_YYY_ExposureT-2.tif
» +-- 1-Pos_XXX_YYY_ExposureT-2.tif
» +-- ...
» +-- YYYYmmdd-HHMMSS_Description_channel-1
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- ...
» +-- 1-Pos_XXX_YYY_ExposureT-2.tif
» +-- 1-Pos_XXX_YYY_ExposureT-2.tif
» +-- ...
» ...
+-- channel-2
» +-- YYYYmmdd-HHMMSS_Description_channel-2
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- ...
» +-- 1-Pos_XXX_YYY_ExposureT-2.tif
» +-- 1-Pos_XXX_YYY_ExposureT-2.tif
» +-- ...
» +-- YYYYmmdd-HHMMSS_Description_channel-2
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- 1-Pos_XXX_YYY_ExposureT-1.tif
» +-- ...
» ...
...
Usage
multiImagePath = '/parent-root' #or higher
overlap = 0.1
p = stitcher.RasterParams(overlap, autoFF = True)
stitcher.walkAndStitch(multiImagePath, p, stitchtype = 'kinetic')
# Alternate stitchtype = 'single'
multiImagePath: (str | pathlib.Path | path-like object) path to the root of the imaging directory structure
overlap: (float) fractional overlap of tiled images [0–1)
autoFF: (bool) flag for automatically applying flat-field corrections, as defined in the stitcher.StitchingSettings
stitchtype: (str: "single" | "kinetic") type of stitching to perform (dictates stitched image out path). If stitching a time series, use "kinetic". Else, use "single".
Micro-Manager can export and convert between flat and stacked images. For simplicity, ImageStitcher only supports stitching the stacked .ome.tif Micro-Manager images. If you collected flat rasters, convert them to stacks using Micro-Manager before proceeding.
Structure (all exposure times and channels are stacked)
parent-root
+-- Description_1_MMStack_1-Pos_XXX_YYY.ome.tif
+-- Description_1_MMStack_1-Pos_XXX_YYY.ome.tif
...
Usage
root = '/stack-parent'
overlap = 0.1
# Channel names from MicroManager configuration
channelExposureMap = {'3-GFP-B': 500, '5------': 100}
# Remap the names of the channels for saved filenames, if desired
channelRemap = {'3-GFP-B': '3-GFP-B', '5------': 'Cy5'}
p = stitcher.RasterParams(overlap, autoFF = False)
stitcher.MMStitchStacks(root,
p,
channelExposureMap,
channelRemap = channelRemap
)
root: (str | pathlib.Path | path-like object) root of the image stacks
overlap: (float) fractional overlap of tiled images [0–1)
channelExposureMap: (dict) Micro-Manager metadata doesn't retain exposure times, so you need to specify these as a dictionary. Note that Micro-Manager also doesn't permit the same channel name to have more than one exposure time per stack, giving rise to the dict structure shown.
channelRemap: (dict) Micro-Manager default channel names may not be descriptive for naming purposes, so remap them if required.
autoFF: (bool) flag for automatically applying flat-field corrections, as defined in the stitcher.StitchingSettings
Description: In ImageStitcher, background subtraction is performed on the full stitched images. This is easily done by 1) storing the reference/background images and their channels/exposures, and 2) specifying the highest level of the directory structure to walk down and perform background subtractions of all stitched images of corresponding parameters
Set up reference images
bg = stitcher.BackgroundImages()
# Reference background images
backgroundsRootD1 = 'd1-parent/StitchedImg_500_4egfp_0.tif'
backgroundsRootD2 = 'd2-parent/StitchedImg_500_4egfp_0.tif'
device_1 = 'd1'
device_2 = 'd2'
reference_channel = '4egfp'
reference_exposure = 500 #ms
bg.add(backgroundsRootD1, device_1, reference_channel, exposure)
bg.add(backgroundsRootD1, device_2, reference_channel, exposure)
Execute
target = '/root-path'
target_device = 'd1'
target_channel = '4egfp'
bg.walkAndBGSubtract(targetRoot, target_device, channel)
1 Peng, T., Thorn, K., Schroeder, T. et al. A BaSiC tool for background and shading correction of optical microscopy images. Nat Commun 8, 14836 (2017) doi:10.1038/ncomms14836