measure how far each part of one image moved relative to another
Divides the region the two images share into a grid of tiles and phase correlates each tile against the matching tile of the other image. The result is a displacement per tile, to sub pixel accuracy, and the height of the correlation peak that produced it.
The peak height is not a diagnostic - it is the weight. A tile that landed on featureless background correlates weakly and must not get an equal vote when a transform is fitted through the displacements:
[u,peak,pos] = xcfShift(A,B);
T = spatialTransformShift.fit(pos, pos + u, 'weights', peak);Description
Only the region where both images are finite is tiled, so the padding an earlier resampling left behind is excluded rather than correlated against. A tile that still contains a non finite value, or that is flat, comes back with NaN in all three outputs - drop those before fitting, which every spatialTransform fit does for you.
Syntax
[u,peak,pos] = xcfShift(A,B)
[u,peak,pos] = xcfShift(mgA,mgB)
[u,peak,pos] = xcfShift(A,B,'ROISize',64,'numROI',[24 18])Input
| A, B | r × c images, the same size |
| mgA, mgB | mapImage on the same grid, in which case u and pos are in specimen units rather than pixels |
Output
| u | n × 1 vector3d, the displacement from A to B at each tile: the feature at pos in A is at pos + u in B |
| peak | n × 1 correlation peak height, the fit weight |
| pos | n × 1 vector3d, the tile centres, in A |
Options
| ROISize | tile width in pixels, default 2^ceil(log2(rows/4)) |
| numROI | tiles across, scalar or [nx ny]. A scalar is scaled by the aspect ratio to give ny. Default 24 |
| XCFMesh | peak upsampling, default 250 |
| coarseMesh | resolution of the first refinement pass, default 48 |
Flags
| dedupeBand | drop the duplicated band pass indices, see xcfCorrelate |
References
- M. Guizar-Sicairos, S. T. Thurman, J. R. Fienup, Efficient subpixel image registration algorithms, Optics Letters (2008), Vol. 33, 156.