/**************************************************************************** Copyright (c) 2006, Colorado School of Mines and others. All rights reserved. This program and accompanying materials are made available under the terms of the Common Public License - v1.0, which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html ****************************************************************************/ package edu.mines.jtk.dsp; import static edu.mines.jtk.util.ArrayMath.*; import edu.mines.jtk.util.Check; /** * Estimates displacement vector fields for two images. For example, given * two 2-D images f(x1,x2) and g(x1,x2), a shift finder estimates two vector * components of displacement u1(x1,x2) and u2(x1,x2) such that * f(x1,x2) ~ g(x1+u1(x1,x2),x2+u2(x1,x2)). *
* Like the images f and g, the components of displacement are sampled * functions of coordinates x1 and x2. That is, displacements may vary * from sample to sample. The components u1 and u2 represent displacements * in the x1 and x2 coordinate directions, respectively. *
* This shift finder estimates each component of displacement using local * cross-correlations. For each image sample, the estimated shift is that * which yields the maximum correlation coefficient. This coefficient is * found by quadratic interpolation of correlation functions sampled at * integer lags. *
* Methods are provided to find and compensate for each component of shift * sequentially. As each component is found, that component can be removed * from the image g before estimating another component. For example, again * for 2-D images f(x1,x2) and g(x1,x2), we might first estimate u1(x1,x2). * If we then compute an image h(x1,x2) = g(x1+u1(x1,x2),x2), we can use * f(x1,x2) and h(x1,x2) to estimate u2(x1,x2). By repeating this process * sequentially, we obtain estimates for both u1(x1,x2) and u2(x1,x2) such * that f(x1,x2) ~ g(x1+u1(x1,x2),x2+u2(x1,x2)). *
* Methods are also provided to whiten 2-D and 3-D images before estimating
* displacement vectors. This (spectral) whitening improves estimates of
* displacements parallel to image features that may be otherwise poorly
* resolved. Whitening is performed with local prediction error filters
* computed from local auto-correlations.
*
* @author Dave Hale, Colorado School of Mines
* @version 2006.11.18
*/
public class LocalShiftFinder {
/**
* Construct a shift estimator with specified parameters.
* When applied to multi-dimensional arrays, the estimator has the
* same correlation window half-width for all dimensions.
* @param sigma the correlation window half-width; must not be less than 1.
*/
public LocalShiftFinder(double sigma) {
this(sigma,sigma,sigma);
}
/**
* Construct a shift estimator with specified parameters.
* When applied to multi-dimensional arrays, the estimator has half-width
* sigma1 for the 1st dimension and half-width sigma2 for 2nd and higher
* dimensions.
* @param sigma1 correlaton window half-width for 0st dimension;
* must not be less than 1.
* @param sigma2 correlation window half-width for 2nd and higher
* dimensions; must not be less than 1.
*/
public LocalShiftFinder(double sigma1, double sigma2) {
this(sigma1,sigma2,sigma2);
}
/**
* Construct a shift estimator with specified parameters.
* When applied to multi-dimensional arrays, the estimator has half-width
* sigma1 for the 1st dimension, half-width sigma2 for the 2nd dimension,
* and half-width sigma3 for 3rd and higher dimensions.
* @param sigma1 correlation window half-width for 1st dimension;
* must not be less than 1.
* @param sigma2 correlation window half-width for 2nd dimension;
* must not be less than 1.
* @param sigma3 correlation window half-width for 3rd and higher
* dimensions; must not be less than 1.
*/
public LocalShiftFinder(double sigma1, double sigma2, double sigma3) {
Check.argument(sigma1>=1.0,"sigma1>=1.0");
Check.argument(sigma2>=1.0,"sigma2>=1.0");
Check.argument(sigma3>=1.0,"sigma3>=1.0");
_lcfSimple = new LocalCorrelationFilter(
LocalCorrelationFilter.Type.SIMPLE,
LocalCorrelationFilter.Window.GAUSSIAN,
sigma1,sigma2,sigma3);
_si = new SincInterpolator();
_si.setExtrapolation(SincInterpolator.Extrapolation.CONSTANT);
}
/**
* Enables or disables interpolation of displacements when shifting.
* The default is to interpolate displacements. This is the most
* accurate method when sequentially applying non-constant shifts.
* @param enable true, to enable interpolation; false, to disable.
*/
public void setInterpolateDisplacements(boolean enable) {
_interpolateDisplacements = enable;
}
/**
* Finds shifts in the 1st (and only) dimension.
* @param min1 the minimum shift.
* @param max1 the maximum shift.
* @param f the input array f.
* @param g the input array g.
* @param u output array of shifts.
*/
public void find1(
int min1, int max1, float[] f, float[] g, float[] u)
{
findShifts(min1,max1,f,g,u);
}
/**
* Finds shifts in the 1st dimension.
* @param min1 the minimum shift.
* @param max1 the maximum shift.
* @param f the input array f.
* @param g the input array g.
* @param u output array of shifts.
*/
public void find1(
int min1, int max1, float[][] f, float[][] g, float[][] u)
{
findShifts(1,min1,max1,f,g,u);
}
/**
* Finds shifts in the 2nd dimension.
* @param min2 the minimum shift.
* @param max2 the maximum shift.
* @param f the input array f.
* @param g the input array g.
* @param u output array of shifts.
*/
public void find2(
int min2, int max2, float[][] f, float[][] g, float[][] u)
{
findShifts(2,min2,max2,f,g,u);
}
/**
* Finds shifts in the 1st dimension.
* @param min1 the minimum shift.
* @param max1 the maximum shift.
* @param f the input array f.
* @param g the input array g.
* @param u output array of shifts.
*/
public void find1(
int min1, int max1, float[][][] f, float[][][] g, float[][][] u)
{
findShifts(1,min1,max1,f,g,u);
}
/**
* Finds shifts in the 2nd dimension.
* @param min2 the minimum shift.
* @param max2 the maximum shift.
* @param f the input array f.
* @param g the input array g.
* @param u output array of shifts.
*/
public void find2(
int min2, int max2, float[][][] f, float[][][] g, float[][][] u)
{
findShifts(2,min2,max2,f,g,u);
}
/**
* Finds shifts in the 3rd dimension.
* @param min3 the minimum shift.
* @param max3 the maximum shift.
* @param f the input array f.
* @param g the input array g.
* @param u output array of shifts.
*/
public void find3(
int min3, int max3, float[][][] f, float[][][] g, float[][][] u)
{
findShifts(3,min3,max3,f,g,u);
}
/**
* Applies specified shift in the 1st (and only) dimension.
* @param du input array of changes to displacements in 1st dimension.
* @param u1 input/output array of displacements in 1st dimension.
* @param h input/output array of image samples.
*/
public void shift1(float[] du, float[] u1, float[] h) {
int n1 = h.length;
float[] xu1 = new float[n1];
float[] u1a = u1;
float[] u1b = new float[n1];
float[] ha = h;
float[] hb = new float[n1];
for (int i1=0; i1