Commit 25c2bbf2 authored by Andrey Filippov's avatar Andrey Filippov

Detect mines with morning/evenimg pair

parent 2ebcdb9c
......@@ -104,7 +104,7 @@ public class ComboMatch {
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13_25-50-75-100m",
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75",
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m"};
int default_list_choice = 0; // files_lists_paths.length-1;
// String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.list";
// String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.data";
//maps_nov3_50-75
......@@ -148,10 +148,11 @@ public class ComboMatch {
boolean use_saved_collection = true; // false;
boolean save_collection = true;
boolean process_correlation = true; // use false to save new version of data
int num_tries_fit = 10;
boolean update_match = true; // use false to save new version of data
boolean render_match = true;
boolean render_match = false; // true;
boolean pattern_match = false;
boolean pattern_match = true; // false;
boolean bounds_to_indices = true;
int temp_mode = 1;
......@@ -166,10 +167,13 @@ public class ComboMatch {
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,900);
gd.addChoice ("Files list/data path (w/o extension):", files_lists_paths, files_lists_paths[files_lists_paths.length-1]);
gd.addChoice ("Files list/data path (w/o extension):", files_lists_paths, files_lists_paths[default_list_choice]);
gd.addCheckbox ("Use saved maps collection", use_saved_collection, "If false - use files list.");
gd.addCheckbox ("Save maps collection", save_collection, "Save maps collection to be able to restore.");
gd.addCheckbox ("Process correlations", process_correlation, "false to skip to just regenerate new save file.");
// int num_tries_fit = 10;
gd.addNumericField("Num tries fit", num_tries_fit, 0,4,"", "Try matching images this number of times");
gd.addCheckbox ("Update match if calculated", update_match, "Will update correlation match for a pair if found.");
gd.addCheckbox ("Render match", render_match, "Render a pair of matched images.");
......@@ -215,6 +219,7 @@ public class ComboMatch {
use_saved_collection = gd.getNextBoolean();
save_collection = gd.getNextBoolean();
process_correlation= gd.getNextBoolean();
num_tries_fit = (int) gd.getNextNumber();
update_match= gd.getNextBoolean();
render_match= gd.getNextBoolean();
......@@ -728,10 +733,10 @@ public class ComboMatch {
double [][][] affines = {affine0,affine1};
int [] zooms = {initial_zoom, min_zoom_lev, 1000,1000}; // make automatic
double scale = 2.0; // scale vectors when warping;
int num_tries = 5;
// int num_tries = 5; // make configurable
if (!process_correlation) {
zooms = new int[] {min_zoom_lev, 1000};
num_tries = 0;
num_tries_fit = 0;
update_match = false;
}
debugLevel = 0;
......@@ -750,7 +755,7 @@ public class ComboMatch {
frac_remove, // double frac_remove, // = 0.25
metric_error, // double metric_error,
ignore_prev_rms, // boolean ignore_prev_rms,
num_tries, // = 5int num_tries, // = 5
num_tries_fit, // = 5int num_tries, // = 5
true, // boolean calc_warp,
batch_mode, // boolean batch_mode,
gpu_pair, // String [] gpu_spair,
......@@ -814,6 +819,7 @@ public class ComboMatch {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Saved data to "+ orthoMapsCollection_path);
}
return true;
}
......@@ -942,7 +948,7 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
ImageDtt.THREADS_MAX, // int threadsMax,
debugLevel); // int debug_level)
}
if (debugLevel > 0) {
if (debugLevel > 1) {
String [] dbg_titles = {"x-raw","x_filled","y-raw","y_filled"};
double [][] dbg_img = {vf[0], vf_filled[0],vf[1], vf_filled[1]};
ShowDoubleFloatArrays.showArrays(
......
package com.elphel.imagej.orthomosaic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
public class ItemMatch {
public double [] combo_pxy; // combo image {pixel_x, pixel_y}
public double [] lla; // add later
public HashMap<String, ItemPatternMatch> pattern_matches = new HashMap<String, ItemPatternMatch>();
public ItemMatch (double [] combo_pxy) {
this.combo_pxy = combo_pxy;
}
public double [] getXY() {
return combo_pxy;
}
public int [] getIntXY() {
return new int [] {(int) Math.round(combo_pxy[0]), (int) Math.round(combo_pxy[1])};
}
public void addPatternMatches(
GroundObjectPattern groundObjectPattern,
double [] matches,
int best_sub) {
String pattern_path = groundObjectPattern.getPatternPath();
ItemPatternMatch match = pattern_matches.get(pattern_path);
if (match == null) {
match = new ItemPatternMatch(groundObjectPattern);
pattern_matches.put(pattern_path, match);
}
match.setMatches(matches);
match.setBestSub(best_sub);
}
public ItemPatternMatch getPatternMatch(GroundObjectPattern groundObjectPattern) {
return getPatternMatch(groundObjectPattern.getPatternPath());
}
public ItemPatternMatch getPatternMatch(String pattern_path) {
return pattern_matches.get(pattern_path);
}
public double [] getMatchValues(String pattern_path) {
ItemPatternMatch match = pattern_matches.get(pattern_path);
if (match == null) {
System.out.println("No matches found for pattern "+pattern_path);
return null;
}
return match.getMatches();
}
public double [] getMatchValues(GroundObjectPattern groundObjectPattern) {
return getMatchValues(groundObjectPattern.getPatternPath());
}
public double getMatchValue(String pattern_path, int indx) {
ItemPatternMatch match = pattern_matches.get(pattern_path);
if (match == null) {
System.out.println("No matches found for pattern "+pattern_path);
return Double.NaN;
}
return match.getMatch(indx);
}
public double getMatchValue(GroundObjectPattern groundObjectPattern, int indx) {
return getMatchValue(groundObjectPattern.getPatternPath(), indx);
}
public static ArrayList<Integer> sortByMatch(
ArrayList<ItemMatch> match_list,
GroundObjectPattern groundObjectPattern,
int indx){
String pattern_path = groundObjectPattern.getPatternPath();
return sortByMatch(match_list, pattern_path, indx);
}
public static ArrayList<Integer> sortByMatch(
ArrayList<ItemMatch> match_list,
String pattern_path,
int indx){
ArrayList<Integer> result_list= new ArrayList<Integer>(match_list.size());
for (int i = 0; i < match_list.size(); i++) {
result_list.add(i);
}
Collections.sort(result_list, new Comparator<Integer>() {
@Override
public int compare(Integer lhs, Integer rhs) {
double rhsd = match_list.get(rhs).getMatchValue(pattern_path, indx);
double lhsd = match_list.get(lhs).getMatchValue(pattern_path, indx);
return (rhsd > lhsd) ? 1 : (rhsd < lhsd) ? -1 : 0; // recreasing
}
});
return result_list;
}
}
package com.elphel.imagej.orthomosaic;
import java.util.Arrays;
public class ItemPatternMatch {
// public String pattern_path;
public double [] sub_matches; // array of sub-pattern match qualities. [0] - is usually combo, [1] - full pattern, [2+] - obscured
public int best_sub = -1; // best subpattern
public GroundObjectPattern groundObjectPattern;
public ItemPatternMatch(GroundObjectPattern groundObjectPattern) {
this.groundObjectPattern = groundObjectPattern;
}
public void setMatches(double [] matches) {
sub_matches = matches;
}
public void setMatch(int indx, double match_value) {
if (sub_matches == null) {
sub_matches = new double [indx+1];
Arrays.fill(sub_matches, Double.NaN);
} else if (sub_matches.length <= indx) {
double [] old_matches = sub_matches;
sub_matches = new double [indx+1];
Arrays.fill(sub_matches, Double.NaN);
System.arraycopy(old_matches, 0, sub_matches, 0, old_matches.length);
}
sub_matches[indx] = match_value;
}
public void setBestSub(int sub) {
best_sub = sub;
}
public int getBestSub() {
return best_sub;
}
public double getMatch(int indx) {
if ((sub_matches == null) || (sub_matches.length <= indx)) {
return Double.NaN;
}
return sub_matches[indx];
}
public double [] getMatches() {
return sub_matches;
}
public GroundObjectPattern getGroundObjectPattern() {
return groundObjectPattern;
}
}
......@@ -10,6 +10,8 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.tileprocessor.Correlation2d;
import com.elphel.imagej.tileprocessor.TileNeibs;
import Jama.EigenvalueDecomposition;
import Jama.Matrix;
import ij.ImagePlus;
import ij.gui.PointRoi;
......@@ -80,6 +82,240 @@ public class ObjectLocation {
return dcrop;
}
public static double [] extractObjectImage(
double [] center_xy,
int size,
double [] src_img,
int width) {
int height = src_img.length / width;
double [] dcrop = new double [size*size];
Arrays.fill(dcrop, Double.NaN);
int hsize = size/2;
int [] xy = {(int) Math.round(center_xy[0]), (int) Math.round(center_xy[1])};
boolean has_NaN=false;
for (int y = 0; y < size; y++) {
int src_y = y - hsize + xy[1];
if ((src_y >= 0) && (y < height)) {
for (int x = 0; x < size; x++) {
int src_x = x - hsize + xy[0];
if ((src_x >= 0) && (x < width)) {
double d = src_img[src_x + src_y * width];
dcrop[x + size * y] = d;
has_NaN |= Double.isNaN(d);
} else {
has_NaN=true;
}
}
} else {
has_NaN=true;
}
}
if (has_NaN) {
TileNeibs tn = new TileNeibs(size,size);
OrthoMap.fillNaNs(
dcrop, // double [] data,
tn, // TileNeibs tn,
3); // int min_neibs)
}
return dcrop;
}
/**
* Search for maximum within specified radius from the center or specified offset from the center
* @param data square data
* @param cent_xy offset from the square center to search
* @param radius search for maximum within this radius
* @param frac_max fraction of maximum to measure area
* @return {maximum, area, dist, x, y}. No interpolation yet, each returned value is integer.
* Returns null if no local maximum within area. x,y are offsets from the (provided) center
*/
public static double [] getMaxLocAreaNaN(
double [] data, // square data
double [] cent_xy, // if null, use center of the square
double radius, // search for maximum within this radius
double frac_max,
int debugLevel) {
double [] rslt = getMaxLocArea(
data, // square data
cent_xy, // if null, use center of the square
radius, // search for maximum within this radius
frac_max,
debugLevel);
if (rslt != null) {
return rslt;
} else {
return new double[] {Double.NaN,Double.NaN,Double.NaN,Double.NaN,Double.NaN,Double.NaN};
}
}
public static double [] getMaxLocArea(
double [] data, // square data
double [] cent_xy, // if null, use center of the square
double radius, // search for maximum within this radius
double frac_max,
int debugLevel) {
boolean debug = debugLevel > 1;
int size = (int) Math.sqrt(data.length);
if (cent_xy == null) {
cent_xy = new double [] {size/2, size/2};
}
double maxr2 = radius * radius;
double best_d = 0;
int best_indx = -1;
int min_x = Math.max(1, (int) Math.floor(cent_xy[0]-radius));
int min_y = Math.max(1, (int) Math.floor(cent_xy[1]-radius));
int max_x = Math.min(size-2, (int) Math.ceil(cent_xy[0]+radius));
int max_y = Math.min(size-2, (int) Math.ceil(cent_xy[1]+radius));
for (int y = min_y; y <= max_y; y++) { // do not search on very edges
double dy = (y-cent_xy[1]);
double y2 = dy*dy;
if (y2 < maxr2) {
for (int x = min_x; x <= max_x; x++) {
double dx = x - cent_xy[0];
double r2 = y2 + dx*dx;
if (r2 < maxr2) {
int indx = y * size + x;
double d = data[indx];
if (d > best_d) {
best_indx = indx;
best_d = d;
}
}
}
}
}
// is it local max?
if ((data[best_indx - 1] > best_d) || (data[best_indx + 1] > best_d) ||
(data[best_indx - size] > best_d) || (data[best_indx + size] > best_d)) {
return null; // on the edge, not a local max
}
boolean [] above_thresh = new boolean [data.length];
double thresh = best_d * frac_max;
for (int i = 0; i < data.length; i++) {
above_thresh[i] = data[i] > thresh;
}
int [] clusters = (new TileNeibs(size,size)).enumerateClusters(
above_thresh, // boolean [] tiles,
null, // int [] num_clusters,
false); // boolean ordered)
int center_cluster = clusters[best_indx];
double xc = best_indx % size - cent_xy[0];
double yc = best_indx / size - cent_xy[1];
double s0=0, sx=0, sy=0, sx2 = 0, sy2=0, sxy = 0;
for (int i = 0; i < clusters.length; i++) {
if (clusters[i] == center_cluster) {
double y = i / size - (yc + cent_xy[1]); //(yc + cent_xy[1]) - absolute, from (0,0)
double x = i % size - (xc + cent_xy[0]);
double w = data[i]-thresh;
s0 += w;
sx += w * x;
sy += w * y;
sx2 += w * x * x;
sy2 += w * y * y;
sxy += w * x * y;
}
}
double cxx = sx2 - sx * sx / s0, cyy= sy2 - sy * sy / s0, cxy = sxy - sx * sy / s0;
/*
* sum(Mi*(Xi-avg(X))^2) = SX2 - SX^2/S0
* sum(Mi*(Yi-avg(Y))^2) = SY2 - SY^2/S0
* sum(Mi*(Xi-avg(X)*(Yi-avg(Y))) = SXY - SX*SY / S0
*/
Matrix covar = new Matrix(new double[][] {{cxx, cxy},{cxy,cyy}});
double [] cent_offs = {sx/s0 + xc,sy/s0 + yc};
EigenvalueDecomposition eig = covar.eig();
double [] eigval = {eig.getD().get(0, 0),eig.getD().get(1, 1)};
Arrays.sort(eigval); // ascending
double elong = Math.sqrt(eigval[1]/eigval[0]);
double eff_rad = Math.sqrt(Math.sqrt(eigval[1]*eigval[0]));
double dist = Math.sqrt(cent_offs[0]*cent_offs[0] + cent_offs[1]*cent_offs[1]);
if (debug) {
System.out.println("\ncenter offset ["+(sx/s0)+","+(sy/s0)+"] , from center: ["+cent_offs[0]+","+cent_offs[1]+"]");
System.out.println("Covariance matrix:");
covar.print(8, 6);
System.out.println("eig.getV()");
eig.getV().print(8, 6);
System.out.println("eig.getD()");
eig.getD().print(8, 6);
System.out.println(String.format("best_d=%7.5f, rad=%6.3f, elong=%6.3f, dist=%6.3f, dx=%6.3f, dy=%6.3f",
best_d, eff_rad, elong, dist, cent_offs[0], cent_offs[1]));
}
return new double [] {best_d, eff_rad, elong, dist, cent_offs[0], cent_offs[1]} ;
}
public static double [] getMaxLocAreaInt(
double [] data, // square data
double [] cent_xy, // if null, use center of the square
double radius, // search for maximum within this radius
double frac_max) {
int size = (int) Math.sqrt(data.length);
if (cent_xy == null) {
cent_xy = new double [] {size/2, size/2};
}
double maxr2 = radius * radius;
double best_d = 0;
int best_indx = -1;
int min_x = Math.max(1, (int) Math.floor(cent_xy[0]-radius));
int min_y = Math.max(1, (int) Math.floor(cent_xy[1]-radius));
int max_x = Math.min(size-2, (int) Math.ceil(cent_xy[0]+radius));
int max_y = Math.min(size-2, (int) Math.ceil(cent_xy[1]+radius));
for (int y = min_y; y <= max_y; y++) { // do not search on very edges
double dy = (y-cent_xy[1]);
double y2 = dy*dy;
if (y2 < maxr2) {
for (int x = min_x; x <= max_x; x++) {
double dx = x - cent_xy[0];
double r2 = y2 + dx*dx;
if (r2 < maxr2) {
int indx = y * size + x;
double d = data[indx];
if (d > best_d) {
best_indx = indx;
best_d = d;
}
}
}
}
}
// is it local max?
if ((data[best_indx - 1] > best_d) || (data[best_indx + 1] > best_d) ||
(data[best_indx - size] > best_d) || (data[best_indx + size] > best_d)) {
return null; // on the edge, not a local max
}
boolean [] above_thresh = new boolean [data.length];
double thresh = best_d * frac_max;
for (int i = 0; i < data.length; i++) {
above_thresh[i] = data[i] > thresh;
}
int [] clusters = (new TileNeibs(size,size)).enumerateClusters(
above_thresh, // boolean [] tiles,
null, // int [] num_clusters,
false); // boolean ordered)
int center_cluster = clusters[best_indx];
double area_max = 0.0;
for (int i = 0; i < clusters.length; i++) {
if (clusters[i] == center_cluster) {
area_max += 1;
}
}
double x_max = best_indx % size - cent_xy[0];
double y_max = best_indx / size - cent_xy[1];
double dist = Math.sqrt(y_max * y_max + x_max * x_max);
return new double [] {best_d, area_max, dist, x_max, y_max} ;
}
public static double [] getPatternCenter(
double [] data_in,
......
......@@ -40,6 +40,8 @@ public class OrthoMapsCollection implements Serializable{
public static final String [] KEY_DIRS= {"rootDirectory", // from EyesisCorrectionParameters
"sourceDirectory","linkedModels","videoDirectory","x3dDirectory","resultsDirectory","scenesDirectory",
"kernelsDirectory", "patternsDirectory"};
public static final String [] NAME_FH = {"full","half"};
public static final String [] NAME_MO = {"main","other"};
OrthoMap [] ortho_maps;
transient HashMap<Double,Integer> map_index;
......@@ -1309,7 +1311,7 @@ public class OrthoMapsCollection implements Serializable{
if ((rms-prev_rms)/prev_rms < rel_improve) {
System.out.println("LMA RMSE worsened, but less than improvement threshold: new"+rms+" ("+ orthoPairLMA.getInitialRms()+"), prev="+prev_rms);
} else {
System.out.println("LMA RMSE worsened: new"+rms+" ("+ orthoPairLMA.getInitialRms()+"), prev="+prev_rms);
System.out.println("LMA RMSE worsened: new "+rms+" ("+ orthoPairLMA.getInitialRms()+"), prev="+prev_rms);
}
}
if (ignore_prev_rms) {
......@@ -1392,7 +1394,7 @@ public class OrthoMapsCollection implements Serializable{
tilesX, // final int gpu_tilesX, // 512
tile_woi, // final Rectangle tile_woi, // only width, height are used top-left corners are the same
scale, // final double scale,
1); // final int debugLevel);
1); // final int debugLevel); // vector_filed_filled - use 2
double [] tl_metric = {bounds_overlap_meters[0][0],bounds_overlap_meters[1][0]};
FineXYCorr warp = new FineXYCorr(
......@@ -1405,6 +1407,43 @@ public class OrthoMapsCollection implements Serializable{
return null;
}
/**
* Project object offset to along and perpendicular to the scenes offset
* @param object_offset object center pixel x and y offset between images (y - down)
* @param scene_offset pixel offset between images
* @return A pair of offsets: parallel (to scene offset) and perpendicular. Negative parallel
* offsets corresponds to objects above ground
*/
public static double [] projectOffsetOnVector(
double [] object_offset,
double [] scene_offset) {
double l1 = Math.sqrt(scene_offset[0]*scene_offset[0] + scene_offset[1]*scene_offset[1]);
double [] offs_rot = new double [2];
offs_rot[0] = ( object_offset[0]*scene_offset[0] + object_offset[1]*scene_offset[1]) / l1;
offs_rot[1] = (-object_offset[0]*scene_offset[1] + object_offset[1]*scene_offset[0]) / l1;
return offs_rot;
}
/**
* Estimate object height if its offset between image is caused by its elevation
* @param object_offset object center pixel x and y offset between images (y - down)
* @param scene_offset pixel offset between images
* @param zoom_level images zoom level
* @param agl scene (second) altitude above ground in meters
* @return Estimated object elevation above ground in meters
*/
public static double offsetToElevation(
double [] object_offset,
double [] scene_offset,
int zoom_level,
double agl) {
double l1 = Math.sqrt(scene_offset[0]*scene_offset[0] + scene_offset[1]*scene_offset[1]);
double offs_par = projectOffsetOnVector(object_offset, scene_offset)[0]; // *OrthoMap.getPixelSizeMeters(zoom_level);
return -agl * offs_par / l1 ;
}
public static Rectangle scaleRectangle(
Rectangle woi,
int tile_size){
......@@ -1622,7 +1661,7 @@ public class OrthoMapsCollection implements Serializable{
ImageDtt.THREADS_MAX, // int threadsMax,
debugLevel-1); // int debug_level)
}
if (debugLevel > 0) {
if (debugLevel > 1) {
String [] dbg_titles = {"x-raw","x_filled","y-raw","y_filled"};
double [][] dbg_img = {vf[0], vf_filled[0],vf[1], vf_filled[1]};
ShowDoubleFloatArrays.showArrays(
......@@ -1655,44 +1694,102 @@ public class OrthoMapsCollection implements Serializable{
double [][][] affines, // null or [indices.length][2][3]
FineXYCorr warp) { // use for a single pair only
double [] min_corrs = {0.01,0.005}; // morning/evening
double phaseCoeff = 0.5;
double [] min_corrs = {0.008, 0.0035}; // morning/evening
// double [] max_area = {60.0, 65.0}; // one per obsolete
// double frac_max = 0.5; // measure are at fraction of max
double [] phaseCoeff = {0.98,0.5};
double min_corr_full_rel = 0.75;
double full_preference = 1.4;
double max_min_ratio = 3.0;
boolean combine_full = true;
int corr_size = 128; // pix
double adv_radius = 30.0; // cm
double search_radius = 15; // look for other scene max within this distance from main
String object_type = "TM62";
double scale_warp = 1.0; // use 4?
int extr_size = 128;
boolean remove_dc = true;
// filters
boolean filt_keep = false; // list filtered out, but actually keep them
boolean filt_atonce = false; // apply main/second together, false - first filter main only
double filt_frac_max = 0.5; // measure are at fraction of max
double [][] filt_max_radius = {{1.0,1.0},{1.0,1.0}}; // [second/main][full/half] - inactive now
double [][] filt_elongation = {{1.5,1.5},{1.7,1.7}}; // [second/main][full/half] ellipse axis ratio
double [] filt_dist = {8.0,3.0}; // full offset and perpendicular to images offsets
int debugLevel = 1;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Correlate two images with patterns",1200,500);
GenericJTabbedDialog gd = new GenericJTabbedDialog("Correlate two images with patterns",1200,900);
gd.addNumericField("Minimal correlation, first", min_corrs[0], 5,7,"","Minimal correlation value to keep, first scene.");
gd.addNumericField("Minimal correlation, second", min_corrs[1], 5,7,"","Minimal correlation value to keep, secondscene.");
gd.addNumericField("Phase correlation coefficient", phaseCoeff, 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation.");
gd.addNumericField("Minimal correlation, second", min_corrs[1], 5,7,"","Minimal correlation value to keep, second scene.");
// gd.addNumericField("Maximal peak area, first", max_area[0], 5,7,"","Maximal cross-section area of the peak at certain height.");
// gd.addNumericField("Maximal peak area, second", max_area[1], 5,7,"","Maximal cross-section area of the peak at certain height.");
gd.addNumericField("Phase correlation main", phaseCoeff[0], 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation.");
gd.addNumericField("Phase correlation other", phaseCoeff[1], 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation.");
gd.addNumericField("Minimal relative full correlation", min_corr_full_rel, 5,7,"","Minimal relative correlation value with full circular pattern to keep.");
gd.addNumericField("Prefer full pattern", full_preference, 3,7,"","Prefer full pattern to partial; scale by this value.");
gd.addNumericField("Max/min halves ratio", max_min_ratio, 3,7,"","Ratio of halves best/worst to use half-pattern.");
gd.addCheckbox ("Combine with full pattern", combine_full, "Multiply by normalized full pattern correlation maximum.");
gd.addNumericField("Correlation size", corr_size, 0,4,"pix", "Should be power of 2.");
gd.addNumericField("Adversarial distance", adv_radius, 1,6,"pix", "Suppress weaker if they have closer strong ones.");
gd.addNumericField("Search other scene max", search_radius, 1,6,"pix", "Search for other scene max from the main one.");
gd.addStringField ("Object type", object_type, 20,"Object type/name.");
gd.addNumericField("Scale warp", scale_warp, 1,6,"x", "Scale second image warping.");
gd.addNumericField("Extract object size", extr_size, 0,4,"", "Size of square object image to extract.");
gd.addCheckbox ("Remove DC", remove_dc, "Remove DC in extracted object images.");
gd.addMessage("--- Filtering results ---");
gd.addCheckbox ("Keep filtered out", filt_keep, "List filtered out, but actaually keep them.");
gd.addCheckbox ("Apply filters at once", filt_atonce, "If false, first filter by main scene only, do not process secondary scene if main failed.");
gd.addNumericField("Peak hight fraction", filt_frac_max, 5,7,"","Fraction of the peak hight for eigenvlues (radius and elongation).");
gd.addNumericField("Max radius, main, full", filt_max_radius[0][0], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max radius, main, halves", filt_max_radius[0][1], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max radius, other, full", filt_max_radius[1][0], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max radius, other, half", filt_max_radius[1][1], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max elongation, main, full", filt_elongation[0][0], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Max elongation, main, halves", filt_elongation[0][1], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Max elongation, other, full", filt_elongation[1][0], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Max elongation, other, halves", filt_elongation[1][1], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Maximal offset", filt_dist[0], 5,7,"pix","Maximal other scene offset from the main.");
gd.addNumericField("Maximal offset perpendicular", filt_dist[1], 5,7,"pix","Maximal other scene offset perpendicular to offset between scenes.");
gd.addNumericField("Debug level", debugLevel, 0,4,"", "Debug level.");
gd.showDialog();
if (gd.wasCanceled()) return null;
min_corrs[0]= gd.getNextNumber();
min_corrs[1]= gd.getNextNumber();
phaseCoeff= gd.getNextNumber();
// max_area[0]= gd.getNextNumber();
// max_area[1]= gd.getNextNumber();
phaseCoeff[0]= gd.getNextNumber();
phaseCoeff[1]= gd.getNextNumber();
min_corr_full_rel= gd.getNextNumber();
full_preference= gd.getNextNumber();
max_min_ratio= gd.getNextNumber();
combine_full = gd.getNextBoolean();
corr_size= (int) gd.getNextNumber();
adv_radius= gd.getNextNumber();
search_radius= gd.getNextNumber();
object_type= gd.getNextString();
scale_warp = gd.getNextNumber();
extr_size= (int) gd.getNextNumber();
remove_dc= gd.getNextBoolean();
filt_keep= gd.getNextBoolean();
filt_atonce= gd.getNextBoolean();
filt_frac_max= gd.getNextNumber();
filt_max_radius[0][0]=gd.getNextNumber();
filt_max_radius[0][1]=gd.getNextNumber();
filt_max_radius[1][0]=gd.getNextNumber();
filt_max_radius[1][1]=gd.getNextNumber();
filt_elongation[0][0]=gd.getNextNumber();
filt_elongation[0][1]=gd.getNextNumber();
filt_elongation[1][0]=gd.getNextNumber();
filt_elongation[1][1]=gd.getNextNumber();
filt_dist[0] = gd.getNextNumber();
filt_dist[1] = gd.getNextNumber();
debugLevel= (int) gd.getNextNumber();
return patternMatchDual (
......@@ -1700,15 +1797,24 @@ public class OrthoMapsCollection implements Serializable{
affines, // double [][][] affines, // null or [indices.length][2][3]
warp, // FineXYCorr warp);
min_corrs, // double [] min_corrs, // one per
phaseCoeff, // double phaseCoeff,
phaseCoeff, // double [] phaseCoeff
min_corr_full_rel, // double min_corr_full_rel,
full_preference, // double full_preference,
max_min_ratio, // double max_min_ratio,
combine_full, // boolean combine_full,
corr_size, // int corr_size,
adv_radius, // double adv_radius, //
search_radius, // double search_radius, //
object_type, // String object_type,
scale_warp, // double scale_warp,
extr_size, // int extr_size,
remove_dc, // boolean remove_dc,
filt_keep, // boolean filt_keep,
filt_atonce, // boolean filt_atonce,
filt_frac_max, // double frac_max, // measure are at fraction of max
filt_max_radius, // double [][] filt_max_radius,
filt_elongation, // double [][] filt_elongation,
filt_dist, // double [] filt_dist,
debugLevel); // int debugLevel)
}
......@@ -1717,15 +1823,25 @@ public class OrthoMapsCollection implements Serializable{
double [][][] affines, // null or [indices.length][2][3]
FineXYCorr warp, // use for a single pair only
double [] min_corrs, // one per
double phaseCoeff,
double [] phaseCoeff, // one per
double min_corr_full_rel,
double full_preference,
double max_min_ratio,
boolean combine_full,
int corr_size,
double adv_radius, //
double search_radius, // look for other scene max within this distance from main
String object_type,
double scale_warp,
int extr_size,
boolean remove_dc,
boolean filt_keep,
boolean filt_atonce,
double frac_max, // measure are at fraction of max
double [][] filt_max_radius,
double [][] filt_elongation,
double [] filt_dist,
int debugLevel) {
warp.scale_warp = scale_warp;
int corr_radius = (int) (Math.sqrt(0.5)* adv_radius) -1 ;
......@@ -1753,28 +1869,7 @@ public class OrthoMapsCollection implements Serializable{
int width = wh[0];
int height = wh[1];
double [][] src_marks = null;
/*
PointRoi pRoi = (PointRoi) imp_src.getRoi();
FloatPolygon fp = pRoi.getContainedFloatPoints();
if (fp != null) {
src_marks = new double[fp.npoints][2];
for (int i = 0; i < src_marks.length; i++) {
src_marks[i][0] = fp.xpoints[i];
src_marks[i][1] = fp.ypoints[i];
}
}
*/
// double [] agls = new double[indices.length];
// LocalDateTime [] dts = new LocalDateTime[indices.length];
/*
int [] zoom_levs = new int[indices.length];
for (int scene_num = 0; scene_num < indices.length; scene_num++) {
// agls[n] = ortho_maps[indices[n]].getAGL();
// dts[n] = ortho_maps[indices[n]].getLocalDateTime();
zoom_levs[scene_num]= ortho_maps[indices[scene_num]].getOriginalZoomLevel();
}
*/
double [][][] patterns_all = new double [indices.length][][];
double [][] kernels_all = new double [indices.length][];
......@@ -1798,7 +1893,18 @@ public class OrthoMapsCollection implements Serializable{
double [][] convolved_merged = new double[indices.length][];
ImagePlus [] imps_patt_corrs = new ImagePlus[indices.length];
ImagePlus [] imps_patt_conv = new ImagePlus[indices.length];
for (int scene_num = 0; scene_num < indices.length; scene_num++) {
ImagePlus [] imps_extracted = new ImagePlus[indices.length];
ImagePlus [] imps_extracted_corr = new ImagePlus[indices.length];
ImagePlus [] imps_extracted_corr_half = new ImagePlus[indices.length];
ArrayList <ItemMatch> matches_list = new ArrayList <ItemMatch>();
double [][][] extracted_objects = new double [indices.length][][];
double [][][] extr_corr = new double [indices.length][][];
double [][][] extr_corr_half = new double [indices.length][][];
double [][][][] filter_data = new double [indices.length][][][]; // [scene][max][0-full, 1 - half][0- max, 1 - area, 2 - distance]
for (int scene_num = 0; scene_num < indices.length; scene_num++) { // will probably just use first one, second - derivative
gops[scene_num] = GroundObjectPattern.getPattern(
object_type, // String object_type,
ortho_maps[indices[scene_num]].getLocalDateTime(), // LocalDateTime utcDateTime,
......@@ -1859,13 +1965,19 @@ public class OrthoMapsCollection implements Serializable{
kernels_all[scene_num], // final double [] kernel,
corr_size); // final int width)
}
}
}
// Splitting - above done for both scenes, below - just for the main one
for (int scene_num = 0; scene_num < indices.length; scene_num++) { // will probably just use first one, second - derivative
for (int n = 0; n < patterns_all[scene_num].length; n++) {
corrs_out[scene_num][n]= OrthoMap.correlateWithPattern(
dmulti[scene_num], // final double [] data,
width, // final int width,
corr_size, // final int psize, // power of 2, such as 64
corr_patterns[scene_num][n], // final double [] pattern, // [psize*psize]
false, // final boolean convolve, // convolve, not correlate
phaseCoeff, // final double phaseCoeff,
phaseCoeff[scene_num], // final double phaseCoeff,
debugLevel); // final int debugLevel) {
}
String [] patt_titles = new String[corrs_out[scene_num].length];
......@@ -1893,7 +2005,7 @@ public class OrthoMapsCollection implements Serializable{
min_corrs_full[scene_num] = min_corrs[scene_num] * min_corr_full_rel;
// TODO: scale adv_radius, corr_radius
object_lists.add(OrthoMap.combineDirCorrs (
ArrayList<Point> plist =OrthoMap.combineDirCorrs (
corrs_out[scene_num], // final double [][] corrs,
width, // final int width,
fullcorr[scene_num], // final double [] fullcorr_in,
......@@ -1905,7 +2017,419 @@ public class OrthoMapsCollection implements Serializable{
max_min_ratio, // final double max_min_ratio,
combine_full, // final boolean combine_full, // multiply by normalized full pattern correlation maximum
adv_radius, // final double adv_radius,
corr_radius)); // final int corr_radius)
corr_radius); // final int corr_radius)
// GroundObjectPattern gop = gops[scene_num];
for (Point p : plist) {
double [] matches = new double [corrs_out[scene_num].length + 1];
double [] match_xy = {p.x%width, p.x/width}; // here int values
int best_patt = p.y + 1;
matches[0] = bestcorr[scene_num][p.x];
for (int i = 1; i < matches.length; i++) {
matches[i] = corrs_out[scene_num][i-1][p.x];
}
ItemMatch item_match = new ItemMatch (match_xy);
item_match.addPatternMatches(
gops[scene_num], // GroundObjectPattern groundObjectPattern,
matches, // double [] matches,
best_patt); // int best_sub);
matches_list.add(item_match);
}
int sort_pattern_index = 0; //combo. 1 - full pattern
ArrayList<Integer> match_sort = ItemMatch.sortByMatch(
matches_list, // ArrayList<ItemMatch> match_list,
gops[scene_num], // GroundObjectPattern groundObjectPattern,
sort_pattern_index); // int indx)
// Print all results
System.out.println("Match candidates ("+match_sort.size()+
") that exceed minimal correlation strength of "+min_corrs[scene_num]);
// remove non-overlapped from the list
int num_non_overlap = 0;
for (int i = match_sort.size()-1; i >=0; i--) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
int [] icenter_xy = match.getIntXY();
for (int sn = 1; sn < indices.length; sn++) {
if (Double.isNaN(dmulti[sn][icenter_xy[0] + icenter_xy[1] * width])) {
match_sort.remove(i);
if (debugLevel > -1) {
System.out.println("Removed object at x="+icenter_xy[0]+", y="+icenter_xy[1]+
" as it is not in the scenes overlap area");
}
num_non_overlap++;
break;
}
}
}
if (num_non_overlap > 0) {
System.out.println("Removed "+num_non_overlap+" objects outside of the scenes overlap, "+match_sort.size()+" remain");
}
System.out.print(String.format("%4s: %9s %8s %3s"," # ", " x/y ", " best ","sub"));
for (int j = 0; j < (corrs_out[scene_num].length + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
System.out.println();
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gops[scene_num]);
int [] icenter_xy = match.getIntXY();
System.out.print(String.format("%4d: %4d/%4d %8.5f %3d",
i,
icenter_xy[0],icenter_xy[1],
match.getMatchValue(gops[scene_num],sort_pattern_index),
match.getPatternMatch(gops[scene_num]).getBestSub()));
for (int j = 0; j < match_values.length; j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8.5f",match_values[j]));
if (j == (match_values.length-1)) {
System.out.println();
} else {
System.out.print(",");
}
}
}
// boolean remove_dc = true;
if (scene_num == 0) {
double [][][] extract_display = new double [extracted_objects.length][][]; // to keep/display both dc/no-dc versions
PointRoi roi = new PointRoi();
roi.setOptions("nolabel"); // label");
for (int mn=0; mn < match_sort.size(); mn++) {
roi.addPoint(extr_size/2,extr_size/2,mn+1); // ,1);
}
// extract already calculated correlations for scene 0
filter_data[scene_num] = new double[match_sort.size()][2][]; // [scene][max][0-full, 1 - half][0- max, 1 - area, 2 - distance]
extr_corr[scene_num] = new double [match_sort.size()][]; // extracted_objects[scene_num].length][];
extr_corr_half[scene_num] = new double [match_sort.size()][]; // extracted_objects[scene_num].length][];
for (int mn=0; mn < match_sort.size(); mn++) {
int indx =match_sort.get(mn);
ItemMatch match = matches_list.get(indx);
int best_patt = match.getPatternMatch(gops[scene_num]).getBestSub() - 1;
double [] center_xy = match.getXY();
extr_corr[scene_num][mn] = ObjectLocation.extractObjectImage(
center_xy, // double [] center_xy,
extr_size, // int size,
corrs_out[scene_num][0], // double [] src_img,
width); // int width)
extr_corr_half[scene_num][mn] = ObjectLocation.extractObjectImage(
center_xy, // double [] center_xy,
extr_size, // int size,
corrs_out[scene_num][best_patt], // double [] src_img,
width); // int width)
filter_data[scene_num][mn][0] = ObjectLocation.getMaxLocAreaNaN(
extr_corr[scene_num][mn], // double [] data, // square data
null, // double [] cent_xy, // if null, use center of the square
search_radius, // double radius, // search for maximum within this radius. Should radius be 0 here?
frac_max, // double frac_max)
debugLevel); // final int debugLevel) {
filter_data[scene_num][mn][1] = ObjectLocation.getMaxLocAreaNaN(
extr_corr_half[scene_num][mn], // double [] data, // square data
null, // double [] cent_xy, // if null, use center of the square
search_radius, // double radius, // search for maximum within this radius. Should radius be 0 here?
frac_max, // double frac_max)
debugLevel); // final int debugLevel) {
}
double [] scene_xy_offset = {centers[1][0]-centers[0][0],centers[1][1]-centers[0][1]};
boolean [] removed = null;
if (!filt_atonce) {
boolean[] filt_main_other = {true,false};
//int num_removed =
removed = filterCandidates(
filt_keep, // boolean filt_keep,
filt_main_other, // new boolean [] filt_main_other,
min_corrs, //double [] min_corrs, // one per
min_corr_full_rel, // double min_corr_full_rel,
filt_max_radius, // double [][] filt_max_radius,
filt_elongation, // double [][] filt_elongation,
filt_dist, // double [] filt_dist,
filter_data, // double [][][][] filter_data,
scene_xy_offset, // double [] scene_xy_offset, //second scene vertical projection offset from the first scene
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
debugLevel); // int debugLevel )
if (!filt_keep && (removed.length > match_sort.size())) { // decimate data arrays
for (int sn = 0; sn < filter_data.length; sn++) {
filter_data[sn] = removeFilteredOut (filter_data[sn], removed);
extracted_objects[sn] = removeFilteredOut (extracted_objects[sn], removed);
extr_corr[sn] = removeFilteredOut (extr_corr[sn], removed);
extr_corr_half[sn] = removeFilteredOut (extr_corr_half[sn], removed);
}
removed = new boolean [match_sort.size()];
}
// System.out.println(num_removed+ "scenes filtered out, "+match_sort.size()+" candidates remain");
}
// show extracted scenes after some were optionally removed by the main scene filters
for (int sn = 0; sn < indices.length; sn++) {
showExtractedImages(
ortho_maps[indices[scene_num]].getName()+"-prefilter", // String prefix
sn, //int scene_num,
sort_pattern_index, // int sort_pattern_index,
extr_size, // int extr_size,
gops[scene_num], // GroundObjectPattern gop,
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
extracted_objects, // double[][][] extracted_objects, // may be null - will not be generated
extract_display, // double[][][] extract_display, // may be null - will not be displayed
dmulti, // double[][] dmulti,
width, // int width,
remove_dc, // boolean remove_dc,
imps_extracted, //ImagePlus[] imps_extracted, // may be null - will not be displayed
debugLevel); // int debugLevel
}
// display extracted correlations for the main scene:
if (debugLevel > 0) {
showExtractedCorrelations(
ortho_maps[indices[scene_num]].getName()+"-prefilter", // String prefix
scene_num, // int scene_num,
phaseCoeff, // double [] phaseCoeff,
extr_corr, // double [][][] extr_corr,
extr_corr_half, // double [][][] extr_corr_half,
extr_size, // int extr_size,
gops[scene_num], // GroundObjectPattern gop,
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
imps_extracted_corr, // ImagePlus[] imps_extracted_corr, // may be null - will not be displayed
imps_extracted_corr_half); // ImagePlus[] imps_extracted_corr_half
}
// Correlate second scene only for selected fragments
for (int scene_other = 1; scene_other < indices.length; scene_other++) { // normally just 1
filter_data[scene_other] = new double[match_sort.size()][2][]; // [scene][max][0-full, 1 - half][0- max, 1 - area, 2 - distance]
double [][] extr_data = new double [match_sort.size()][]; //extracted_objects[scene_other].length][];
extr_corr[scene_other] = new double [match_sort.size()][]; //extracted_objects[scene_other].length][];
extr_corr_half[scene_other] = new double [match_sort.size()][]; //extracted_objects[scene_other].length][];
for (int mn=0; mn < match_sort.size(); mn++) {
int indx =match_sort.get(mn);
ItemMatch match = matches_list.get(indx);
int best_patt = match.getPatternMatch(gops[scene_num]).getBestSub() - 1;
extr_data[mn] = extract_display[scene_other][mn].clone();
OrthoMap.removeDC(extr_data[mn]); // now always removing DC
extr_corr[scene_other][mn] =OrthoMap.correlateWithPattern(
extr_data[mn], // final double [] data,
corr_size, // final int width,
corr_size, // final int psize, // power of 2, such as 64
corr_patterns[scene_other][0], // final double [] pattern, // [psize*psize]
false, // final boolean convolve, // convolve, not correlate
phaseCoeff[scene_other], // final double phaseCoeff,
debugLevel); // final int debugLevel) {
if (best_patt > 0) { // not full match
extr_corr_half[scene_other][mn] =OrthoMap.correlateWithPattern(
extr_data[mn], // final double [] data,
corr_size, // final int width,
corr_size, // final int psize, // power of 2, such as 64
corr_patterns[scene_other][best_patt], // final double [] pattern, // [psize*psize]
false, // final boolean convolve, // convolve, not correlate
phaseCoeff[scene_other], // final double phaseCoeff,
debugLevel); // final int debugLevel) {
} else {
// Maybe correlate with all and make sure the best is +/- 1 from the main scene
extr_corr_half[scene_other][mn] = extr_corr[scene_other][mn];
}
filter_data[scene_other][mn][0] = ObjectLocation.getMaxLocAreaNaN(
extr_corr[scene_other][mn], // double [] data, // square data
null, // double [] cent_xy, // if null, use center of the square
search_radius, // double radius, // search for maximum within this radius. Should radius be 0 here?
frac_max, // double frac_max)
debugLevel); // final int debugLevel) {
filter_data[scene_other][mn][1] = ObjectLocation.getMaxLocAreaNaN(
extr_corr_half[scene_other][mn], // double [] data, // square data
null, // double [] cent_xy, // if null, use center of the square
search_radius, // double radius, // search for maximum within this radius. Should radius be 0 here?
frac_max, // double frac_max)
debugLevel); // final int debugLevel) {
}
if (debugLevel > 0) {
showExtractedCorrelations(
ortho_maps[indices[scene_num]].getName()+"-prefilter", // String prefix
scene_other, // int scene_num,
phaseCoeff, // double [] phaseCoeff,
extr_corr, // double [][][] extr_corr,
extr_corr_half, // double [][][] extr_corr_half,
extr_size, // int extr_size,
// or should it be other gop?
gops[scene_num], // GroundObjectPattern gop,
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
imps_extracted_corr, // ImagePlus[] imps_extracted_corr, // may be null - will not be displayed
imps_extracted_corr_half); // ImagePlus[] imps_extracted_corr_half
}
}
// final filter
removed = filterCandidates( // will filter again if already
filt_keep, // boolean filt_keep,
new boolean[] {true,true}, // new boolean [] filt_main_other,
min_corrs, //double [] min_corrs, // one per
min_corr_full_rel, // double min_corr_full_rel,
filt_max_radius, // double [][] filt_max_radius,
filt_elongation, // double [][] filt_elongation,
filt_dist, // double [] filt_dist,
filter_data, // double [][][][] filter_data,
scene_xy_offset, // double [] scene_xy_offset, //second scene vertical projection offset from the first scene
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
debugLevel); // int debugLevel )
if (!filt_keep && (removed.length > match_sort.size())) { // decimate data arrays
for (int sn = 0; sn < filter_data.length; sn++) {
filter_data[sn] = removeFilteredOut (filter_data[sn], removed);
extracted_objects[sn] = removeFilteredOut (extracted_objects[sn], removed);
extr_corr[sn] = removeFilteredOut (extr_corr[sn], removed);
extr_corr_half[sn] = removeFilteredOut (extr_corr_half[sn], removed);
}
removed = new boolean [match_sort.size()];
}
ImagePlus [] imps_extracted_final = new ImagePlus[indices.length];
ImagePlus [] imps_extracted_corr_final = new ImagePlus[indices.length];
ImagePlus [] imps_extracted_corr_half_final = new ImagePlus[indices.length];
if (!filt_keep) { // show final filtered images again - just extracts (2) and all correlations (4)
for (int sn = 0; sn < indices.length; sn++) {
showExtractedImages(
ortho_maps[indices[scene_num]].getName()+"-final", // String prefix
sn, //int scene_num,
sort_pattern_index, // int sort_pattern_index,
extr_size, // int extr_size,
gops[scene_num], // GroundObjectPattern gop,
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
extracted_objects, // double[][][] extracted_objects, // may be null - will not be generated
extract_display, // double[][][] extract_display, // may be null - will not be displayed
dmulti, // double[][] dmulti,
width, // int width,
remove_dc, // boolean remove_dc,
imps_extracted_final, //ImagePlus[] imps_extracted, // may be null - will not be displayed
debugLevel); // int debugLevel
showExtractedCorrelations(
ortho_maps[indices[scene_num]].getName()+"-final", // String prefix
sn, // int scene_num,
phaseCoeff, // double [] phaseCoeff,
extr_corr, // double [][][] extr_corr,
extr_corr_half, // double [][][] extr_corr_half,
extr_size, // int extr_size,
gops[scene_num], // GroundObjectPattern gop,
matches_list, // ArrayList <ItemMatch> matches_list,
match_sort, // ArrayList<Integer> match_sort,
imps_extracted_corr_final, // ImagePlus[] imps_extracted_corr, // may be null - will not be displayed
imps_extracted_corr_half_final); // ImagePlus[] imps_extracted_corr_half
}
}
// TODO: add filtering list by areas and distances
double scene_agl = gops[1].getAGL(); // second scene agl
System.out.println("TODO: add filtering list by areas and distances for both scenes");
// display updated list with areas for the main scene, and maximums areas, distances for the second
System.out.println("Second image is offset by dx="+scene_xy_offset[0]+", dy="+scene_xy_offset[1]+", dist="+
Math.sqrt(scene_xy_offset[0]*scene_xy_offset[0]+scene_xy_offset[1]*scene_xy_offset[1])+" pix");
System.out.println("Updated object list with main scene peak areas and secondary scene maximums, areas and maximum distances from the main");
System.out.print(String.format("%4s: %9s %8s %3s"," # ", " x/y ", " best ","sub"));
for (int j = 0; j < (corrs_out[scene_num].length + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
// System.out.print(String.format("%8s %8s | %8s %8s %8s %8s %8s %8s",
// "mf-area","mh-area", "of-max", "of-area", "of-dist", "oh-max", "oh-area", "oh-dist"));
System.out.print(String.format("%6s %6s %6s %6s | %8s %6s %6s %6s %7s %7s %7s %7s %7s | %8s %6s %6s %6s %7s %7s %7s",
"mf-rad","mf-eln","mh-rad","mh-eln", // main: full radius, full elongation, half radius, half elongation
"of-corr","of-rad","of-eln","of-dst","of-dx","of-dy","of-par","of-prp","elevat",
"oh-corr","oh-rad","oh-eln","oh-dst","oh-dx","oh-dy","removed"));
System.out.println();
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gops[scene_num]);
int [] icenter_xy = match.getIntXY();
System.out.print(String.format("%4d: %4d/%4d %8.5f %3d",
i,
icenter_xy[0],icenter_xy[1],
match.getMatchValue(gops[scene_num],sort_pattern_index),
match.getPatternMatch(gops[scene_num]).getBestSub()));
for (int j = 0; j < match_values.length; j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8.5f",match_values[j]));
if (j != (match_values.length-1)) {
System.out.print(",");
} else {
System.out.print(" ");
}
}
// 0 1 2 3 4 5
// return new double [] {best_d, eff_rad, elong, dist, cent_offs[0], cent_offs[1]} ;
double [] second_xy_offsets = {filter_data[1][i][0][4],filter_data[1][i][0][5]};
// try elevation for second scene and full pattern only
double [] scnd_xy_proj = projectOffsetOnVector(
second_xy_offsets, // double [] object_offset,
scene_xy_offset); // double [] scene_offset)
double obj_elev = offsetToElevation(
second_xy_offsets, //double [] object_offset,
scene_xy_offset, // double [] scene_offset,
zoom_level, // int zoom_level,
scene_agl); // double agl)
// System.out.println(String.format("best_d=%7.5f, rad=%6.3f, elong=%6.3f, dist=%6.3f, dx=%6.3f, dy=%6.3f",
String sremoved = removed[i]?" removed":"";
System.out.print(String.format(
"%6.3f %6.3f %6.3f %6.3f | %8.5f %6.3f %6.3f %6.3f %7.3f %7.3f %7.3f %7.3f %7.3f | %8.5f %6.3f %6.3f %6.3f %7.3f %7.3f %7s",
// main full and best half areas only, radius and elongation
filter_data[0][i][0][1], filter_data[0][i][0][2], // main full: radius and elongation
filter_data[0][i][1][1], filter_data[0][i][1][2], // main best half: radius and elongation
// for second full - everything and parallel/perpendicular+elevation
filter_data[1][i][0][0], filter_data[1][i][0][1], filter_data[1][i][0][2], // full: corr, radius, elongation
filter_data[1][i][0][3], filter_data[1][i][0][4], filter_data[1][i][0][5], // full: dist, dx, dy
scnd_xy_proj[0], scnd_xy_proj[1],obj_elev, // full: parallel, perpnd, elevation(m)
filter_data[1][i][1][0], filter_data[1][i][1][1], filter_data[1][i][1][2], // half: corr, radius, elongation
filter_data[1][i][1][3], filter_data[1][i][1][4], filter_data[1][i][1][5], // half: dist, dx, dy
sremoved));
System.out.println();
}
//ortho_maps[indices[0]]
//double [][] dmulti
//ortho_maps[indices[scene_num]].getName()
/*
PointRoi roi = new PointRoi();
roi.setOptions("label");
for (int i = 0; i < src_marks.length; i++) {
roi.addPoint(src_marks[i][0],src_marks[i][1]); // ,1);
}
imp_corrs[scene_num].setRoi(roi);
*/
{ // Create image with marked mines
PointRoi final_roi = new PointRoi();
final_roi.setOptions("label");
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gops[scene_num]);
double [] center_xy = match.getXY();
final_roi.addPoint(center_xy[0], center_xy[1]); // ,1);
}
String [] final_titles = new String[indices.length];
double [][] final_map = new double [indices.length][];
for (int i = 0; i < final_map.length; i++) {
final_titles[i] = ortho_maps[indices[0]].getName();
final_map[i] = dmulti[i];
}
String final_title = final_titles[0]+"-"+final_titles[0]+"-MARKED_"+match_sort.size()+"_OBJECTS";
ImagePlus img_final = ShowDoubleFloatArrays.makeArrays(
final_map,
width,
height,
final_title,
final_titles);
img_final.setRoi(final_roi);
img_final.show();
}
} // if (scene_num == 0) {
if (debugLevel > -1000) {
return null;
}
object_lists.add(plist); // old way
System.out.println("patternMatchDual(): Found "+object_lists.get(scene_num).size()+" candidates for scene #"+scene_num);
imps_best[scene_num] = ShowDoubleFloatArrays.makeArrays(
bestcorr[scene_num],
......@@ -1947,7 +2471,7 @@ public class OrthoMapsCollection implements Serializable{
corr_size, // final int psize, // power of 2, such as 64
corr_patterns[scene_num][n], // final double [] pattern, // [psize*psize]
true, // final boolean convolve, // convolve, not correlate
phaseCoeff, // final double phaseCoeff,
phaseCoeff[scene_num],// final double phaseCoeff,
debugLevel); // final int debugLevel) {
}
convolved_merged[scene_num] = OrthoMap.mergePattenConvolutions(
......@@ -2005,6 +2529,284 @@ public class OrthoMapsCollection implements Serializable{
return null;
}
public static double [][][] removeFilteredOut(
double [][][] data,
boolean [] remove){
if (data == null) {
return null;
}
int num_left = data.length;
for (int i = 0; i < remove.length; i++) {
if (remove[i]) {
num_left--;
}
}
double [][][] new_data = new double[num_left][][];
int indx = 0;
for (int i = 0; i < remove.length; i++) if (!remove[i]) {
new_data[indx++] = data[i];
}
return new_data;
}
public static double [][] removeFilteredOut(
double [][] data,
boolean [] remove){
if (data == null) {
return null;
}
int num_left = data.length;
for (int i = 0; i < remove.length; i++) {
if (remove[i]) {
num_left--;
}
}
double [][] new_data = new double[num_left][];
int indx = 0;
for (int i = 0; i < remove.length; i++) if (!remove[i]) {
new_data[indx++] = data[i];
}
return new_data;
}
/**
* Returns boolean array of original length
* @param filt_keep
* @param filt_main_other
* @param min_corrs
* @param min_corr_full_rel
* @param filt_max_radius
* @param filt_elongation
* @param filt_dist
* @param filter_data
* @param scene_xy_offset
* @param matches_list
* @param match_sort
* @param debugLevel
* @return
*/
public static boolean[] filterCandidates(
boolean filt_keep,
boolean [] filt_main_other,
double [] min_corrs, // one per
double min_corr_full_rel,
double [][] filt_max_radius,
double [][] filt_elongation,
double [] filt_dist,
double [][][][] filter_data,
double [] scene_xy_offset, //second scene vertical projection offset from the first scene
ArrayList <ItemMatch> matches_list,
ArrayList<Integer> match_sort,
int debugLevel ) {
boolean [] remove = new boolean [match_sort.size()];
int num_removed = 0;
double [] min_corrs_other = {min_corrs[1]*min_corr_full_rel, min_corrs[1]};
for (int mn=0; mn < match_sort.size(); mn++) {
for (int hf = 0; hf < 2; hf++) {
int indx =match_sort.get(mn);
ItemMatch match = matches_list.get(indx);
int [] ixy = match.getIntXY();
String name = ixy[0]+"/"+ixy[1];
for (int scene_num = 0; scene_num < 2; scene_num++) if (filt_main_other[scene_num]){
if (Double.isNaN(filter_data[scene_num][mn][hf][0])) {
System.out.println(name+": filtered out by "+NAME_MO[scene_num]+"/"+NAME_FH[hf]+
" as correlation maximum is not found");
if (!remove[mn]) num_removed++;
remove[mn] = true;
continue;
}
double eff_rad = filter_data[scene_num][mn][hf][1];
double elong = filter_data[scene_num][mn][hf][2];
double corr_val = filter_data[scene_num][mn][hf][0];
double dist = filter_data[scene_num][mn][hf][3];
double [] second_xy_offsets = {filter_data[scene_num][mn][hf][4],filter_data[scene_num][mn][hf][5]};
// calculate projection
double scnd_xy_proj_perp = projectOffsetOnVector(
second_xy_offsets, // double [] object_offset,
scene_xy_offset)[1]; // double [] scene_offset)
if (scene_num > 0) { // other scene
// {best_d, eff_rad, elong, dist, cent_offs[0], cent_offs[1]} ;
if (corr_val < min_corrs_other[hf]) {
System.out.println(name+": filtered out by "+NAME_MO[scene_num]+" correlation maximum value for "+
NAME_FH[hf]+ " = "+corr_val+" < "+ min_corrs_other[hf]);
if (!remove[mn]) num_removed++;
remove[mn] = true;
}
if (dist > filt_dist[0]) {
System.out.println(name+": filtered out by "+NAME_MO[scene_num]+" distance from the main scene peak "+
NAME_FH[hf]+ " = "+dist+" > "+filt_dist[0]);
if (!remove[mn]) num_removed++;
remove[mn] = true;
}
// distance for main only or both?
if (scnd_xy_proj_perp > filt_dist[1]) {
System.out.println(name+": filtered out by "+NAME_MO[scene_num]+" distance from the main scene peak perpendicular to the scene offset vector "+
NAME_FH[hf]+ " = "+scnd_xy_proj_perp+" > "+filt_dist[1]);
if (!remove[mn]) num_removed++;
remove[mn] = true;
}
}
if (eff_rad > filt_max_radius[scene_num][hf]) {
System.out.println(name+": filtered out by "+NAME_MO[scene_num]+" scene radius for "+
NAME_FH[hf]+ " pattern: "+eff_rad+" > "+ filt_max_radius[scene_num][hf]);
if (!remove[mn]) num_removed++;
remove[mn] = true;
}
if (elong > filt_elongation[scene_num][hf]) {
System.out.println(name+": filtered out by "+NAME_MO[0]+" scene peak cros-section elongation for "+
NAME_FH[hf]+ " pattern: "+elong+" > "+ filt_elongation[scene_num][hf]);
if (!remove[mn]) num_removed++;
remove[mn] = true;
}
}
}
}
if (! filt_keep) {
if (num_removed > 0) {
for (int mn=match_sort.size()-1; mn >=0; mn--) {
if (remove[mn]) {
match_sort.remove(mn);
}
}
System.out.println("Filtered out "+num_removed+
" scenes by the main scene filter.");
// remove = new boolean [match_sort.size()];
} else {
System.out.println("No scenes were filtered out by the main scene filter");
}
System.out.println(match_sort.size()+" candidates remain");
}
return remove;
}
//ortho_maps[indices[scene_num]].getName()
public static void showExtractedImages(
String prefix,
int scene_num,
int sort_pattern_index,
int extr_size,
GroundObjectPattern gop,
ArrayList <ItemMatch> matches_list,
ArrayList<Integer> match_sort,
double[][][] extracted_objects, // may be null - will not be generated
double[][][] extract_display, // may be null - will not be displayed
double[][] dmulti,
int width,
boolean remove_dc,
ImagePlus[] imps_extracted, // may be null - will not be displayed
int debugLevel
) {
PointRoi roi = new PointRoi();
roi.setOptions("nolabel"); // label");
for (int mn=0; mn < match_sort.size(); mn++) {
roi.addPoint(extr_size/2,extr_size/2,mn+1); // ,1);
}
if (extracted_objects != null) {
extracted_objects[scene_num] = new double [match_sort.size()][];
}
if (extract_display != null ) {
extract_display[scene_num] = new double [match_sort.size()][];
}
for (int mn=0; mn < match_sort.size(); mn++) {
int indx =match_sort.get(mn);
ItemMatch match = matches_list.get(indx);
double [] center_xy = match.getXY();
//some may be missing on a second image
if (extracted_objects != null) {
extracted_objects[scene_num][mn] = ObjectLocation.extractObjectImage(
center_xy, // double [] center_xy,
extr_size, // int size,
dmulti[scene_num], // double [] src_img,
width); // int width)
}
if (extract_display != null) {
if (extracted_objects != null) {
extract_display[scene_num][mn] =extracted_objects[scene_num][mn].clone();
} else {
extract_display[scene_num][mn] = ObjectLocation.extractObjectImage(
center_xy, // double [] center_xy,
extr_size, // int size,
dmulti[scene_num], // double [] src_img,
width); // int width)
}
if (remove_dc) {
OrthoMap.removeDC(extract_display[scene_num][mn]);
}
}
}
if ((debugLevel > 0) && (imps_extracted != null) && (extract_display != null)) {
String [] extr_titles = new String [match_sort.size()];
for (int mn=0; mn < match_sort.size(); mn++) {
int indx =match_sort.get(mn);
ItemMatch match = matches_list.get(indx);
int [] ixy = match.getIntXY();
extr_titles[mn] = ixy[0]+"/"+ ixy[1]+" "+match.getMatchValue(gop,sort_pattern_index);
}
imps_extracted[scene_num] = ShowDoubleFloatArrays.makeArrays(
extract_display[scene_num],
extr_size,
extr_size,
prefix+"-objects_"+scene_num+(remove_dc?"_no-DC":"_with-DC"),
extr_titles); // test_titles,
imps_extracted[scene_num].setRoi(roi);
imps_extracted[scene_num].show();
}
}
public static void showExtractedCorrelations(
String prefix,
int scene_num,
double [] phaseCoeff,
double [][][] extr_corr, // may be null if imps_extracted_corr == null too
double [][][] extr_corr_half, // may be null if imps_extracted_corr_half == null too
int extr_size,
GroundObjectPattern gop,
ArrayList <ItemMatch> matches_list,
ArrayList<Integer> match_sort,
ImagePlus[] imps_extracted_corr, // may be null - will not be displayed
ImagePlus[] imps_extracted_corr_half // may be null - will not be displayed
) {
PointRoi roi = new PointRoi();
roi.setOptions("nolabel"); // label");
for (int mn=0; mn < match_sort.size(); mn++) {
roi.addPoint(extr_size/2,extr_size/2,mn+1); // ,1);
}
String [] extr_titles_full = new String [match_sort.size()];
String [] extr_titles_half = new String [match_sort.size()];
for (int mn=0; mn < match_sort.size(); mn++) {
int indx =match_sort.get(mn);
ItemMatch match = matches_list.get(indx);
int [] ixy = match.getIntXY();
int best_patt = match.getPatternMatch(gop).getBestSub() - 1;
extr_titles_full[mn] = ixy[0]+"/"+ ixy[1];
extr_titles_half[mn] = extr_titles_full[mn]+best_patt;
}
if ((extr_corr != null) && (extr_corr[scene_num] != null) &&(imps_extracted_corr != null)) {
imps_extracted_corr[scene_num] = ShowDoubleFloatArrays.makeArrays(
extr_corr[scene_num],
extr_size,
extr_size,
prefix+"-objects_corr_full-"+scene_num+"_pc"+phaseCoeff[scene_num],
extr_titles_full); // test_titles,
imps_extracted_corr [scene_num].setRoi(roi);
imps_extracted_corr [scene_num].show();
}
if ((extr_corr_half != null) && (extr_corr_half[scene_num] != null) && (imps_extracted_corr_half != null)) {
imps_extracted_corr_half[scene_num] = ShowDoubleFloatArrays.makeArrays(
extr_corr_half[scene_num],
extr_size,
extr_size,
prefix+"-objects_corr_halves-"+scene_num+"_pc"+phaseCoeff[scene_num],
extr_titles_half); // test_titles,
imps_extracted_corr_half[scene_num].setRoi(roi);
imps_extracted_corr_half[scene_num].show();
}
}
}
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