Commit 95386703 authored by Andrey Filippov's avatar Andrey Filippov

adjusting parameters, improved filtering, added error display by the

targets
parent 25577f58
...@@ -546,7 +546,7 @@ public class LensAdjustment { ...@@ -546,7 +546,7 @@ public class LensAdjustment {
double targetMicrons, // target lens center distance (away from "best focus" double targetMicrons, // target lens center distance (away from "best focus"
double toleranceMicrons, // microns double toleranceMicrons, // microns
double toleranceTilt, // double toleranceTilt, //
double toleranceThreshold, // When each error is under swcaled thereshold, reduce correxction step twice double toleranceThreshold, // When each error is under swcaled threshold, reduce correxction step twice
double parallelAdjustThreshold, // adjust 3 motors parallel if focal distance error in the center exceeds this double parallelAdjustThreshold, // adjust 3 motors parallel if focal distance error in the center exceeds this
double motorsSigma, // when fitting planes for far/near, tiltX and tiltY the weights of the samples decay with this sigma double motorsSigma, // when fitting planes for far/near, tiltX and tiltY the weights of the samples decay with this sigma
double motorsSigma3, // all 3 motors together (focusing center) double motorsSigma3, // all 3 motors together (focusing center)
...@@ -710,7 +710,7 @@ public class LensAdjustment { ...@@ -710,7 +710,7 @@ public class LensAdjustment {
this.targetMicrons=targetMicrons; // target lens center distance (away from "best focus" this.targetMicrons=targetMicrons; // target lens center distance (away from "best focus"
this.toleranceMicrons=toleranceMicrons; // microns this.toleranceMicrons=toleranceMicrons; // microns
this.toleranceTilt=toleranceTilt; // this.toleranceTilt=toleranceTilt; //
this.toleranceThreshold=toleranceThreshold; // When each error is under swcaled thereshold, reduce correxction step twice this.toleranceThreshold=toleranceThreshold; // When each error is under swcaled threshold, reduce correxction step twice
this.parallelAdjustThreshold=parallelAdjustThreshold; // adjust 3 motors parallel if focal distance error in the center exceeds this this.parallelAdjustThreshold=parallelAdjustThreshold; // adjust 3 motors parallel if focal distance error in the center exceeds this
this.motorsSigma=motorsSigma; // when fitting planes for far/near, tiltX and tiltY the weights of the samples decay with this sigma this.motorsSigma=motorsSigma; // when fitting planes for far/near, tiltX and tiltY the weights of the samples decay with this sigma
this.motorsSigma3=motorsSigma3; // same when 3 motors move together this.motorsSigma3=motorsSigma3; // same when 3 motors move together
...@@ -873,7 +873,7 @@ public class LensAdjustment { ...@@ -873,7 +873,7 @@ public class LensAdjustment {
this.targetMicrons, // target lens center distance (away from "best focus" this.targetMicrons, // target lens center distance (away from "best focus"
this.toleranceMicrons, // microns this.toleranceMicrons, // microns
this.toleranceTilt, // this.toleranceTilt, //
this.toleranceThreshold, // When each error is under swcaled thereshold, reduce correxction step twice this.toleranceThreshold, // When each error is under swcaled threshold, reduce correxction step twice
this.parallelAdjustThreshold, // adjust 3 motors parallel if focal distance error in the center exceeds this this.parallelAdjustThreshold, // adjust 3 motors parallel if focal distance error in the center exceeds this
this.motorsSigma, // when fitting planes for far/near, tiltX and tiltY the weights of the samples decay with this sigma this.motorsSigma, // when fitting planes for far/near, tiltX and tiltY the weights of the samples decay with this sigma
......
...@@ -3512,7 +3512,7 @@ public class CLTParameters { ...@@ -3512,7 +3512,7 @@ public class CLTParameters {
gd.addCheckbox ("Add port weights to RGBA stack (debug feature)", this.keep_weights); gd.addCheckbox ("Add port weights to RGBA stack (debug feature)", this.keep_weights);
gd.addCheckbox ("Replace port weights with per-channel MIDCT (16x16) - were relevant", this.replace_weights); gd.addCheckbox ("Replace port weights with per-channel MIDCT (16x16) - were relevant", this.replace_weights);
gd.addCheckbox ("Alpha channel: use center 8x8 (unchecked - treat same as RGB)", this.sharp_alpha); gd.addCheckbox ("Alpha channel: use center 8x8 (unchecked - treat same as RGB)", this.sharp_alpha);
gd.addNumericField("Alpha channel 0.0 thereshold (lower - transparent)", this.alpha0, 3); gd.addNumericField("Alpha channel 0.0 threshold (lower - transparent)", this.alpha0, 3);
gd.addNumericField("Alpha channel 1.0 threshold (higher - opaque)", this.alpha1, 3); gd.addNumericField("Alpha channel 1.0 threshold (higher - opaque)", this.alpha1, 3);
gd.addCheckbox ("Generate shifted channel linear RGB stacks", this.gen_chn_stacks); gd.addCheckbox ("Generate shifted channel linear RGB stacks", this.gen_chn_stacks);
gd.addCheckbox ("Generate shifted channel color image stack", this.gen_chn_img); gd.addCheckbox ("Generate shifted channel color image stack", this.gen_chn_img);
...@@ -4130,11 +4130,11 @@ public class CLTParameters { ...@@ -4130,11 +4130,11 @@ public class CLTParameters {
"Absolute inter-sensor difference to seed transparent texture."); "Absolute inter-sensor difference to seed transparent texture.");
gd.addNumericField("Seed fat zero of combo variance", this.lre_seed_same_fz, 5,7,"", // 6.5; // 13; // seed_inter = 50.0; gd.addNumericField("Seed fat zero of combo variance", this.lre_seed_same_fz, 5,7,"", // 6.5; // 13; // seed_inter = 50.0;
"Add to the denominator (to combined variance) to divide inter-sensor variance."); "Add to the denominator (to combined variance) to divide inter-sensor variance.");
gd.addNumericField("Seed FOM thereshold", this.lre_seed_fom, 5,7,"", // 2.0; // 1.9; // 1.2; gd.addNumericField("Seed FOM threshold", this.lre_seed_fom, 5,7,"", // 2.0; // 1.9; // 1.2;
"Seed threshold for var_inter/(var_same+var_same_fz) - definitely not a foreground."); "Seed threshold for var_inter/(var_same+var_same_fz) - definitely not a foreground.");
gd.addNumericField("Seed fat zero of inter-sensor variance",this.lre_trim_inter_fz, 5,7,"", //5.0; // 13.0; gd.addNumericField("Seed fat zero of inter-sensor variance",this.lre_trim_inter_fz, 5,7,"", //5.0; // 13.0;
"Add to the denominator (to inter-sensor variance) to divide combo variance."); "Add to the denominator (to inter-sensor variance) to divide combo variance.");
gd.addNumericField("Trim FOM thereshold", this.lre_trim_fom, 5,7,"", // 0.5; // 0.8; // 1.3; // 1.8; // 1.2; // 0.8; // 0.4; // 0.7; gd.addNumericField("Trim FOM threshold", this.lre_trim_fom, 5,7,"", // 0.5; // 0.8; // 1.3; // 1.8; // 1.2; // 0.8; // 0.4; // 0.7;
"Trim threshold for var_same/(var_inter+var_inter_fz) - seems to be foreground."); "Trim threshold for var_same/(var_inter+var_inter_fz) - seems to be foreground.");
gd.addMessage("Reducing Trim FOM near high-contrast FG over sky by thresholding, bluring and dividing"); gd.addMessage("Reducing Trim FOM near high-contrast FG over sky by thresholding, bluring and dividing");
// Scale down FOM for pixels near high-variance VAR_SAME // Scale down FOM for pixels near high-variance VAR_SAME
......
...@@ -106,7 +106,8 @@ public class DoubleGaussianBlur { ...@@ -106,7 +106,8 @@ public class DoubleGaussianBlur {
return; return;
} }
/* Blur an image in one direction (x or y) by a Gaussian. /**
* Blur an image in one direction (x or y) by a Gaussian.
* @param ip The Image with the original data where also the result will be stored * @param ip The Image with the original data where also the result will be stored
* @param sigma Standard deviation of the Gaussian * @param sigma Standard deviation of the Gaussian
* @param accuracy Accuracy of kernel, should not be > 0.02 * @param accuracy Accuracy of kernel, should not be > 0.02
...@@ -188,7 +189,8 @@ public class DoubleGaussianBlur { ...@@ -188,7 +189,8 @@ public class DoubleGaussianBlur {
} }
return; return;
} }
/* Create a 1-dimensional normalized Gaussian kernel with standard deviation sigma /**
* Create a 1-dimensional normalized Gaussian kernel with standard deviation sigma
* and the running sum over the kernel * and the running sum over the kernel
* Note: this is one side of the kernel only, not the full kernel as used by the * Note: this is one side of the kernel only, not the full kernel as used by the
* Convolver class of ImageJ. * Convolver class of ImageJ.
...@@ -252,14 +254,15 @@ public class DoubleGaussianBlur { ...@@ -252,14 +254,15 @@ public class DoubleGaussianBlur {
} }
return kernel; return kernel;
} }
/* Scale a line (row or column of a FloatProcessor or part thereof)
/** Scale a line (row or column of a FloatProcessor or part thereof)
* down by a factor <code>reduceBy</code> and write the result into * down by a factor <code>reduceBy</code> and write the result into
* <code>cache</code>. * <code>cache</code>.
* Input line pixel # <code>unscaled0</code> will correspond to output * Input line pixel # <code>unscaled0</code> will correspond to output
* line pixel # 0. <code>unscaled0</code> may be negative. Out-of-line * line pixel # 0. <code>unscaled0</code> may be negative. Out-of-line
* pixels of the input are replaced by the edge pixels. * pixels of the input are replaced by the edge pixels.
*/ */
void downscaleLine(double[] pixels, double[] cache, double[] kernel, static void downscaleLine(double[] pixels, double[] cache, double[] kernel,
int reduceBy, int pixel0, int unscaled0, int length, int pointInc, int newLength) { int reduceBy, int pixel0, int unscaled0, int length, int pointInc, int newLength) {
if (pixel0 > pixels.length) { if (pixel0 > pixels.length) {
System.out.println("++++++ Error in DoubleGaussianBlur, pixel0="+pixel0+", pixels.length="+(pixels.length)); System.out.println("++++++ Error in DoubleGaussianBlur, pixel0="+pixel0+", pixels.length="+(pixels.length));
...@@ -280,7 +283,8 @@ public class DoubleGaussianBlur { ...@@ -280,7 +283,8 @@ public class DoubleGaussianBlur {
} }
} }
/* Create a kernel for downscaling. The kernel function preserves /**
* Create a kernel for downscaling. The kernel function preserves
* norm and 1st moment (i.e., position) and has fixed 2nd moment, * norm and 1st moment (i.e., position) and has fixed 2nd moment,
* (in contrast to linear interpolation). * (in contrast to linear interpolation).
* In scaled space, the length of the kernel runs from -1.5 to +1.5, * In scaled space, the length of the kernel runs from -1.5 to +1.5,
...@@ -288,7 +292,7 @@ public class DoubleGaussianBlur { ...@@ -288,7 +292,7 @@ public class DoubleGaussianBlur {
* Array index corresponding to the kernel center is * Array index corresponding to the kernel center is
* unitLength*3/2 * unitLength*3/2
*/ */
double[] makeDownscaleKernel (int unitLength) { static double[] makeDownscaleKernel (int unitLength) {
int mid = unitLength*3/2; int mid = unitLength*3/2;
double[] kernel = new double[3*unitLength]; double[] kernel = new double[3*unitLength];
for (int i=0; i<=unitLength/2; i++) { for (int i=0; i<=unitLength/2; i++) {
...@@ -306,10 +310,11 @@ public class DoubleGaussianBlur { ...@@ -306,10 +310,11 @@ public class DoubleGaussianBlur {
return kernel; return kernel;
} }
/* Scale a line up by factor <code>reduceBy</code> and write as a row /**
* Scale a line up by factor <code>reduceBy</code> and write as a row
* or column (or part thereof) to the pixels array of a FloatProcessor. * or column (or part thereof) to the pixels array of a FloatProcessor.
*/ */
void upscaleLine (double[] cache, double[] pixels, double[] kernel, static void upscaleLine (double[] cache, double[] pixels, double[] kernel,
int reduceBy, int pixel0, int unscaled0, int writeFrom, int writeTo, int pointInc) { int reduceBy, int pixel0, int unscaled0, int writeFrom, int writeTo, int pointInc) {
int p = pixel0 + pointInc*writeFrom; int p = pixel0 + pointInc*writeFrom;
for (int xout = writeFrom; xout < writeTo; xout++, p+=pointInc) { for (int xout = writeFrom; xout < writeTo; xout++, p+=pointInc) {
...@@ -322,7 +327,8 @@ public class DoubleGaussianBlur { ...@@ -322,7 +327,8 @@ public class DoubleGaussianBlur {
} }
} }
/* Create a kernel for upscaling. The kernel function is a convolution /**
* Create a kernel for upscaling. The kernel function is a convolution
* of four unit squares, i.e., four uniform kernels with value +1 * of four unit squares, i.e., four uniform kernels with value +1
* from -0.5 to +0.5 (in downscaled coordinates). The second derivative * from -0.5 to +0.5 (in downscaled coordinates). The second derivative
* of this kernel is smooth, the third is not. Its standard deviation * of this kernel is smooth, the third is not. Its standard deviation
...@@ -330,7 +336,7 @@ public class DoubleGaussianBlur { ...@@ -330,7 +336,7 @@ public class DoubleGaussianBlur {
* The kernel runs from [-2 to +2[, corresponding to array index * The kernel runs from [-2 to +2[, corresponding to array index
* 0 ... 4*unitLength (whereby the last point is not in the array any more). * 0 ... 4*unitLength (whereby the last point is not in the array any more).
*/ */
double[] makeUpscaleKernel (int unitLength) { static double[] makeUpscaleKernel (int unitLength) {
double[] kernel = new double[4*unitLength]; double[] kernel = new double[4*unitLength];
int mid = 2*unitLength; int mid = 2*unitLength;
kernel[0] = 0; kernel[0] = 0;
...@@ -349,7 +355,8 @@ public class DoubleGaussianBlur { ...@@ -349,7 +355,8 @@ public class DoubleGaussianBlur {
return kernel; return kernel;
} }
/* Convolve a line with a symmetric kernel and write to a separate array, /**
* Convolve a line with a symmetric kernel and write to a separate array,
* possibly the pixels array of a FloatProcessor (as a row or column or part thereof) * possibly the pixels array of a FloatProcessor (as a row or column or part thereof)
* *
* @param input Input array containing the line * @param input Input array containing the line
...@@ -371,7 +378,7 @@ public class DoubleGaussianBlur { ...@@ -371,7 +378,7 @@ public class DoubleGaussianBlur {
* @param pointInc Increment of the pixels array index to the next point (for an ImageProcessor, * @param pointInc Increment of the pixels array index to the next point (for an ImageProcessor,
* it should be <code>1</code> for a row, <code>width</code> for a column) * it should be <code>1</code> for a row, <code>width</code> for a column)
*/ */
public void convolveLine(double[] input, double[] pixels, double[][] kernel, int readFrom, public static void convolveLine(double[] input, double[] pixels, double[][] kernel, int readFrom,
int readTo, int writeFrom, int writeTo, int point0, int pointInc) { int readTo, int writeFrom, int writeTo, int point0, int pointInc) {
int length = input.length; int length = input.length;
double first = input[0]; //out-of-edge pixels are replaced by nearest edge pixels double first = input[0]; //out-of-edge pixels are replaced by nearest edge pixels
......
...@@ -17,6 +17,7 @@ import java.net.URISyntaxException; ...@@ -17,6 +17,7 @@ import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import com.elphel.imagej.cameras.CLTParameters; import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.GenericJTabbedDialog; import com.elphel.imagej.common.GenericJTabbedDialog;
import com.elphel.imagej.common.ShowDoubleFloatArrays; import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.gpu.GPUTileProcessor; import com.elphel.imagej.gpu.GPUTileProcessor;
...@@ -33,6 +34,7 @@ import com.elphel.imagej.tileprocessor.TileNeibs; ...@@ -33,6 +34,7 @@ import com.elphel.imagej.tileprocessor.TileNeibs;
import ij.IJ; import ij.IJ;
import ij.ImagePlus; import ij.ImagePlus;
import ij.ImageStack; import ij.ImageStack;
import ij.plugin.filter.GaussianBlur;
import ij.process.ByteProcessor; import ij.process.ByteProcessor;
import ij.process.ColorProcessor; import ij.process.ColorProcessor;
import ij.process.FloatProcessor; import ij.process.FloatProcessor;
...@@ -54,7 +56,9 @@ public class CuasMotion { ...@@ -54,7 +56,9 @@ public class CuasMotion {
final static public int TARGET_VX = 2; final static public int TARGET_VX = 2;
final static public int TARGET_VY = 3; final static public int TARGET_VY = 3;
final static public int TARGET_STRENGTH = 4; final static public int TARGET_STRENGTH = 4;
final static public int TARGET_LENGTH = TARGET_STRENGTH+1; final static public int TARGET_NTILE = 5;
final static public int TARGET_LENGTH = TARGET_NTILE+1;
public static String RESOURCE_GRAPICS_DIR ="graphics"; public static String RESOURCE_GRAPICS_DIR ="graphics";
public static String ICON_TARGET_1X = "TDbox_dashed21x21_bold.png"; public static String ICON_TARGET_1X = "TDbox_dashed21x21_bold.png";
...@@ -317,7 +321,8 @@ public class CuasMotion { ...@@ -317,7 +321,8 @@ public class CuasMotion {
double lma_maxr = clt_parameters.imp.cuas_lma_maxr; // = 5.0; // Maximal radius (>3.8) double lma_maxr = clt_parameters.imp.cuas_lma_maxr; // = 5.0; // Maximal radius (>3.8)
double lma_mink = clt_parameters.imp.cuas_lma_mink; // = 0.0; // Minimal K (overshoot) <0.007 double lma_mink = clt_parameters.imp.cuas_lma_mink; // = 0.0; // Minimal K (overshoot) <0.007
double lma_maxk = clt_parameters.imp.cuas_lma_maxk; // = 5.0; // Minimal K (overshoot) > 3.8 double lma_maxk = clt_parameters.imp.cuas_lma_maxk; // = 5.0; // Minimal K (overshoot) > 3.8
boolean remove_isolated= clt_parameters.imp.cuas_isolated; // false; boolean remove_isolated= clt_parameters.imp.cuas_isolated; // true;
double max_mismatch = clt_parameters.imp.cuas_max_mismatch; // 2;
double mask_width = clt_parameters.imp.cuas_mask_width; // 9; double mask_width = clt_parameters.imp.cuas_mask_width; // 9;
double mask_blur = clt_parameters.imp.cuas_mask_blur; // 3; double mask_blur = clt_parameters.imp.cuas_mask_blur; // 3;
...@@ -413,7 +418,7 @@ public class CuasMotion { ...@@ -413,7 +418,7 @@ public class CuasMotion {
"Finish fitting when the relative RMS improvement drops below this value."); "Finish fitting when the relative RMS improvement drops below this value.");
gd.addNumericField("LMA iterations", num_iter, 0,3,"", gd.addNumericField("LMA iterations", num_iter, 0,3,"",
"Maximal number of the LMA iterations."); "Maximal number of the LMA iterations.");
gd.addMessage("--- Moving target discrimination parameters theresholds ---"); gd.addMessage("--- Moving target discrimination parameters thresholds ---");
gd.addNumericField("Maximal RMS", lma_rms, 5,8,"", gd.addNumericField("Maximal RMS", lma_rms, 5,8,"",
"Maximal RMS for target that should match always, regardless of the amplitude."); "Maximal RMS for target that should match always, regardless of the amplitude.");
gd.addNumericField("Maximal sufficient RMS", lma_arms, 5,8,"", gd.addNumericField("Maximal sufficient RMS", lma_arms, 5,8,"",
...@@ -2092,6 +2097,66 @@ public class CuasMotion { ...@@ -2092,6 +2097,66 @@ public class CuasMotion {
return frames_accum; return frames_accum;
} }
/**
* Calculate image x,y for each target half keyframe interval before the keyframe and half-interval after.
* It is used to filter out stray targets, these coordinates for the consecutive frames should be close:
* "after" for the earlier keyframe and "before" for the later one.
* @param vector_field [keyframe_number][tile][] first two elements - targets vX, vY in pixels per frame. Empty are nulls, same velocities for 5x5
* @param target_positions [keyframe_number][tile][] target positions of the targets relative to the tile center
* @param interseq_scale multiply velocity vector to get pixel offset in the middle between the two keyframes
* @param tilesX number of tiles in a row
* @param debugLevel debug level
* @return [keyframe_number][tile]{before=0, after=1}{px, py}
*/
public static double [][][][] getHalfBeforeAfterPixXY(
final double [][][] vector_field,
final double [][][] target_positions,
final double interseq_scale,
final int tilesX,
final int debugLevel) {
final int num_seq = vector_field.length;
final int num_tiles = vector_field[0].length;
final double [][][][] pix_xy = new double [num_seq][num_tiles][][]; // [][]{0-before,1 - after}{px, py}
final int tileSize = GPUTileProcessor.DTT_SIZE;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
// for (int nseq = 0; nseq < vector_field.length; nseq++) {
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nSeq = ai.getAndIncrement(); nSeq < num_seq; nSeq = ai.getAndIncrement()) {
for (int ntile = 0; ntile < num_tiles; ntile++) {
double [] vvector = vector_field[nSeq][ntile];
if (vvector != null) {
double [] target_pos = target_positions[nSeq][ntile];
if (target_pos != null) { // should be always
int tileX = ntile % tilesX;
int tileY = ntile / tilesX;
double xc = tileSize * tileX + tileSize/2;
double yc = tileSize * tileY + tileSize/2;
double xtk = xc + target_pos[CuasMotionLMA.RSLT_X];
double ytk = yc + target_pos[CuasMotionLMA.RSLT_Y];
double dx = vvector[INDX_VX] * interseq_scale;
double dy = vvector[INDX_VY] * interseq_scale;
double [][] baxy = new double [2][2];
//baxy[0][0]
baxy[0][0] = xtk - dx; // before, x
baxy[0][1] = ytk - dy; // before, y
baxy[1][0] = xtk + dx; // after, x
baxy[1][1] = ytk + dy; // after, y
pix_xy[nSeq][ntile] = baxy;
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return pix_xy;
}
/** /**
* Generate target images * Generate target images
* @param clt_parameters * @param clt_parameters
...@@ -2131,7 +2196,7 @@ public class CuasMotion { ...@@ -2131,7 +2196,7 @@ public class CuasMotion {
fpix_out[i]= background[i].clone(); fpix_out[i]= background[i].clone();
} }
final int tileSize = GPUTileProcessor.DTT_SIZE; final int tileSize = GPUTileProcessor.DTT_SIZE;
final int tileSize2 = 2 * tileSize; // final int tileSize2 = 2 * tileSize;
final int half_step0 = -(frame_step+1)/2; final int half_step0 = -(frame_step+1)/2;
final int half_step1 = frame_step + half_step0; final int half_step1 = frame_step + half_step0;
final int num_scenes = background.length; final int num_scenes = background.length;
...@@ -2155,6 +2220,7 @@ public class CuasMotion { ...@@ -2155,6 +2220,7 @@ public class CuasMotion {
target_list.add(ntile); target_list.add(ntile);
} }
final int[] targets = target_list.stream().mapToInt(Integer::intValue).toArray(); final int[] targets = target_list.stream().mapToInt(Integer::intValue).toArray();
for (int dscene = half_step0; dscene < half_step1; dscene ++) { for (int dscene = half_step0; dscene < half_step1; dscene ++) {
final int fdscene = dscene; final int fdscene = dscene;
int nscene = frame_center + dscene; int nscene = frame_center + dscene;
...@@ -2190,6 +2256,7 @@ public class CuasMotion { ...@@ -2190,6 +2256,7 @@ public class CuasMotion {
targets_data[nTarget][TARGET_VX] = vvector[INDX_VX]; targets_data[nTarget][TARGET_VX] = vvector[INDX_VX];
targets_data[nTarget][TARGET_VY] = vvector[INDX_VY]; targets_data[nTarget][TARGET_VY] = vvector[INDX_VY];
targets_data[nTarget][TARGET_STRENGTH] = target_pos[CuasMotionLMA.RSLT_A]; targets_data[nTarget][TARGET_STRENGTH] = target_pos[CuasMotionLMA.RSLT_A];
targets_data[nTarget][TARGET_NTILE] = ntile;
int pxl = (int) Math.round(targets_data[nTarget][TARGET_X]) - offs; int pxl = (int) Math.round(targets_data[nTarget][TARGET_X]) - offs;
int pyt = (int) Math.round(targets_data[nTarget][TARGET_Y]) - offs; int pyt = (int) Math.round(targets_data[nTarget][TARGET_Y]) - offs;
for (int ym = 0; ym < isize; ym++) { for (int ym = 0; ym < isize; ym++) {
...@@ -2292,6 +2359,173 @@ public class CuasMotion { ...@@ -2292,6 +2359,173 @@ public class CuasMotion {
return out_pix; return out_pix;
} }
public static float [][] runningGaussian(
final float [][] fpixels,
final int ra_length,
final int width){
final int num_scenes = fpixels.length;
final int num_pixels = fpixels[0].length;
final int height = num_pixels/width;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final double sigma = 0.5* ra_length;
final float [][] out_pix = new float [num_scenes][num_pixels];
/*
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nSeq = ai.getAndIncrement(); nSeq < num_scenes; nSeq = ai.getAndIncrement()) {
Arrays.fill(out_pix[nSeq],Float.NaN);
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
*/
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] temp_line = new double[width*num_scenes];
DoubleGaussianBlur gb = new DoubleGaussianBlur();
for (int nLine = ai.getAndIncrement(); nLine < height; nLine = ai.getAndIncrement()) {
for (int nseq = 0; nseq < num_scenes; nseq++) {
int src_index = nLine*width;
int dst_index = nseq*width;
for (int i = 0; i < width; i++) {
temp_line[dst_index++] = fpixels[nseq][src_index++];
}
}
gb.blur1Direction(
temp_line, // double [] pixels,
width, // int width,
num_scenes, // int height,
sigma, // double sigma,
0.001, // double accuracy,
false); // boolean xDirection vertical along time line
for (int nseq = 0; nseq < num_scenes; nseq++) {
int dst_index = nLine*width;
int src_index = nseq*width;
for (int i = 0; i < width; i++) {
out_pix[nseq][dst_index++] = (float)(temp_line[src_index++]);
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return out_pix;
}
public static float [][] runningGaussianNaN(
final float [][] fpixels,
final int ra_length,
final int width){
final int num_scenes = fpixels.length;
final int num_pixels = fpixels[0].length;
final int height = num_pixels/width;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final double sigma = 0.5* ra_length;
final float [][] out_pix = new float [num_scenes][num_pixels];
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nSeq = ai.getAndIncrement(); nSeq < num_scenes; nSeq = ai.getAndIncrement()) {
System.arraycopy(
fpixels[nSeq],
0,
out_pix[nSeq],
0,
num_pixels);
/*
for (int npix = 0; npix < num_pixels; npix++) {
out_pix[nSeq][npix] = fpixels[nSeq][npix];
}
*/
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] temp_line = new double[width*num_scenes];
boolean [] has_nans = new boolean[width];
DoubleGaussianBlur gb = new DoubleGaussianBlur();
for (int nLine = ai.getAndIncrement(); nLine < height; nLine = ai.getAndIncrement()) {
Arrays.fill(has_nans, false);
boolean has_some_nans = false;
for (int nseq = 0; nseq < num_scenes; nseq++) {
int src_index = nLine*width;
int dst_index = nseq*width;
for (int x = 0; x < width; x++) {
double dpix = out_pix[nseq][src_index++];
temp_line[dst_index++] = dpix;
boolean nan = Double.isNaN(dpix);
has_nans[x] |= nan;
has_some_nans |= nan;
}
}
if (has_some_nans) {
for (int x = 0; x < width; x++) if (has_nans[x]){
// duplicate first/last, interpolate middle
if (Double.isNaN(temp_line[x])) {
int i;
for (i = 1; Double.isNaN(temp_line[i * width+x]) && (i < num_scenes); i++);
temp_line[x] = temp_line[i * width+x];
}
if (Double.isNaN(temp_line[(num_scenes-1)*width + x])) {
int i;
for (i = num_scenes-1; Double.isNaN(temp_line[i*width+x]) && (i >=0); i--);
temp_line[(num_scenes - 1) * width + x] = temp_line[i*width+x];
}
// interpolate remaining gaps
int i;
for (i=0; i < num_scenes; i++) {
if (Double.isNaN(temp_line[i * width + x])) {
int gap_start = i-1;
for (i = i+1; Double.isNaN(temp_line[i * width + x]); i++); // last is not NaN, set above
int gap_end = i;
double v0 = temp_line[gap_start * width + x];
double v1 = temp_line[gap_end * width + x];
for (int k = 1; k < (gap_end - gap_start); k++) {
temp_line[(gap_start + k) * width + x] = v0 + (v1-v0) * k;
}
}
}
}
}
gb.blur1Direction(
temp_line, // double [] pixels,
width, // int width,
num_scenes, // int height,
sigma, // double sigma,
0.001, // double accuracy,
false); // boolean xDirection vertical along time line
for (int nseq = 0; nseq < num_scenes; nseq++) {
int dst_index = nLine*width;
int src_index = nseq*width;
for (int i = 0; i < width; i++) {
out_pix[nseq][dst_index++] = (float)(temp_line[src_index++]);
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return out_pix;
}
/** /**
* Version of runningAverage) that tolerates NaN value. It modifies fpixels[][] replacing first/last scene values if they were NaNs * Version of runningAverage) that tolerates NaN value. It modifies fpixels[][] replacing first/last scene values if they were NaNs
* @param fpixels * @param fpixels
...@@ -2329,7 +2563,7 @@ public class CuasMotion { ...@@ -2329,7 +2563,7 @@ public class CuasMotion {
Arrays.fill(line_ra, 0.0f); Arrays.fill(line_ra, 0.0f);
Arrays.fill(line_ra_length, 0); Arrays.fill(line_ra_length, 0);
int pix0 = nLine* width; int pix0 = nLine* width;
// fix first and last pixels if they ar nulls; // fix first and last pixels if they are nulls;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
if (Float.isNaN(fpixels[0][pix0+x])) { if (Float.isNaN(fpixels[0][pix0+x])) {
int i; int i;
...@@ -2546,6 +2780,7 @@ public class CuasMotion { ...@@ -2546,6 +2780,7 @@ public class CuasMotion {
final int target_type, // = 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe final int target_type, // = 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
final float [][] fpixels, final float [][] fpixels,
final double [][][] targets60hz, final double [][][] targets60hz,
final double [][][] mismatch_ba,
final int frame0, final int frame0,
final int frame_step, final int frame_step,
final int width_src, final int width_src,
...@@ -2578,11 +2813,6 @@ public class CuasMotion { ...@@ -2578,11 +2813,6 @@ public class CuasMotion {
final String font_name = clt_parameters.imp.cuas_font_name; final String font_name = clt_parameters.imp.cuas_font_name;
final int font_size = clt_parameters.imp.cuas_font_size; final int font_size = clt_parameters.imp.cuas_font_size;
final int font_type = clt_parameters.imp.cuas_font_type; final int font_type = clt_parameters.imp.cuas_font_type;
final double ifov = clt_parameters.imp.cuas_ifov;
final int px0 = clt_parameters.imp.cuas_px0;
final int py0 = clt_parameters.imp.cuas_py0;
final double az0 = clt_parameters.imp.cuas_az0;
final double el0 = clt_parameters.imp.cuas_el0;
final int space_before_text = 2; final int space_before_text = 2;
ColorProcessor diamond_cp = null; ColorProcessor diamond_cp = null;
...@@ -2769,6 +2999,13 @@ public class CuasMotion { ...@@ -2769,6 +2999,13 @@ public class CuasMotion {
String txt = getTargetText( String txt = getTargetText(
clt_parameters, // CLTParameters clt_parameters, clt_parameters, // CLTParameters clt_parameters,
targets[ntarget]); // double [] target); targets[ntarget]); // double [] target);
int ntile = (int) targets[ntarget][TARGET_NTILE];
if ((mismatch_ba != null)) {
double [] mm = mismatch_ba[nSeq][ntile];
if (mm != null) {
txt += String.format("\nErr-%3.1f\nErr-%3.1f", mm[0],mm[1]);
}
}
ip.setColor(text_color); ip.setColor(text_color);
ip.setFont(font_target); ip.setFont(font_target);
if (target_text_transparent) { if (target_text_transparent) {
...@@ -3049,6 +3286,7 @@ public class CuasMotion { ...@@ -3049,6 +3286,7 @@ public class CuasMotion {
boolean intermed_low = clt_parameters.imp.cuas_intermed_low; //true; boolean intermed_low = clt_parameters.imp.cuas_intermed_low; //true;
boolean intermed_high = clt_parameters.imp.cuas_intermed_high; //true; boolean intermed_high = clt_parameters.imp.cuas_intermed_high; //true;
boolean intermed_giga = clt_parameters.imp.cuas_intermed_giga; //false; boolean intermed_giga = clt_parameters.imp.cuas_intermed_giga; //false;
boolean cuas_gaussian_ra = clt_parameters.imp.cuas_gaussian_ra; // use gaussian temporal Gaussian instead of running average
for (int i = 0; i < target_frac.length; i++) { for (int i = 0; i < target_frac.length; i++) {
if (clt_parameters.imp.cuas_target_frac[i].length >= 2) { if (clt_parameters.imp.cuas_target_frac[i].length >= 2) {
target_frac[i][0] = clt_parameters.imp.cuas_target_frac[i][0]; target_frac[i][0] = clt_parameters.imp.cuas_target_frac[i][0];
...@@ -3065,7 +3303,7 @@ public class CuasMotion { ...@@ -3065,7 +3303,7 @@ public class CuasMotion {
final int frame0 = start_frame + seq_length/2; final int frame0 = start_frame + seq_length/2;
final int half_accum_range = corr_pairs/2; final int half_accum_range = corr_pairs/2;
int [] remain = new int [num_corr_samples]; int [] remain = new int [num_corr_samples];
boolean debug_tum= false; boolean debug_tum= true; // false;
String model_prefix = parentCLT.getImageName()+getParametersSuffix(clt_parameters,null); String model_prefix = parentCLT.getImageName()+getParametersSuffix(clt_parameters,null);
float [][] fpixels_tum = fpixels; float [][] fpixels_tum = fpixels;
if (temporal_um > 0) { if (temporal_um > 0) {
...@@ -3082,16 +3320,24 @@ public class CuasMotion { ...@@ -3082,16 +3320,24 @@ public class CuasMotion {
} }
parentCLT.saveImagePlusInModelDirectory(imp_src); // ImagePlus imp) parentCLT.saveImagePlusInModelDirectory(imp_src); // ImagePlus imp)
} }
float [][] fpixels_ra = runningAverage( float [][] fpixels_ra;
if (cuas_gaussian_ra) {
fpixels_ra= runningGaussian(
fpixels, // final float [][] fpixels,
temporal_um, // final int ra_length,
cuasMotion.gpu_max_width); // final int width);
} else {
fpixels_ra= runningAverage(
fpixels, // final float [][] fpixels, fpixels, // final float [][] fpixels,
temporal_um, // final int ra_length, temporal_um, // final int ra_length,
cuasMotion.gpu_max_width); // final int width); cuasMotion.gpu_max_width); // final int width);
}
if (intermed_high && debug_tum) { if (intermed_high && debug_tum) {
ImagePlus imp_src_ra = ShowDoubleFloatArrays.makeArrays( ImagePlus imp_src_ra = ShowDoubleFloatArrays.makeArrays(
fpixels_ra, // float[][] pixels, fpixels_ra, // float[][] pixels,
cuasMotion.gpu_max_width, // int width, cuasMotion.gpu_max_width, // int width,
cuasMotion.gpu_max_height, // int height, cuasMotion.gpu_max_height, // int height,
model_prefix+"-SOURCE-RA"+temporal_um, //String title, model_prefix+(cuas_gaussian_ra?"-SOURCE-RG":"-SOURCE-RA")+temporal_um, //String title,
scene_titles); //String [] titles) scene_titles); //String [] titles)
imp_src_ra.getProcessor().setMinAndMax(-input_range/2, input_range/2); imp_src_ra.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) { if (!batch_mode) {
...@@ -3118,16 +3364,23 @@ public class CuasMotion { ...@@ -3118,16 +3364,23 @@ public class CuasMotion {
} }
parentCLT.saveImagePlusInModelDirectory(imp_outliers); // ImagePlus imp) parentCLT.saveImagePlusInModelDirectory(imp_outliers); // ImagePlus imp)
} }
if (cuas_gaussian_ra) {
fpixels_ra = runningGaussianNaN(
fpixels_nan, // final float [][] fpixels,
temporal_um, // final int ra_length,
cuasMotion.gpu_max_width); // final int width);
} else {
fpixels_ra = runningAverageNaN( fpixels_ra = runningAverageNaN(
fpixels_nan, // final float [][] fpixels, fpixels_nan, // final float [][] fpixels,
temporal_um, // final int ra_length, temporal_um, // final int ra_length,
cuasMotion.gpu_max_width); // final int width); cuasMotion.gpu_max_width); // final int width);
}
if (intermed_high && debug_tum) { if (intermed_high && debug_tum) {
ImagePlus imp_src_ra = ShowDoubleFloatArrays.makeArrays( ImagePlus imp_src_ra = ShowDoubleFloatArrays.makeArrays(
fpixels_ra, // float[][] pixels, fpixels_ra, // float[][] pixels,
cuasMotion.gpu_max_width, // int width, cuasMotion.gpu_max_width, // int width,
cuasMotion.gpu_max_height, // int height, cuasMotion.gpu_max_height, // int height,
model_prefix+"-SOURCE-RA-NOOUTLIERS"+temporal_um, //String title, model_prefix+(cuas_gaussian_ra?"-SOURCE-RG":"-SOURCE-RA")+"-NOOUTLIERS"+temporal_um, //String title,
scene_titles); //String [] titles) scene_titles); //String [] titles)
imp_src_ra.getProcessor().setMinAndMax(-input_range/2, input_range/2); imp_src_ra.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) { if (!batch_mode) {
...@@ -3158,16 +3411,23 @@ public class CuasMotion { ...@@ -3158,16 +3411,23 @@ public class CuasMotion {
float [][] fpixels_ra = fpixels_tum; //fpixels; float [][] fpixels_ra = fpixels_tum; //fpixels;
if (precorr_ra > 1) { if (precorr_ra > 1) {
if (cuas_gaussian_ra) {
fpixels_ra = runningGaussian(
fpixels_tum, // fpixels, // final float [][] fpixels,
precorr_ra, // final int ra_length,
cuasMotion.gpu_max_width); // final int width)
} else {
fpixels_ra = runningAverage( fpixels_ra = runningAverage(
fpixels_tum, // fpixels, // final float [][] fpixels, fpixels_tum, // fpixels, // final float [][] fpixels,
precorr_ra, // final int ra_length, precorr_ra, // final int ra_length,
cuasMotion.gpu_max_width); // final int width) cuasMotion.gpu_max_width); // final int width)
}
if (intermed_high) { if (intermed_high) {
ImagePlus imp_ra = ShowDoubleFloatArrays.makeArrays( ImagePlus imp_ra = ShowDoubleFloatArrays.makeArrays(
fpixels_ra, // float[][] pixels, fpixels_ra, // float[][] pixels,
cuasMotion.gpu_max_width, // int width, cuasMotion.gpu_max_width, // int width,
cuasMotion.gpu_max_height, // int height, cuasMotion.gpu_max_height, // int height,
model_prefix+"-SOURCE-RA", //String title, model_prefix+(cuas_gaussian_ra?"-SOURCE-RG":"-SOURCE-RA"), //String title,
scene_titles); //String [] titles) scene_titles); //String [] titles)
imp_ra.getProcessor().setMinAndMax(-input_range/2, input_range/2); imp_ra.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) { if (!batch_mode) {
...@@ -3634,6 +3894,9 @@ public class CuasMotion { ...@@ -3634,6 +3894,9 @@ public class CuasMotion {
double lma_mink = clt_parameters.imp.cuas_lma_mink; // = 0.0; // Minimal K (overshoot) <0.007 double lma_mink = clt_parameters.imp.cuas_lma_mink; // = 0.0; // Minimal K (overshoot) <0.007
double lma_maxk = clt_parameters.imp.cuas_lma_maxk; // = 5.0; // Minimal K (overshoot) > 3.8 double lma_maxk = clt_parameters.imp.cuas_lma_maxk; // = 5.0; // Minimal K (overshoot) > 3.8
boolean remove_isolated= clt_parameters.imp.cuas_isolated; boolean remove_isolated= clt_parameters.imp.cuas_isolated;
double max_mismatch = clt_parameters.imp.cuas_max_mismatch; // 2;
boolean ignore_mismatch= clt_parameters.imp.cuas_ignore_mismatch;
int target_type = clt_parameters.imp.cuas_target_type; //0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe int target_type = clt_parameters.imp.cuas_target_type; //0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
double input_range = clt_parameters.imp.cuas_input_range; // 5; double input_range = clt_parameters.imp.cuas_input_range; // 5;
boolean scale2x = clt_parameters.imp.cuas_scale2x; //true; boolean scale2x = clt_parameters.imp.cuas_scale2x; //true;
...@@ -3647,6 +3910,8 @@ public class CuasMotion { ...@@ -3647,6 +3910,8 @@ public class CuasMotion {
boolean save_color = clt_parameters.imp.cuas_save_color; //true; boolean save_color = clt_parameters.imp.cuas_save_color; //true;
boolean save_video = clt_parameters.imp.cuas_save_video; //true; boolean save_video = clt_parameters.imp.cuas_save_video; //true;
boolean cuas_gaussian_ra = clt_parameters.imp.cuas_gaussian_ra; // use gaussian temporal Gaussian instead of running average
int start_frame = 0; int start_frame = 0;
int seq_length = corr_offset + corr_pairs; int seq_length = corr_offset + corr_pairs;
final int frame0 = start_frame + seq_length/2; final int frame0 = start_frame + seq_length/2;
...@@ -3802,9 +4067,27 @@ public class CuasMotion { ...@@ -3802,9 +4067,27 @@ public class CuasMotion {
parentCLT.saveImagePlusInModelDirectory(imp_filtered_combo); // ImagePlus imp) parentCLT.saveImagePlusInModelDirectory(imp_filtered_combo); // ImagePlus imp)
} }
double [][][] mismatch_ba = null;
if (remove_isolated) { if (remove_isolated) {
double interseq_scale = 0.5* corr_inc/corr_offset; // multiply target velocity to get offset in the middle between the key frames
double [][][][] ba_xy = getHalfBeforeAfterPixXY(
targets_vf_combo, // final double [][][] vector_field,
targets_lma_combo, // final double [][][] target_positions,
interseq_scale, // final double interseq_scale,
cuasMotion.tilesX, // final int tilesX,
debugLevel); // final int debugLevel)
boolean debug_mismatch = clt_parameters.imp.cuas_target_debug;
if (debug_mismatch) {
mismatch_ba = new double [targets_vf_combo.length][][];
}
targets_vf_combo = filterIsolatedTargets( targets_vf_combo = filterIsolatedTargets(
targets_vf_combo, // final double [][][] all_tiles, targets_vf_combo, // final double [][][] all_tiles,
ba_xy, // final double [][][][] ba_xy,
max_mismatch, // final double max_mismatch,
ignore_mismatch, // final boolean ignore_mismatch
mismatch_ba, // final double [][][] mismatch_ba,
remain, // final int [] remain, remain, // final int [] remain,
cuasMotion.tilesX); // final int tilesX) cuasMotion.tilesX); // final int tilesX)
// synchronize targets_lma_combo with targets_vf_combo // synchronize targets_lma_combo with targets_vf_combo
...@@ -3889,12 +4172,22 @@ public class CuasMotion { ...@@ -3889,12 +4172,22 @@ public class CuasMotion {
float [][] background = fpixels; float [][] background = fpixels;
String ra_bg_suffix=(ra_background? "-RABG":""); String ra_bg_suffix=(ra_background? "-RABG":"");
if (mismatch_ba != null) {
ra_bg_suffix += "-DBG";
}
if (ra_background) { if (ra_background) {
if (cuas_gaussian_ra) {
background = runningGaussian(
fpixels, // final float [][] fpixels,
corr_pairs, // final int ra_length,
cuasMotion.gpu_max_width); // final int width)
} else {
background = runningAverage( background = runningAverage(
fpixels, // final float [][] fpixels, fpixels, // final float [][] fpixels,
corr_pairs, // final int ra_length, corr_pairs, // final int ra_length,
cuasMotion.gpu_max_width); // final int width) cuasMotion.gpu_max_width); // final int width)
} }
}
float [][] replaced_targets = cuasMotion.shiftAndRenderTargets( float [][] replaced_targets = cuasMotion.shiftAndRenderTargets(
...@@ -3933,6 +4226,7 @@ public class CuasMotion { ...@@ -3933,6 +4226,7 @@ public class CuasMotion {
target_type, // final int target_type, // = 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe target_type, // final int target_type, // = 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
replaced_targets, // final float [][] fpixels, replaced_targets, // final float [][] fpixels,
targets60hz, // final double [][][] targets60hz, targets60hz, // final double [][][] targets60hz,
mismatch_ba, // final double [][][] mismatch_ba, if not null (in debug mode) print data in the image. this is [keyframes]
frame0, // final int frame0, frame0, // final int frame0,
corr_inc, // final int frame_step, corr_inc, // final int frame_step,
cuasMotion.gpu_max_width, // final int width, cuasMotion.gpu_max_width, // final int width,
...@@ -3962,12 +4256,15 @@ public class CuasMotion { ...@@ -3962,12 +4256,15 @@ public class CuasMotion {
public static double [][][] filterIsolatedTargets( public static double [][][] filterIsolatedTargets(
final double [][][] all_tiles, final double [][][] all_tiles,
final double [][][][] ba_xy,
final double max_mismatch, // if <=0, do not calculate mismatch_ba and filter
final boolean ignore_mismatch,
final double [][][] mismatch_ba, // if not null, will provide mismatches (before, after) and still keep them. Then output debug data in the final image with targets
final int [] remain, final int [] remain,
final int tilesX) { final int tilesX) {
final int num_seq = all_tiles.length; final int num_seq = all_tiles.length;
final int num_tiles = all_tiles[0].length; final int num_tiles = all_tiles[0].length;
final double [][][] filtered_tiles = new double [num_seq][num_tiles][]; final double [][][] filtered_tiles = new double [num_seq][num_tiles][];
final Thread[] threads = ImageDtt.newThreadArray(); final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
...@@ -3975,6 +4272,9 @@ public class CuasMotion { ...@@ -3975,6 +4272,9 @@ public class CuasMotion {
public void run() { public void run() {
TileNeibs tn = new TileNeibs(tilesX, num_tiles/tilesX); TileNeibs tn = new TileNeibs(tilesX, num_tiles/tilesX);
for (int nSeq = ai.getAndIncrement(); nSeq < num_seq; nSeq = ai.getAndIncrement()) { for (int nSeq = ai.getAndIncrement(); nSeq < num_seq; nSeq = ai.getAndIncrement()) {
if (mismatch_ba != null) {
mismatch_ba[nSeq] = new double [num_tiles][];
}
if (remain != null) { if (remain != null) {
remain[nSeq] = 0; remain[nSeq] = 0;
} }
...@@ -3998,6 +4298,45 @@ public class CuasMotion { ...@@ -3998,6 +4298,45 @@ public class CuasMotion {
has_neib = false; has_neib = false;
} }
if (has_neib) { if (has_neib) {
if (max_mismatch > 0) {
double [] mm = {Double.NaN, Double.NaN};
for (int dseq = -1; dseq <= 1; dseq+=2) {
double [] this_ba = ba_xy[nSeq][ntile][(dseq > 0) ? 1 : 0];
double [] other_ba = null;
int nSeq1 = nSeq+dseq;
if ((nSeq1 >= 0) && (nSeq1 < num_seq)) {
get_ba: {
if (ba_xy[nSeq1][ntile] != null) {
other_ba = ba_xy[nSeq1][ntile][(dseq > 0) ? 0 : 1];
break get_ba;
}
for (int dir = 0; dir < 8; dir++) {
int tile1 = tn.getNeibIndex(ntile, dir);
if ((tile1 >= 0) && (ba_xy[nSeq1][tile1] != null)) {
other_ba = ba_xy[nSeq1][tile1][(dseq > 0) ? 0 : 1];
break get_ba;
}
}
}
if (other_ba != null) {
double dx = this_ba[0] - other_ba[0];
double dy = this_ba[1] - other_ba[1];
mm[(dseq > 0) ? 1 : 0] = Math.sqrt(dx*dx + dy*dy);
}
}
}
if (mismatch_ba != null) {
mismatch_ba[nSeq][ntile] = mm;
}
if (!ignore_mismatch){
if (mm[0] > max_mismatch) {
continue; // for (int ntile = 0; ntile < num_tiles; ntile++) if (all_tiles[nSeq][ntile] != null) {
}
if (mm[1] > max_mismatch) {
continue; // for (int ntile = 0; ntile < num_tiles; ntile++) if (all_tiles[nSeq][ntile] != null) {
}
}
}
filtered_tiles[nSeq][ntile] = all_tiles[nSeq][ntile]; // clone()? filtered_tiles[nSeq][ntile] = all_tiles[nSeq][ntile]; // clone()?
if (remain != null) { if (remain != null) {
remain[nSeq]++; remain[nSeq]++;
......
...@@ -707,6 +707,7 @@ min_str_neib_fpn 0.35 ...@@ -707,6 +707,7 @@ min_str_neib_fpn 0.35
public boolean cuas_smooth = true; // used cosine window when averaging correlations public boolean cuas_smooth = true; // used cosine window when averaging correlations
public int cuas_corr_pairs = 50; // number of correlation pairs to accumulate public int cuas_corr_pairs = 50; // number of correlation pairs to accumulate
public int cuas_corr_offset = 20; // offset between motion detection pairs public int cuas_corr_offset = 20; // offset between motion detection pairs
public boolean cuas_gaussian_ra = true; // use gaussian temporal Gaussian instead of running average
public int cuas_temporal_um = 100; // temporal "unsharp mask" - subtract running public int cuas_temporal_um = 100; // temporal "unsharp mask" - subtract running
public double cuas_tum_threshold = 5.0; // if >0, remove outliers frim the running average and recalculate RA public double cuas_tum_threshold = 5.0; // if >0, remove outliers frim the running average and recalculate RA
...@@ -754,6 +755,9 @@ min_str_neib_fpn 0.35 ...@@ -754,6 +755,9 @@ min_str_neib_fpn 0.35
public double cuas_lma_maxk = 5.0; // Maximal K (overshoot) = 5.0 (>3.8) public double cuas_lma_maxk = 5.0; // Maximal K (overshoot) = 5.0 (>3.8)
public boolean cuas_isolated = true; // remove targets that do not have neighbors before/after public boolean cuas_isolated = true; // remove targets that do not have neighbors before/after
public double cuas_max_mismatch = 2.0; // maximal position error between consecutive scene sequences
public boolean cuas_ignore_mismatch = false; // calculate mismatch but do not remove
public double cuas_mask_width = 9; public double cuas_mask_width = 9;
...@@ -793,7 +797,7 @@ min_str_neib_fpn 0.35 ...@@ -793,7 +797,7 @@ min_str_neib_fpn 0.35
public boolean cuas_debug = false; // save debug images (and show them if not in batch mode) public boolean cuas_debug = false; // save debug images (and show them if not in batch mode)
public boolean cuas_step_debug = false; // save debug images during per-step cuas recalculation (and show them if not in batch mode) public boolean cuas_step_debug = false; // save debug images during per-step cuas recalculation (and show them if not in batch mode)
public boolean cuas_target_debug = false; // save debug images during per-step cuas recalculation (and show them if not in batch mode)
public boolean cuas_overwrite = false; // overwrite num_orient and num_accum public boolean cuas_overwrite = false; // overwrite num_orient and num_accum
public int cuas_num_orient = 2; // initial value for num_orient public int cuas_num_orient = 2; // initial value for num_orient
public int cuas_num_accum = 1; // initial value for num_accum public int cuas_num_accum = 1; // initial value for num_accum
...@@ -2213,6 +2217,8 @@ min_str_neib_fpn 0.35 ...@@ -2213,6 +2217,8 @@ min_str_neib_fpn 0.35
"The number of correlation pairs to accumulate."); "The number of correlation pairs to accumulate.");
gd.addNumericField("Pairs offset", this.cuas_corr_offset, 0,3,"scenes", gd.addNumericField("Pairs offset", this.cuas_corr_offset, 0,3,"scenes",
"Offset between the correlation pairs"); "Offset between the correlation pairs");
gd.addCheckbox ("Gaussian instead of Running Average", this.cuas_gaussian_ra,
"Use gaussian temporal Gaussian instead of running average.");
gd.addNumericField("Temporal unsharp mask length", this.cuas_temporal_um, 0,3,"scenes", gd.addNumericField("Temporal unsharp mask length", this.cuas_temporal_um, 0,3,"scenes",
"Subtract running average this long."); "Subtract running average this long.");
gd.addNumericField("Temporal UM threshold", this.cuas_tum_threshold, 5,8,"", gd.addNumericField("Temporal UM threshold", this.cuas_tum_threshold, 5,8,"",
...@@ -2284,7 +2290,7 @@ min_str_neib_fpn 0.35 ...@@ -2284,7 +2290,7 @@ min_str_neib_fpn 0.35
"Finish fitting when the relative RMS improvement drops below this value."); "Finish fitting when the relative RMS improvement drops below this value.");
gd.addNumericField("LMA iterations", this.cuas_num_iter, 0,3,"", gd.addNumericField("LMA iterations", this.cuas_num_iter, 0,3,"",
"Maximal number of the LMA iterations."); "Maximal number of the LMA iterations.");
gd.addMessage("--- Moving target discrimination parameters theresholds ---"); gd.addMessage("--- Moving target discrimination parameters thresholds ---");
gd.addNumericField("Maximal RMS", this.cuas_lma_rms, 5,8,"", gd.addNumericField("Maximal RMS", this.cuas_lma_rms, 5,8,"",
"Maximal RMS for target that should match always, regardless of the amplitude."); "Maximal RMS for target that should match always, regardless of the amplitude.");
gd.addNumericField("Maximal sufficient RMS", this.cuas_lma_arms, 5,8,"", gd.addNumericField("Maximal sufficient RMS", this.cuas_lma_arms, 5,8,"",
...@@ -2302,7 +2308,10 @@ min_str_neib_fpn 0.35 ...@@ -2302,7 +2308,10 @@ min_str_neib_fpn 0.35
gd.addCheckbox ("Remove single-frame targets", this.cuas_isolated, gd.addCheckbox ("Remove single-frame targets", this.cuas_isolated,
"Remove targets that do not have neighbors before/afte."); "Remove targets that do not have neighbors before/afte.");
gd.addNumericField("Remove by mismatch", this.cuas_max_mismatch, 5,8,"pix",
"Maximal position error between consecutive scene sequences.");
gd.addCheckbox ("Ignore mismatch", this.cuas_ignore_mismatch,
"Calculate mismatch, but keep targets for debugging (see cuas_target_debug).");
gd.addMessage("=== Targets video generation (see also Vidoe/Stereo tab) ==="); gd.addMessage("=== Targets video generation (see also Vidoe/Stereo tab) ===");
...@@ -2375,6 +2384,8 @@ min_str_neib_fpn 0.35 ...@@ -2375,6 +2384,8 @@ min_str_neib_fpn 0.35
"Save CUAS-related debug images and show them in non-batch mode."); "Save CUAS-related debug images and show them in non-batch mode.");
gd.addCheckbox ("Save/show debug images for each tuning step",this.cuas_step_debug, gd.addCheckbox ("Save/show debug images for each tuning step",this.cuas_step_debug,
"Save CUAS-related debug images during per-step cuas recalculation and show them in non-batch mode."); "Save CUAS-related debug images during per-step cuas recalculation and show them in non-batch mode.");
gd.addCheckbox ("Add debug to the target text", this.cuas_target_debug,
"Add additional debug text to the .");
gd.addCheckbox ("Overwrite number of performed adjustments", this.cuas_overwrite, gd.addCheckbox ("Overwrite number of performed adjustments", this.cuas_overwrite,
"Debug feature: overwrite actual number of performed orientation and disparity refinements to re-run them."); "Debug feature: overwrite actual number of performed orientation and disparity refinements to re-run them.");
...@@ -3329,7 +3340,7 @@ min_str_neib_fpn 0.35 ...@@ -3329,7 +3340,7 @@ min_str_neib_fpn 0.35
this.cuas_smooth = gd.getNextBoolean(); this.cuas_smooth = gd.getNextBoolean();
this.cuas_corr_pairs = (int) gd.getNextNumber(); this.cuas_corr_pairs = (int) gd.getNextNumber();
this.cuas_corr_offset = (int) gd.getNextNumber(); this.cuas_corr_offset = (int) gd.getNextNumber();
this.cuas_gaussian_ra = gd.getNextBoolean();
this.cuas_temporal_um = (int) gd.getNextNumber(); this.cuas_temporal_um = (int) gd.getNextNumber();
this.cuas_tum_threshold = gd.getNextNumber(); this.cuas_tum_threshold = gd.getNextNumber();
...@@ -3373,6 +3384,8 @@ min_str_neib_fpn 0.35 ...@@ -3373,6 +3384,8 @@ min_str_neib_fpn 0.35
this.cuas_lma_maxk = gd.getNextNumber(); this.cuas_lma_maxk = gd.getNextNumber();
this.cuas_isolated = gd.getNextBoolean(); this.cuas_isolated = gd.getNextBoolean();
this.cuas_max_mismatch= gd.getNextNumber();
this.cuas_ignore_mismatch = gd.getNextBoolean();
this.cuas_mask_width = gd.getNextNumber(); this.cuas_mask_width = gd.getNextNumber();
this.cuas_mask_blur = gd.getNextNumber(); this.cuas_mask_blur = gd.getNextNumber();
...@@ -3413,6 +3426,7 @@ min_str_neib_fpn 0.35 ...@@ -3413,6 +3426,7 @@ min_str_neib_fpn 0.35
this.cuas_el0 = gd.getNextNumber(); this.cuas_el0 = gd.getNextNumber();
this.cuas_debug = gd.getNextBoolean(); this.cuas_debug = gd.getNextBoolean();
this.cuas_target_debug = gd.getNextBoolean();
this.cuas_step_debug = gd.getNextBoolean(); this.cuas_step_debug = gd.getNextBoolean();
this.cuas_overwrite = gd.getNextBoolean(); this.cuas_overwrite = gd.getNextBoolean();
...@@ -4295,6 +4309,7 @@ min_str_neib_fpn 0.35 ...@@ -4295,6 +4309,7 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_smooth", this.cuas_smooth+""); // boolean properties.setProperty(prefix+"cuas_smooth", this.cuas_smooth+""); // boolean
properties.setProperty(prefix+"cuas_corr_pairs", this.cuas_corr_pairs+""); // int properties.setProperty(prefix+"cuas_corr_pairs", this.cuas_corr_pairs+""); // int
properties.setProperty(prefix+"cuas_corr_offset", this.cuas_corr_offset+""); // int properties.setProperty(prefix+"cuas_corr_offset", this.cuas_corr_offset+""); // int
properties.setProperty(prefix+"cuas_gaussian_ra", this.cuas_gaussian_ra+""); // boolean
properties.setProperty(prefix+"cuas_temporal_um", this.cuas_temporal_um+""); // int properties.setProperty(prefix+"cuas_temporal_um", this.cuas_temporal_um+""); // int
properties.setProperty(prefix+"cuas_tum_threshold", this.cuas_tum_threshold+""); // double properties.setProperty(prefix+"cuas_tum_threshold", this.cuas_tum_threshold+""); // double
...@@ -4338,6 +4353,8 @@ min_str_neib_fpn 0.35 ...@@ -4338,6 +4353,8 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_lma_maxk", this.cuas_lma_maxk+""); // double properties.setProperty(prefix+"cuas_lma_maxk", this.cuas_lma_maxk+""); // double
properties.setProperty(prefix+"cuas_isolated", this.cuas_isolated+""); // boolean properties.setProperty(prefix+"cuas_isolated", this.cuas_isolated+""); // boolean
properties.setProperty(prefix+"cuas_max_mismatch", this.cuas_max_mismatch+""); // double
properties.setProperty(prefix+"cuas_ignore_mismatch", this.cuas_ignore_mismatch+"");// boolean
properties.setProperty(prefix+"cuas_mask_width", this.cuas_mask_width+""); // double properties.setProperty(prefix+"cuas_mask_width", this.cuas_mask_width+""); // double
properties.setProperty(prefix+"cuas_mask_blur", this.cuas_mask_blur+""); // double properties.setProperty(prefix+"cuas_mask_blur", this.cuas_mask_blur+""); // double
...@@ -4374,6 +4391,7 @@ min_str_neib_fpn 0.35 ...@@ -4374,6 +4391,7 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_debug", this.cuas_debug+""); // boolean properties.setProperty(prefix+"cuas_debug", this.cuas_debug+""); // boolean
properties.setProperty(prefix+"cuas_step_debug", this.cuas_step_debug+""); // boolean properties.setProperty(prefix+"cuas_step_debug", this.cuas_step_debug+""); // boolean
properties.setProperty(prefix+"cuas_target_debug", this.cuas_target_debug+""); // boolean
properties.setProperty(prefix+"cuas_overwrite", this.cuas_overwrite+""); // boolean properties.setProperty(prefix+"cuas_overwrite", this.cuas_overwrite+""); // boolean
properties.setProperty(prefix+"cuas_num_orient", this.cuas_num_orient+""); // int properties.setProperty(prefix+"cuas_num_orient", this.cuas_num_orient+""); // int
...@@ -5227,6 +5245,7 @@ min_str_neib_fpn 0.35 ...@@ -5227,6 +5245,7 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_smooth")!=null) this.cuas_smooth=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_smooth")); if (properties.getProperty(prefix+"cuas_smooth")!=null) this.cuas_smooth=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_smooth"));
if (properties.getProperty(prefix+"cuas_corr_pairs")!=null) this.cuas_corr_pairs=Integer.parseInt(properties.getProperty(prefix+"cuas_corr_pairs")); if (properties.getProperty(prefix+"cuas_corr_pairs")!=null) this.cuas_corr_pairs=Integer.parseInt(properties.getProperty(prefix+"cuas_corr_pairs"));
if (properties.getProperty(prefix+"cuas_corr_offset")!=null) this.cuas_corr_offset=Integer.parseInt(properties.getProperty(prefix+"cuas_corr_offset")); if (properties.getProperty(prefix+"cuas_corr_offset")!=null) this.cuas_corr_offset=Integer.parseInt(properties.getProperty(prefix+"cuas_corr_offset"));
if (properties.getProperty(prefix+"cuas_gaussian_ra")!=null) this.cuas_gaussian_ra=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_gaussian_ra"));
if (properties.getProperty(prefix+"cuas_temporal_um")!=null) this.cuas_temporal_um=Integer.parseInt(properties.getProperty(prefix+"cuas_temporal_um")); if (properties.getProperty(prefix+"cuas_temporal_um")!=null) this.cuas_temporal_um=Integer.parseInt(properties.getProperty(prefix+"cuas_temporal_um"));
if (properties.getProperty(prefix+"cuas_tum_threshold")!=null) this.cuas_tum_threshold=Double.parseDouble(properties.getProperty(prefix+"cuas_tum_threshold")); if (properties.getProperty(prefix+"cuas_tum_threshold")!=null) this.cuas_tum_threshold=Double.parseDouble(properties.getProperty(prefix+"cuas_tum_threshold"));
...@@ -5271,6 +5290,8 @@ min_str_neib_fpn 0.35 ...@@ -5271,6 +5290,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_lma_maxk")!=null) this.cuas_lma_maxk=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_maxk")); if (properties.getProperty(prefix+"cuas_lma_maxk")!=null) this.cuas_lma_maxk=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_maxk"));
if (properties.getProperty(prefix+"cuas_isolated")!=null) this.cuas_isolated=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_isolated")); if (properties.getProperty(prefix+"cuas_isolated")!=null) this.cuas_isolated=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_isolated"));
if (properties.getProperty(prefix+"cuas_max_mismatch")!=null) this.cuas_max_mismatch=Double.parseDouble(properties.getProperty(prefix+"cuas_max_mismatch"));
if (properties.getProperty(prefix+"cuas_ignore_mismatch")!=null) this.cuas_ignore_mismatch=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_ignore_mismatch"));
if (properties.getProperty(prefix+"cuas_mask_width")!=null) this.cuas_mask_width=Double.parseDouble(properties.getProperty(prefix+"cuas_mask_width")); if (properties.getProperty(prefix+"cuas_mask_width")!=null) this.cuas_mask_width=Double.parseDouble(properties.getProperty(prefix+"cuas_mask_width"));
if (properties.getProperty(prefix+"cuas_mask_blur")!=null) this.cuas_mask_blur=Double.parseDouble(properties.getProperty(prefix+"cuas_mask_blur")); if (properties.getProperty(prefix+"cuas_mask_blur")!=null) this.cuas_mask_blur=Double.parseDouble(properties.getProperty(prefix+"cuas_mask_blur"));
...@@ -5307,6 +5328,7 @@ min_str_neib_fpn 0.35 ...@@ -5307,6 +5328,7 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_debug")!=null) this.cuas_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_debug")); if (properties.getProperty(prefix+"cuas_debug")!=null) this.cuas_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_debug"));
if (properties.getProperty(prefix+"cuas_step_debug")!=null) this.cuas_step_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_step_debug")); if (properties.getProperty(prefix+"cuas_step_debug")!=null) this.cuas_step_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_step_debug"));
if (properties.getProperty(prefix+"cuas_target_debug")!=null) this.cuas_target_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_target_debug"));
if (properties.getProperty(prefix+"cuas_overwrite")!=null) this.cuas_overwrite=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_overwrite")); if (properties.getProperty(prefix+"cuas_overwrite")!=null) this.cuas_overwrite=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_overwrite"));
if (properties.getProperty(prefix+"cuas_num_orient")!=null) this.cuas_num_orient=Integer.parseInt(properties.getProperty(prefix+"cuas_num_orient")); if (properties.getProperty(prefix+"cuas_num_orient")!=null) this.cuas_num_orient=Integer.parseInt(properties.getProperty(prefix+"cuas_num_orient"));
...@@ -6162,6 +6184,7 @@ min_str_neib_fpn 0.35 ...@@ -6162,6 +6184,7 @@ min_str_neib_fpn 0.35
imp.cuas_smooth = this.cuas_smooth; imp.cuas_smooth = this.cuas_smooth;
imp.cuas_corr_pairs = this.cuas_corr_pairs; imp.cuas_corr_pairs = this.cuas_corr_pairs;
imp.cuas_corr_offset = this.cuas_corr_offset; imp.cuas_corr_offset = this.cuas_corr_offset;
imp.cuas_gaussian_ra = this.cuas_gaussian_ra;
imp.cuas_temporal_um = this.cuas_temporal_um; imp.cuas_temporal_um = this.cuas_temporal_um;
imp.cuas_tum_threshold = this.cuas_tum_threshold; imp.cuas_tum_threshold = this.cuas_tum_threshold;
...@@ -6203,6 +6226,8 @@ min_str_neib_fpn 0.35 ...@@ -6203,6 +6226,8 @@ min_str_neib_fpn 0.35
imp.cuas_lma_maxk = this.cuas_lma_maxk; imp.cuas_lma_maxk = this.cuas_lma_maxk;
imp.cuas_isolated = this.cuas_isolated; imp.cuas_isolated = this.cuas_isolated;
imp.cuas_max_mismatch = this.cuas_max_mismatch;
imp.cuas_ignore_mismatch = this.cuas_ignore_mismatch;
imp.cuas_mask_width = this.cuas_mask_width; imp.cuas_mask_width = this.cuas_mask_width;
imp.cuas_mask_blur = this.cuas_mask_blur; imp.cuas_mask_blur = this.cuas_mask_blur;
...@@ -6237,6 +6262,7 @@ min_str_neib_fpn 0.35 ...@@ -6237,6 +6262,7 @@ min_str_neib_fpn 0.35
imp.cuas_debug = this.cuas_debug; imp.cuas_debug = this.cuas_debug;
imp.cuas_step_debug = this.cuas_step_debug; imp.cuas_step_debug = this.cuas_step_debug;
imp.cuas_target_debug = this.cuas_target_debug;
imp.cuas_overwrite = this.cuas_overwrite; imp.cuas_overwrite = this.cuas_overwrite;
imp.cuas_num_orient = this.cuas_num_orient; imp.cuas_num_orient = this.cuas_num_orient;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment