Commit 3f96868f authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: CuasPoseRT: outlier post-filter (-POSE-RT-RELIABLE-FILT) + two-pass selection

Per Andrey: a selected tile is BAD if its measured dxy is NaN in any scene or
exceeds curt_pose_max_dxy (absolute, default 0.25 pix) in at least one scene.
Survivors saved as -POSE-RT-RELIABLE-FILT.tiff; curt_pose_use_filt loads it on
a next run and ANDs with the strength selection (two-pass workflow: full run
calibrates the selection, subsequent runs use ~191 clean tiles instead of 1074
on the reference footage; kept-tile mean dxy 0.087 pix).
Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
parent 0063d548
......@@ -148,6 +148,24 @@ public class CuasPoseRT {
System.out.println("CuasPoseRT.testPoseSequence(): num_reliable="+num_reliable+
" (strength > "+min_str+")");
}
// Two-pass workflow: optionally AND with the outlier-filtered selection saved by a
// previous full run (-POSE-RT-RELIABLE-FILT: no NaN in any scene, dxy never > curt_pose_max_dxy)
if (clt_parameters.imp.curt_pose_use_filt) {
final ImagePlus imp_filt = center_CLT.readImagePlusFromModelDirectory("-POSE-RT-RELIABLE-FILT");
if (imp_filt != null) {
final float [] ffilt = (float []) imp_filt.getProcessor().getPixels();
int num_filt = 0;
for (int i = 0; i < reliable_ref.length; i++) {
reliable_ref[i] &= (i < ffilt.length) && (ffilt[i] > 0.5f);
if (reliable_ref[i]) num_filt++;
}
System.out.println("CuasPoseRT.testPoseSequence(): applied -POSE-RT-RELIABLE-FILT, "+
num_filt+" tiles remain (of "+num_reliable+" by strength)");
} else {
System.out.println("CuasPoseRT.testPoseSequence(): WARNING - curt_pose_use_filt is ON but "+
"-POSE-RT-RELIABLE-FILT.tiff not found, using the strength-only selection");
}
}
final double [][] pXpYD_center = OpticalFlow.transformToScenePxPyD(
null, // final Rectangle [] extra_woi,
center_disparity, // final double [] disparity_ref,
......@@ -382,6 +400,31 @@ public class CuasPoseRT {
new FloatProcessor(tilesX, tilesY, frel));
center_CLT.saveImagePlusInModelDirectory(null, imp_rel); // title as filename
}
// Outlier post-filter: a selected tile is BAD if its dxy is NaN in any scene or
// exceeds curt_pose_max_dxy (absolute, pix) in at least one scene. Survivors ->
// -POSE-RT-RELIABLE-FILT (consumed by a next run with curt_pose_use_filt).
final double max_dxy = clt_parameters.imp.curt_pose_max_dxy;
if ((max_dxy > 0) && !hyper_scenes.isEmpty()) {
final boolean [] keep = reliable_ref.clone();
for (float [][] comps : hyper_scenes) {
for (int i = 0; i < num_pix; i++) if (keep[i]) {
final float d = comps[3][i]; // dxy
if (Float.isNaN(d) || (d > max_dxy)) keep[i] = false;
}
}
int num_keep = 0;
final float [] fkeep = new float [num_pix];
for (int i = 0; i < num_pix; i++) {
fkeep[i] = keep[i] ? 1.0f : 0.0f;
if (keep[i]) num_keep++;
}
final ImagePlus imp_filt = new ImagePlus(center_CLT.getImageName()+"-POSE-RT-RELIABLE-FILT",
new FloatProcessor(tilesX, tilesY, fkeep));
center_CLT.saveImagePlusInModelDirectory(null, imp_filt);
System.out.println("CuasPoseRT.testPoseSequence(): outlier filter (dxy NaN or > "+max_dxy+
" pix in at least one scene): "+num_keep+" tiles kept of "+num_reliable+
" selected -> -POSE-RT-RELIABLE-FILT");
}
// -POSE-RT-HYPER: z = scenes (top slider), t = components (bottom slider) -
// same layout as renderSceneSequence make_hyper (component is the outer slice order)
if (!hyper_scenes.isEmpty()) {
......
......@@ -1129,6 +1129,8 @@ min_str_neib_fpn 0.35
public boolean curt_cond_test = false; // conditioning/calibration isolation test inside the curt_en branch: build the QuadCLT instances (borrowed calibration) then print per-sensor average spread (CuasMotion.perSensorAveragesFromTD) instead of normal RT detection; well-calibrated -> 16 sensor averages match (spread ~0). // By Claude on 07/01/2026
public boolean curt_pose_test = false; // RT pose-adjustment prototype (phase A) inside the curt_en branch: re-generate per-scene 3-angle poses against the virtual-center reference, ascending, prediction-seeded (CuasPoseRT.testPoseSequence) instead of RT detection; writes -POSE-RT-TEST.csv + fitted-vs-stored summary. // By Claude on 07/03/2026
public double curt_pose_str = 1.0; // reliable-tile strength threshold over the combo-DSI strength for the pose test tile selection (1.0 ~ old getReliableTiles population). // By Claude on 07/03/2026
public double curt_pose_max_dxy = 0.25; // post-filter (absolute, pix): a tile is BAD if its measured dxy exceeds this in at least one scene, or is NaN in any scene; survivors saved as -POSE-RT-RELIABLE-FILT (0 - skip). 0.25 ~ 70th percentile of all measurements on 1773135476_186641 (kept 191 of 1074 tiles, mean dxy 0.087). // By Claude on 07/04/2026
public boolean curt_pose_use_filt = false; // use the previously saved -POSE-RT-RELIABLE-FILT tile selection (AND with the strength threshold) - the two-pass workflow: full run generates the filtered selection, next run uses it. // By Claude on 07/04/2026
//=== LoG prefilter ===
public double curt_psf_radius = 1.0; // sensor PSF radius for LoG pre-filter
public double curt_n_sigma = 4.0; // cutoff LoG kernel array, number of sigmas
......@@ -3422,6 +3424,10 @@ min_str_neib_fpn 0.35
"RT pose-adjustment prototype (phase A): re-generate per-scene 3-angle poses against the virtual-center reference (ascending, prediction-seeded) instead of RT detection. Writes -POSE-RT-TEST.csv and a fitted-vs-stored summary.");
gd.addNumericField("Pose test reliable strength", this.curt_pose_str, 5,7,"", // By Claude on 07/03/2026
"Tile selection for the pose test: combo-DSI strength threshold (1.0 gives ~ the old getReliableTiles population).");
gd.addNumericField("Pose test max dxy (outlier filter)", this.curt_pose_max_dxy, 5,7,"pix", // By Claude on 07/04/2026
"Post-filter: a tile is BAD if measured dxy exceeds this in at least one scene or is NaN in any scene; survivors saved as -POSE-RT-RELIABLE-FILT.tiff. 0 - skip.");
gd.addCheckbox ("Pose test use filtered selection", this.curt_pose_use_filt, // By Claude on 07/04/2026
"Load the previously saved -POSE-RT-RELIABLE-FILT.tiff and AND it with the strength selection (two-pass workflow: full run generates it, next run uses it).");
gd.addMessage("=== LoG prefilter ===");
gd.addNumericField("Optical PSF radius", this.curt_psf_radius, 6,8,"pix",
......@@ -5016,6 +5022,8 @@ min_str_neib_fpn 0.35
this.curt_cond_test = gd.getNextBoolean();
this.curt_pose_test = gd.getNextBoolean(); // By Claude on 07/03/2026
this.curt_pose_str = gd.getNextNumber(); // By Claude on 07/03/2026
this.curt_pose_max_dxy = gd.getNextNumber(); // By Claude on 07/04/2026
this.curt_pose_use_filt = gd.getNextBoolean(); // By Claude on 07/04/2026
this.curt_psf_radius = gd.getNextNumber();
this.curt_n_sigma = gd.getNextNumber();
......@@ -6384,6 +6392,8 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"curt_cond_test", this.curt_cond_test+""); // boolean
properties.setProperty(prefix+"curt_pose_test", this.curt_pose_test+""); // boolean // By Claude on 07/03/2026
properties.setProperty(prefix+"curt_pose_str", this.curt_pose_str+""); // double // By Claude on 07/03/2026
properties.setProperty(prefix+"curt_pose_max_dxy", this.curt_pose_max_dxy+""); // double // By Claude on 07/04/2026
properties.setProperty(prefix+"curt_pose_use_filt", this.curt_pose_use_filt+""); // boolean // By Claude on 07/04/2026
properties.setProperty(prefix+"curt_psf_radius", this.curt_psf_radius+""); // double
properties.setProperty(prefix+"curt_n_sigma", this.curt_n_sigma+""); // double
......@@ -6786,6 +6796,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"curt_cond_test")!=null) this.curt_cond_test=Boolean.parseBoolean(properties.getProperty(prefix+"curt_cond_test"));
if (properties.getProperty(prefix+"curt_pose_test")!=null) this.curt_pose_test=Boolean.parseBoolean(properties.getProperty(prefix+"curt_pose_test")); // By Claude on 07/03/2026
if (properties.getProperty(prefix+"curt_pose_str")!=null) this.curt_pose_str=Double.parseDouble(properties.getProperty(prefix+"curt_pose_str")); // By Claude on 07/03/2026
if (properties.getProperty(prefix+"curt_pose_max_dxy")!=null) this.curt_pose_max_dxy=Double.parseDouble(properties.getProperty(prefix+"curt_pose_max_dxy")); // By Claude on 07/04/2026
if (properties.getProperty(prefix+"curt_pose_use_filt")!=null) this.curt_pose_use_filt=Boolean.parseBoolean(properties.getProperty(prefix+"curt_pose_use_filt")); // By Claude on 07/04/2026
if (properties.getProperty(prefix+"curt_psf_radius")!=null) this.curt_psf_radius=Double.parseDouble(properties.getProperty(prefix+"curt_psf_radius"));
if (properties.getProperty(prefix+"curt_n_sigma")!=null) this.curt_n_sigma=Double.parseDouble(properties.getProperty(prefix+"curt_n_sigma"));
......@@ -9073,6 +9085,8 @@ min_str_neib_fpn 0.35
imp.curt_cond_test = this.curt_cond_test;
imp.curt_pose_test = this.curt_pose_test; // By Claude on 07/03/2026
imp.curt_pose_str = this.curt_pose_str; // By Claude on 07/03/2026
imp.curt_pose_max_dxy = this.curt_pose_max_dxy; // By Claude on 07/04/2026
imp.curt_pose_use_filt = this.curt_pose_use_filt; // By Claude on 07/04/2026
imp.curt_psf_radius = this.curt_psf_radius;
imp.curt_n_sigma = this.curt_n_sigma;
// rleak0 imp.X copy removed 2026-06-20 (LReLU now LINEAR); predecessor code at git tag cuas-layer1. // By Claude on 06/20/2026
......
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