Skip to content

Achieving high stitching accuracy

Rob Campbell edited this page Sep 2, 2019 · 11 revisions

Achieving high stitching accuracy

Data will be stitched using StitchIt. StitchIt assembles stitched sections out of individual tiles by placing images according to their position in the image grid and the number of microns per pixel of the images. If the number of microns per pixel is not accurate, the tile placement will also not be accurate. Furthermore, StitchIt will assume images are undistorted and that the stage motions are perfectly in line with the scan axes. Deviations from the above will cause imperfections in stitching accuracy. These instructions explain how to create tweaked microns per pixel values and correct for any image distortion prior to stitching.

It assumed that you have already:

You will need to install StitchIt before proceeding.

Measuring and correcting for image distortion

Acquire a uniform EM grid. Part number 2145C from 2spi works well. This grid has a pitch of 25 microns, a hole width of 19 microns, and a bar width of 6 microns. Place the grid on a slide and seal with a coverslip and nail varnish. Image the grid at low power: the copper will auto-fluoresce under a 2-photon laser. Align the grid with the image axes. Use a higher image resolution (1 micron per pixel should do). This will make easiest to see any barrel or pincushion distortion. Inspect the image. If you see noticeable distortion then do the following:

  1. Right click on the channel window and copy the image to the base workspace.
  2. The stitchit.tools.lensdistort command to correct for the distortion. e.g. see what imagesc(stitchit.tools.lensdistort(ImageData,0.2)) looks like. You will need to experiment and see the function help: note that k can be vector.

Once you have settings that look reasonable to the eye, note down the values.

Modify the scan settings file so it contains these numbers under a field called lensDistort. You will also want to add the fields affineMat and stitchingVoxelSize to handle shear and to get exact numbers for the stitching accuracy. File an issue if you need help with this now. Docs to come.

 setB:
  objective: nikon16x
  pixelsPerLine: 750
  linesPerFrame: 750
  zoomFactor: 1.0
  nominalMicronsPerPixel: 1.667
  fastMult: 1
  slowMult: 1
  objRes: 53.44
  lensDistort: {rows: 0, cols: 0.03}
  affineMat: 
    - [1, -0.014,   0]
    - [0.0,    1,   0]
    - [0,      0,   1]
  stitchingVoxelSize: {X: 0.673, Y: 0.658}

You will likely need to repeat the measurements for different zoom values but not for different image resolutions.

Tweaking the number of microns per pixel

Acquire a small tile of scan of a sample with structure. Agar with dissolved fluorescent marker pen will do. You can acquire just one small 9 by 9 grid with one section and one optical plane. Make sure you uncheck the boxes to turn off the laser and to slice. The laser box you will have to uncheck after the acquisition starts. Use imaging settings where you have entered a lensDistort value in the yml if needed. Once the acquisition is done you can verify that indeed you can see the lensDistort value in the recipe yml file. Stitch the data with chessboard stitching. e.g.

stitchSection([1,1],2,'chessboard',1,'overwrite',1)

Visualise and look at the overlap regions. If you see too much overlap you need to decrease the number of microns per pixel. Too little overlap means you need to increase it. The settings you need to change are:

StitchingParameters: 
  VoxelSize: {X: 1.2212, Y: 1.221}

Play with one at a time to see which affects which axis.

If you continue to see offsets that seem like sideways offsets then you can add an affine term. e.g. these parameters will add some distortion along the columns and perform a skew along one axis.

StitchingParameters:
  VoxelSize: {X: 1.654, Y: 1.615}
  lensDistort: {rows: 0.0, cols: 0.03}
  affineMat:
  - [1.0, -0.011, 0.0]
  - [0.0, 1.0, 0.0]
  - [0.0, 0.0, 1.0]

Save the recipe and re-stitch after each attempt.

This affine matrix is equivalent to doing imrotate by -0.75 degrees:

  - [0.9999, -0.0131, 0.0]
  - [0.0131, 0.9999,  0.0]
  - [0.0,      0.0,   1.0]

This is because:

>> cos(deg2rad(-0.75))
ans =
    0.9999

>> sin(deg2rad(-0.75))   
ans =
   -0.0131
Clone this wiki locally