Commit af55d764 authored by Andrey Filippov's avatar Andrey Filippov

Improved fillNaNs, tested terrain-only tiles

parent 108cab36
......@@ -892,6 +892,8 @@ min_str_neib_fpn 0.35
public int terr_num_exaggerate = 3; // generate exaggerated rendering
// Experimental reconstruction
public boolean terr_rebuild_elev = false; // rebuild elevations and scales
public int terr_elev_grow = 1024; // was 200
public double terr_threshold_terrain = 0.05;
public double terr_min_max_terrain= 0.1;
public double terr_min_terrain = 0.001;
......@@ -2249,6 +2251,9 @@ min_str_neib_fpn 0.35
gd.addNumericField("Exagerrate steps", terr_num_exaggerate, 0,3,"", ".");
gd.addMessage ("Experimental");
gd.addCheckbox ("Rebuild elevations", terr_rebuild_elev, "Regenerate elevations/scales in *.terrveg-tiff file");
gd.addNumericField("Grow elevations", terr_elev_grow, 0,3,"","Grow elevations over NaNs.");
gd.addNumericField("Terrain threshold alpha",terr_threshold_terrain, 5,7,"", ".");
gd.addNumericField("Min max terrain", terr_min_max_terrain, 5,7,"", ".");
gd.addNumericField("Minimal terrain", terr_min_terrain, 5,7,"", ".");
......@@ -3021,7 +3026,8 @@ min_str_neib_fpn 0.35
terr_boost_render = gd.getNextNumber(); // double
terr_max_render = gd.getNextNumber(); // double
terr_num_exaggerate = (int)gd.getNextNumber(); // int
terr_rebuild_elev = gd.getNextBoolean();// boolean
terr_elev_grow = (int)gd.getNextNumber(); // int
terr_threshold_terrain = gd.getNextNumber();// double
terr_min_max_terrain = gd.getNextNumber();// double
terr_min_terrain = gd.getNextNumber();// double
......@@ -3772,7 +3778,8 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"terr_boost_render", terr_boost_render+""); // double
properties.setProperty(prefix+"terr_max_render", terr_max_render+""); // double
properties.setProperty(prefix+"terr_num_exaggerate", terr_num_exaggerate+""); // int
properties.setProperty(prefix+"terr_rebuild_elev", terr_rebuild_elev+""); // boolean
properties.setProperty(prefix+"terr_elev_grow", terr_elev_grow+""); // int
properties.setProperty(prefix+"terr_threshold_terrain", terr_threshold_terrain+""); // double
properties.setProperty(prefix+"terr_min_max_terrain", terr_min_max_terrain+""); // double
properties.setProperty(prefix+"terr_min_terrain", terr_min_terrain+""); // double
......@@ -4543,7 +4550,8 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"terr_boost_render")!= null) terr_boost_render=Double.parseDouble(properties.getProperty(prefix+"terr_boost_render"));
if (properties.getProperty(prefix+"terr_max_render")!= null) terr_max_render=Double.parseDouble(properties.getProperty(prefix+"terr_max_render"));
if (properties.getProperty(prefix+"terr_num_exaggerate")!= null) terr_num_exaggerate=Integer.parseInt(properties.getProperty(prefix+"terr_num_exaggerate"));
if (properties.getProperty(prefix+"terr_rebuild_elev")!= null) terr_rebuild_elev=Boolean.parseBoolean(properties.getProperty(prefix+"terr_rebuild_elev"));
if (properties.getProperty(prefix+"terr_elev_grow")!= null) terr_elev_grow=Integer.parseInt(properties.getProperty(prefix+"terr_elev_grow"));
if (properties.getProperty(prefix+"terr_threshold_terrain")!= null) terr_threshold_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_threshold_terrain"));
if (properties.getProperty(prefix+"terr_min_max_terrain")!= null) terr_min_max_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_max_terrain"));
if (properties.getProperty(prefix+"terr_min_terrain")!= null) terr_min_terrain=Double.parseDouble(properties.getProperty(prefix+"terr_min_terrain"));
......@@ -5275,7 +5283,8 @@ min_str_neib_fpn 0.35
imp.terr_boost_render = this.terr_boost_render;
imp.terr_max_render = this.terr_max_render;
imp.terr_num_exaggerate = this.terr_num_exaggerate;
imp.terr_rebuild_elev = this.terr_rebuild_elev;
imp.terr_elev_grow = this.terr_elev_grow;
imp.terr_threshold_terrain = this.terr_threshold_terrain;
imp.terr_min_max_terrain = this.terr_min_max_terrain;
imp.terr_min_terrain = this.terr_min_terrain;
......
......@@ -5531,7 +5531,8 @@ public class TexturedModel {
0.7, // double diagonal_weight, // relative to ortho
100, // int num_passes,
0.01, // final double max_rchange, // = 0.01
THREADS_MAX); // final int threadsMax) // maximal number of threads to launch
THREADS_MAX, // final int threadsMax) // maximal number of threads to launch
0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations
if (dbg_img != null) dbg_img[4] = sky_pixels_filled.clone();
if (blur_sigma > 0.0) {
(new DoubleGaussianBlur()).blurDouble(
......
......@@ -24,8 +24,10 @@ package com.elphel.imagej.tileprocessor;
*/
import java.awt.Rectangle;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
//import java.util.concurrent.atomic.AtomicInteger;
......@@ -8805,7 +8807,8 @@ ImageDtt.startAndJoin(threads);
diagonal_weight, //double diagonal_weight, // relative to ortho
num_passes, // int num_passes,
max_rchange, // final double max_rchange, // = 0.01
ImageDtt.THREADS_MAX); // final int threadsMax)
ImageDtt.THREADS_MAX, // final int threadsMax)
0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations
}
public static double [] fillNaNs(
final double [] data,
......@@ -8826,15 +8829,201 @@ ImageDtt.startAndJoin(threads);
diagonal_weight, //double diagonal_weight, // relative to ortho
num_passes, // int num_passes,
max_rchange, // final double max_rchange, // = 0.01
threadsMax); // final int threadsMax)
threadsMax, // final int threadsMax)
0); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations
}
/**
* Us this one when filling full frame and prohibit is not used. Faster as it first tries lower resolution, then full
* @param data_in input data array
* @param width_full width of the input dtata
* @param decimate_step decimation step (such as 16)
* @param num_decimate number of decimation steps (should be >=1). If 1 just two passes
* @param num_passes number of passes for each decimation step (100)
* @param max_rchange maximal relative change to exit
* @param debugTitle Generate images if non-null
* @param debugLevel debug inner method: 0 - none, 1 - when done, 2 - all iterations
* @return
*/
public static double [] fillNaNs(
final double [] data_in,
int width_full,
final int decimate_step, // 16
final int num_decimate,
int num_passes,
final double max_rchange, // = 0.01
String debugTitle,
final int debugLevel) { // 0 - none, 1 - when done, 2 - all iterations
final int dbg_pix = (debugTitle == null) ? -1 : -1205;
final double diagonal_weight = 0.7; // relative to ortho
int height_full = data_in.length/width_full;
if (debugTitle != null) {
ShowDoubleFloatArrays.showArrays(
data_in,
width_full,
height_full,
debugTitle+"-data_in");
}
double [] data_prev_filled = null;
int width_prev = -1;
double [] dbg_bkp = null;
for (int ndecimate = num_decimate; ndecimate >= 0; ndecimate--) {
int dcm = 1;
for (int i = 0; i < ndecimate; i++) {
dcm *= decimate_step;
}
final int decimate = dcm;
final int width = (width_full+(decimate-1))/decimate;
final int height = (height_full+(decimate-1))/decimate;
final int num_pixels = width*height;
final double [] data = new double[num_pixels];
final double [] data_nan = new double[num_pixels]; // only nan/non-nan
final int grow = 2 * Math.max(width, height);
if (ndecimate == num_decimate) { // prepare initial lo-res data
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nDecPix = ai.getAndIncrement(); nDecPix < num_pixels; nDecPix = ai.getAndIncrement()) {
if (nDecPix == dbg_pix) {
System.out.println("fillNaNs(multi) nDecPix="+nDecPix);
}
int x_dcm = nDecPix % width;
int y_dcm = nDecPix / width;
int num_defined = 0;
double sum_val = 0;
int x0_full = x_dcm*decimate;
int x1_full = Math.min((x_dcm + 1) * decimate, width_full);
int y0_full = y_dcm*decimate;
int y1_full = Math.min((y_dcm + 1) * decimate, height_full);
for (int y_full = y0_full; y_full < y1_full; y_full++) {
for (int x_full = x0_full; x_full < x1_full; x_full++) {
int pix_full = y_full * width_full + x_full;
double d = data_in[pix_full];
if (!Double.isNaN(d)) {
sum_val += d;
num_defined++;
}
}
}
if (num_defined > 0) {
data[nDecPix] = sum_val/num_defined;
} else {
data[nDecPix] = Double.NaN;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debugTitle != null) {
dbg_bkp = data.clone();
}
data_prev_filled = fillNaNs(
data, // final double [] data,
null, // final double [] data_nan, // only modify tiles that are not fixed
null, // final boolean [] prohibit,
width, // int width,
grow, // final int grow,
diagonal_weight, // double diagonal_weight, // relative to ortho
num_passes, // int num_passes,
max_rchange, //final double max_rchange, // = 0.01
ImageDtt.THREADS_MAX, // final int threadsMax) // maximal number of threads to launch
debugLevel); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations
} else {
// assuming no NaN in data_prev_filled
final double [] fdata_prev_filled = data_prev_filled;
final int fwidth_prev = width_prev;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nDecPix = ai.getAndIncrement(); nDecPix < num_pixels; nDecPix = ai.getAndIncrement()) {
int x_dcm = nDecPix % width;
int y_dcm = nDecPix / width;
double sum_val = 0;
int x0_full = x_dcm*decimate;
int x1_full = Math.min((x_dcm + 1) * decimate, width_full);
int y0_full = y_dcm*decimate;
int y1_full = Math.min((y_dcm + 1) * decimate, height_full);
int y_pdcm = y_dcm / decimate_step;
int x_pdcm = x_dcm / decimate_step;
int pix_prev = y_pdcm * fwidth_prev + x_pdcm;
double d_prev = fdata_prev_filled[pix_prev];
int num_defined = (y1_full-y0_full) * (x1_full-x0_full);
int num_defined1 = 0;
int num_fixed = 0; // number of actually defined pixels (not filled in the previous steps
for (int y_full = y0_full; y_full < y1_full; y_full++) {
for (int x_full = x0_full; x_full < x1_full; x_full++) {
int pix_full = y_full * width_full + x_full;
double d = data_in[pix_full];
if (!Double.isNaN(d)) {
sum_val += d;
num_fixed ++;
} else {
sum_val += d_prev;
}
num_defined1++;
}
}
if ((num_defined1 != num_defined) || (num_defined == 0)) {
System.out.println("fillNaNs(multi) BUG: num_defined="+num_defined+", num_defined1="+num_defined1);
}
data[nDecPix] = sum_val/num_defined;
data_nan[nDecPix] = (num_fixed > 0) ? data[nDecPix] : Double.NaN; // non-NaN may be any value, like 0.0;
}
}
};
}
ImageDtt.startAndJoin(threads);
if (debugTitle != null) {
dbg_bkp = data.clone();
}
data_prev_filled = fillNaNs(
data, // final double [] data,
data_nan, // final double [] data_nan, // only modify tiles that are not fixed
null, // final boolean [] prohibit,
width, // int width,
grow, // final int grow,
diagonal_weight, // double diagonal_weight, // relative to ortho
num_passes, // int num_passes,
max_rchange, //final double max_rchange, // = 0.01
ImageDtt.THREADS_MAX, // final int threadsMax) // maximal number of threads to launch
debugLevel); // final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations
}
if (debugTitle != null) {
String [] dbg_titles = {"data","nan","filled"};
double [][] dbg_data = {dbg_bkp,data_nan, data_prev_filled};
ShowDoubleFloatArrays.showArrays(
dbg_data,
width,
height,
true,
debugTitle+"-dcm"+decimate,
dbg_titles);
}
width_prev = width;
}
return data_prev_filled;
}
/**
* Fill NaN values in 2D array from neighbors using Laplacian==0
* @param data data array (in line-scan order) with NaN values to be filled,
* non-NaN values will not be modified.
* @param data_nan optional "original" data with NaN values to be replaced. If null,
* (single-pass) the data[] array will be used
* If non-null, will be used as a mask NaN/nonNaN and data - as initial values
* @param prohibit_in optional (may be null) boolean array of the same size specifying
* prohibited pixels.
* @param width data width (height = data.length/width)
......@@ -8842,7 +9031,8 @@ ImageDtt.startAndJoin(threads);
* @param diagonal_weight weight of 4 diagonal neighbors relative to 4 ortho ones.
* @param num_passes maximal number of iterations.
* @param max_rchange max relative (to data RMS) step change to exit iterations.
* @param threadsMax maximal number of concurrent threads to launch.
* @param threadsMax maximal number of concurrent threads to launch.
* @param debugLevel 0 - none, 1 - when done, 2 - all iterations
* @return data array made of input data with replaced NaN limited by
* optional prohibit array and amount of growth.
*/
......@@ -8854,8 +9044,9 @@ ImageDtt.startAndJoin(threads);
final int grow,
double diagonal_weight, // relative to ortho
int num_passes,
final double max_rchange, // = 0.01
final int threadsMax) // maximal number of threads to launch
final double max_rchange, // = 0.01
final int threadsMax, // maximal number of threads to launch
final int debugLevel) // 0 - none, 1 - when done, 2 - all iterations
{
int height = data.length/width;
double wdiag = 0.25 *diagonal_weight / (diagonal_weight + 1.0);
......@@ -8984,6 +9175,9 @@ ImageDtt.startAndJoin(threads);
s /= sw;
data_io[1][nt] = s;
last_change[ti] = Math.max(last_change[ti], Math.abs(data_io[1][nt]-data_io[0][nt]));
if (Double.isNaN(last_change[ti] )) {
System.out.println("fillNaNs():ti="+ti+",data_io[0]["+nt+"]="+data_io[0][nt]+",data_io[1]["+nt+"]="+data_io[1][nt]);
}
}
}
};
......@@ -8994,8 +9188,10 @@ ImageDtt.startAndJoin(threads);
multi_change = Math.max(multi_change, last_change[i]);
}
boolean done = (pass >= (num_passes - 1)) || (multi_change < max_change);
if (data_nan != null) {
System.out.println("fillNaNs(): pass="+pass+" change="+multi_change+" done="+done);
if ((debugLevel > 1) || ((debugLevel >0) && done)) {
// if (data_nan != null) {
System.out.println("fillNaNs(): "+(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()))+
" pass="+pass+" change="+multi_change+" done="+done);
}
if (done) {
break;
......
......@@ -110,6 +110,7 @@ public class VegetationLMA {
// derivatives, only defined when elevations are adjusted NOT USED???
private double [][][] elev_dweights4; // [scene][woi_veg][4] derivatives of weights of influence for 4 neighbors with respect to elevations
private double [][][] elev_dsum_weights; // [scene][elev_par][woi] derivative of elev_sum_weights by each of the elevation parameter
// private int [][][] elev_dindx4; // [scene][woi_veg][4] derivatives of weights of influence for 4 neighbors with respect to elevations
// elevation-dependent parameters, calculated once if terrain elevation is not adjusted or each time if they are
......@@ -162,6 +163,7 @@ public class VegetationLMA {
private double hifreq_weight; // (+) 22.5 0 - do not use high-freq. Relative weight of laplacian components
private double reg_weights; // (+) fraction of the total weight used for regularization
private boolean [] fits = new boolean[TVAO_TYPES];// (+)
public boolean terr_elevation_full = false; // false - common terrain elevation, true - per-pixel terrain elevation
private double alpha_loss = 0; // (+) quadratic loss
private double alpha_loss_lin = 0.5; // (+) linear loss
private double alpha_offset = 0; // (+) if >0, start losses below 1.0;
......@@ -425,7 +427,7 @@ public class VegetationLMA {
return scales_xy;
}
public void fillScalesWOI(
public boolean fillScalesWOI(
final Rectangle woi_in,
final boolean debug) {
final Rectangle woi = woi_in.intersection(full); // if woi_in extends beyond full
......@@ -457,16 +459,20 @@ public class VegetationLMA {
if (debug) {
System.out.println("fillScalesWOI(): detected null in scales_xy inside woi="+woi.toString()+", filling missing pairs");
}
fillScalesXY( // FIXME: make it work with woi outside of full!
boolean ok = fillScalesXY( // FIXME: make it work with woi outside of full!
scales_xy, // double [][][] scalesXY,
full.width, // int width,
woi, // Rectangle woi,
false); // debug); // false); // boolean debug)
false); // debug); // false); // boolean debug)
if (!ok) {
System.out.println("fillScalesWOI(): ***** FAILED. *****");
return false;
}
if (debug) {
System.out.println("fillScalesWOI(): DONE.");
}
}
return; //
return true; //
}
/*
......@@ -529,7 +535,7 @@ public class VegetationLMA {
*/
private static void fillScalesXY(
private static boolean fillScalesXY(
double [][][] scalesXY,
int width,
Rectangle woi,
......@@ -541,6 +547,7 @@ public class VegetationLMA {
final AtomicInteger ai = new AtomicInteger(0);
final double [][] full_scales = new double [2][woi_length];
final int num_passes = 20;
final AtomicBoolean ano_scales = new AtomicBoolean(false);
for (int nscene = 0; nscene < scalesXY.length; nscene++) {
final int nScene = nscene;
if (debug) {
......@@ -581,15 +588,21 @@ public class VegetationLMA {
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int wIndx = ai.getAndIncrement(); wIndx < woi_length; wIndx = ai.getAndIncrement()) {
for (int wIndx = ai.getAndIncrement(); (wIndx < woi_length) && !ano_scales.get(); wIndx = ai.getAndIncrement()) {
int findx = getWoiIndex(
woi, // Rectangle woi_src,
full_woi, // Rectangle woi_dst,
full_woi, // Rectangle woi_full,
wIndx); // int indx)
if (Double.isNaN(full_scales[0][wIndx]) || Double.isNaN(full_scales[0][wIndx])) {
throw new IllegalArgumentException("fillScalesXY(): BUG: full_scales[0]["+wIndx+"] ="+full_scales[0][wIndx]+
", full_scales[1]["+wIndx+"] ="+full_scales[1][wIndx]);
ano_scales.set(true);
if (debug) {
System.out.println("fillScalesXY(): BUG: full_scales[0]["+wIndx+"] ="+full_scales[0][wIndx]+
", full_scales[1]["+wIndx+"] ="+full_scales[1][wIndx]);
}
continue;
// throw new IllegalArgumentException("fillScalesXY(): BUG: full_scales[0]["+wIndx+"] ="+full_scales[0][wIndx]+
// ", full_scales[1]["+wIndx+"] ="+full_scales[1][wIndx]);
}
scalesXY[nScene][findx] = new double [] {
full_scales[0][wIndx],
......@@ -599,12 +612,19 @@ public class VegetationLMA {
};
}
ImageDtt.startAndJoin(threads);
if (ano_scales.get()) {
break;
}
}
if (ano_scales.get()) {
System.out.println("fillScalesXY(): Missing scales for at least some scenes, can not fill NaNs");
return false;
}
if (debug) {
System.out.println("fillScalesXY(): filling scalesXY DONE.");
}
return;
return true;
}
......@@ -955,10 +975,12 @@ public class VegetationLMA {
Arrays.fill(elev_radius, elevation_radius); // 5);
Rectangle woi_terr_ext = expandWoi(woi,max_elev_terr);
fillScalesWOI(
boolean ok = fillScalesWOI(
woi_terr_ext, // final Rectangle woi,
(debugLevel > -2)); // final boolean debug)
if (!ok) {
return -1;
}
// calculate warps (as distances between vegetation projections of this pixel and its neighbors)
warps = getMaxWarp(
tvao[TVAO_ELEVATION], // final double [] elevations,
......@@ -977,7 +999,9 @@ public class VegetationLMA {
}
// valid_scenes = getValidScenes(max_offset); // final int max_offset)
this.woi_veg = (woi_veg_in != null)? woi_veg_in : new Rectangle();
/// this.woi_veg = (woi_veg_in != null)? woi_veg_in : new Rectangle();
/// when restoring, woi_veg_in may be null while woi_terr != null. It means that there is no vegetation saved, only terrain
this.woi_veg = (woi_terr_in != null)? woi_veg_in : new Rectangle();
this.woi_terr = (woi_terr_in != null)? woi_terr_in : new Rectangle();
int max_sacrifice = 5;
boolean [] valid_pixels_in = null;
......@@ -997,11 +1021,14 @@ public class VegetationLMA {
this.woi, // final Rectangle woi,
this.woi_veg, // final Rectangle woi_veg, // should be initialized, will be modified
this.woi_terr); // final Rectangle woi_terr) // should be initialized, will be modified
if (valid_scene_pix == null) {
System.out.println("prepareLMA(): ***** getValidScenesPixels() FAILED *****");
return -1;
}
if (valid_scene_pix_in != null) {
String [] names = {"scenes","woi pixels","vegetation pixels"};
boolean mismatch = false;
// TODO: Compare and notify i=f different
// TODO: Compare and notify if different
for (int i = 0; i < names.length; i++) {
boolean mismatch_this = false;
int num_gen=0, num_restore = 0;
......@@ -1027,22 +1054,39 @@ public class VegetationLMA {
}
}
}
woi_max = new Rectangle (woi);
woi_max.add(woi_veg);
woi_max.add(woi_terr);
valid_scenes = valid_scene_pix[0]; // [num_scenes]
valid_terr_proj = valid_scene_pix[1]; // [woi.width*woi.height] valid terrain and y_vector pixels
valid_vegetation = valid_scene_pix[2]; // [woi_veg.width*woi_veg.height] valid vegetation pixels
has_vegetation = valid_scene_pix[3]; // [woi.width*woi.height] this valid terrain pixel is overlaid by vegetation (in all valid scenes)
valid_terrain = valid_scene_pix[4]; // [woi_terr.width*woi_terr.height] valid terrain pixels
has_terrain = valid_scene_pix[5]; // [woi.width*woi.height] has terrain source pixels
if (valid_vegetation == null) {
woi_veg = null;
}
woi_max = new Rectangle (woi);
if (woi_veg != null) { // here - never, as it will be (0,0,0,0)
woi_max.add(woi_veg);
}
woi_max.add(woi_terr);
if (woi_veg == null) {
if (debugLevel > -3) {
System.out.println("prepareLMA() as there is no vegitation (woi_veg==null),"+
" fitting for VEGETATION,ALPHA, and ELEVATION is disabled");
fits[TVAO_VEGETATION] = false;
fits[TVAO_ALPHA] = false;
fits[TVAO_ELEVATION] = false;
}
}
if (debugLevel > -2) {
String s = (this.woi_veg == null) ? " no valid vegetation\n" : valid_stats[2] + " valid vegetation pixels (of "+(this.woi_veg.width*this.woi_veg.height)+")\n";
System.out.println("Got\t"+valid_stats[0]+" valid scenes (of "+this.terrain_rendered.length+"),\n"+
valid_stats[1] + " valid WOI pixels (of "+(this.woi.width*this.woi.height)+"), of them "+
valid_stats[3] + " have vegetation influence, "+valid_stats[5]+" have terrain influence,\n"+
valid_stats[2] + " valid vegetation pixels (of "+(this.woi_veg.width*this.woi_veg.height)+")\n"+
s + // valid_stats[2] + " valid vegetation pixels (of "+(this.woi_veg.width*this.woi_veg.height)+")\n"+
valid_stats[4] + " valid terrain pixels (of "+(this.woi_terr.width*this.woi_terr.height)+").\n"+
"Removed "+valid_stats[6]+" scenes because of the warp > "+max_warp+".");
if ((warps != null) && (max_warp_scene_pix != null)) {
......@@ -1088,7 +1132,7 @@ public class VegetationLMA {
woi, // Rectangle woi_dst,
full, // Rectangle woi_full,
wm_indx); // int indx)
int wvindx = getWoiIndex(
int wvindx = (woi_veg == null) ? -1 : getWoiIndex(
woi_max, // Rectangle woi_src,
woi_veg, // Rectangle woi_dst,
full, // Rectangle woi_full,
......@@ -1100,7 +1144,7 @@ public class VegetationLMA {
wm_indx); // int indx)
int [] fxy = woiXY(full, findx);
int [] wxy = woiXY(woi, windx);
int [] wvxy = woiXY(woi_veg, wvindx);
int [] wvxy = (woi_veg == null) ? null : woiXY(woi_veg, wvindx);
int [] wtxy = woiXY(woi_terr, wtindx);
// int x = fxy[0]; //java.lang.NullPointerException
......@@ -1110,7 +1154,7 @@ public class VegetationLMA {
dbg_img[2][wm_indx] = (wtxy != null) ? bool_min_max[1]:bool_min_max[0]; // "woi_terr"
if (windx >= 0) dbg_img[3][wm_indx] = valid_terr_proj [windx]? bool_min_max[1] : bool_min_max[0]; // "terr_proj",
if (wvindx >= 0) dbg_img[4][wm_indx] = valid_vegetation[wvindx]? bool_min_max[1] : bool_min_max[0]; // "vegetation"
if (wvindx >= 0) dbg_img[4][wm_indx] = (valid_vegetation==null) ? Double.NaN: (valid_vegetation[wvindx]? bool_min_max[1] : bool_min_max[0]); // "vegetation"
if (windx >= 0) dbg_img[5][wm_indx] = has_vegetation [windx]? bool_min_max[1] : bool_min_max[0]; // "has_veg",
if (wtindx >= 0) dbg_img[6][wm_indx] = valid_terrain [wtindx]? bool_min_max[1] : bool_min_max[0]; // "terrain"
if (windx >= 0) dbg_img[7][wm_indx] = has_terrain [windx]? bool_min_max[1] : bool_min_max[0]; // "has_terr",
......@@ -1142,10 +1186,10 @@ public class VegetationLMA {
}
ShowDoubleFloatArrays.showArrays(
dbg_img,
woi_veg.width,
woi_veg.height,
woi_max.width,
woi_max.height,
true,
"woi_veg_uses_"+woi_veg.x+"-"+woi_veg.y+"-"+woi_veg.width+"-"+woi_veg.height,
"woi_max_uses_"+woi_max.x+"-"+woi_max.y+"-"+woi_max.width+"-"+woi_max.height,
titles);
}
......@@ -1164,7 +1208,7 @@ public class VegetationLMA {
fits, // boolean [] fits,
debugLevel); // final int debugLevel)
alpha_neibs = getNeighbors(
alpha_neibs = (woi_veg == null) ? null :getNeighbors(
TVAO_ALPHA, // final int tvao, // TVAO_VEGETATION_ALPHA
ind_pars[TVAO_ALPHA], // final int ind_samples, // ind_pars[TVAO_VEGETATION]_alpha
num_pars[TVAO_ALPHA]); // final int num_samples); // num_pars[TVAO_VEGETATION]_alpha
......@@ -1172,11 +1216,11 @@ public class VegetationLMA {
TVAO_TERRAIN, // final int tvao, // TVAO_VEGETATION_ALPHA
ind_pars[TVAO_TERRAIN], // final int ind_samples, // ind_pars[TVAO_VEGETATION]_alpha
num_pars[TVAO_TERRAIN]); // final int num_samples); // num_pars[TVAO_VEGETATION]_alpha
veget_neibs = getNeighbors(
veget_neibs = (woi_veg == null) ? null :getNeighbors(
TVAO_VEGETATION, // final int tvao, // TVAO_VEGETATION_ALPHA
ind_pars[TVAO_VEGETATION], // final int ind_samples, // ind_pars[TVAO_VEGETATION]_alpha
num_pars[TVAO_VEGETATION]); // final int num_samples); // num_pars[TVAO_VEGETATION]_alpha
elevation_neibs = getNeighbors(
elevation_neibs = (woi_veg == null) ? null :getNeighbors(
TVAO_ELEVATION, // final int tvao, // TVAO_VEGETATION_ALPHA
ind_pars[TVAO_ELEVATION], // final int ind_samples, // ind_pars[TVAO_VEGETATION]_alpha
num_pars[TVAO_ELEVATION]); // final int num_samples); // num_pars[TVAO_VEGETATION]_alpha
......@@ -1186,18 +1230,20 @@ public class VegetationLMA {
neibs_neibs, // final int [][] second_neibs,
terr_neibs, // final int [][] par_neibs,
ind_pars[TVAO_TERRAIN]); // final int start_index)
addSecondNeighbors(
neibs_neibs, // final int [][] second_neibs,
alpha_neibs, // final int [][] par_neibs,
ind_pars[TVAO_ALPHA]); // final int start_index)
addSecondNeighbors(
neibs_neibs, // final int [][] second_neibs,
veget_neibs, // final int [][] par_neibs,
ind_pars[TVAO_VEGETATION]); // final int start_index)
addSecondNeighbors(
neibs_neibs, // final int [][] second_neibs,
elevation_neibs, // final int [][] par_neibs,
ind_pars[TVAO_ELEVATION]); // final int start_index)
if (woi_veg != null) {
addSecondNeighbors(
neibs_neibs, // final int [][] second_neibs,
alpha_neibs, // final int [][] par_neibs,
ind_pars[TVAO_ALPHA]); // final int start_index)
addSecondNeighbors(
neibs_neibs, // final int [][] second_neibs,
veget_neibs, // final int [][] par_neibs,
ind_pars[TVAO_VEGETATION]); // final int start_index)
addSecondNeighbors(
neibs_neibs, // final int [][] second_neibs,
elevation_neibs, // final int [][] par_neibs,
ind_pars[TVAO_ELEVATION]); // final int start_index)
}
if (debugLevel > 4) {
showPivot(
......@@ -1238,6 +1284,44 @@ public class VegetationLMA {
final double ceil_parallax) {
// find max parallax
final double ceil_parallax2 = ceil_parallax * ceil_parallax;
final double [] scene_weights = new double[scales_xy.length];
if (boost_parallax == 0) {
for (int nscene = 0; nscene < scales_xy.length; nscene++) {
scene_weights[nscene] = 1.0;
}
} else {
final double [] max_parallax2 = new double [scales_xy.length];
double super_max_parallax2 = 0;
for (int nscene = 0; nscene < scales_xy.length; nscene++) {
// only compare for selected window!
for (int drow = 0; drow < woi.height; drow++) {
int row = woi.y + drow;
for (int dcol = 0; dcol < woi.width; dcol++) {
int col = woi.x + dcol;
// int windx =dcol + drow * woi.width;
int indx = row*full.width + col;
double [] d = scales_xy[nscene][indx];
if (d != null) {
double d2 = Math.min(ceil_parallax2, d[0]*d[0] + d[1]*d[1]);
max_parallax2[nscene] = Math.max(max_parallax2[nscene], d2);
}
}
}
super_max_parallax2 = Math.max(super_max_parallax2, max_parallax2[nscene]);
}
for (int nscene = 0; nscene < scales_xy.length; nscene++) {
scene_weights[nscene] = 1.0+(boost_parallax - 1) * Math.sqrt(max_parallax2[nscene]/super_max_parallax2);
}
}
return scene_weights;
}
private double [] setupSceneWeightsOld(
final double boost_parallax,
final Rectangle woi,
final double ceil_parallax) {
// find max parallax
final double ceil_parallax2 = ceil_parallax * ceil_parallax;
final double [] scene_weights = new double[vegetation_offsets.length];
if (boost_parallax == 0) {
for (int nscene = 0; nscene < vegetation_offsets.length; nscene++) {
......@@ -1274,6 +1358,7 @@ public class VegetationLMA {
}
return scene_weights;
}
private double [] getYminusFxWeighted(
final double [] fx,
......@@ -2114,96 +2199,6 @@ public class VegetationLMA {
ImageDtt.startAndJoin(threads);
}
@Deprecated
public void showResults( // broken, not used
String title,
double [] vector,
double threshold_terrain,
double min_max_terrain, //0.1
double min_terrain, //0.001
double min_vegetation) { // 0.5
double [][] tvas = getTVASWoi(
vector); // final double [] vector)
double [][] terrain_weights_max;
// if (tvas== null) { // just temporary
// terrain_weights_max = getTerrainWeights(
// threshold_terrain, // final double alpha_threshold, // discard images with too low transparency
// vector); // final double [] vector)
// } else {
terrain_weights_max = new double [2][woi_veg.width * woi_veg.height];
Arrays.fill(terrain_weights_max[0],0.1);
Arrays.fill(terrain_weights_max[1],0.9);
// }
double [] terrain_masked = tvas[0].clone();
double [] vegetation_masked = tvas[1].clone();
for (int i = 0; i < terrain_masked.length; i++) {
if (!(terrain_weights_max[0][i] >= min_terrain)) terrain_masked[i] = Double.NaN;
if (!(terrain_weights_max[1][i] >= min_max_terrain)) terrain_masked[i] = Double.NaN;
if (!(tvas[2][i] >= min_vegetation)) vegetation_masked[i] = Double.NaN;
}
double [][] tvww = {terrain_masked, vegetation_masked, tvas[0], tvas[1], terrain_weights_max[0], terrain_weights_max[1],tvas[2],tvas[3]}; // no scene offsets
String [] titles = {"terr>"+min_terrain,"veget>"+min_vegetation,"terr","veget","terr_str","terr_max","alpha","elevation"};
ShowDoubleFloatArrays.showArrays(
tvww,
woi_veg.width,
woi_veg.height,
true,
title,
titles);
return;
}
@Deprecated
public double [][] getTVASWoi( // broken, not used now
final double [] vector){
final int woi_length = woi_veg.width*woi_veg.height;
double [][] tvas = new double [TVAO_TYPES][];
for (int i = 0; i < TVAO_SCENE_OFFSET; i++) tvas[i] = new double [woi_length];
tvas[TVAO_SCENE_OFFSET] = new double [num_scenes];
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int windx = ai.getAndIncrement(); windx < woi_length; windx = ai.getAndIncrement()) {
int x = windx % woi_veg.width + woi_veg.x;
int y = windx / woi_veg.width + woi_veg.y;
int indx = x + y * full.width;
for (int i = 0; i < 3; i++) {
tvas[i][windx] = tvao[i][indx]; // non-adjusted parameters
}
}
}
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int pindx = ai.getAndIncrement(); pindx < vector.length; pindx = ai.getAndIncrement()) {
int [] indices = par_rindex[pindx];
if (indices[0] < TVAO_SCENE_OFFSET) {
int wx = indices[1] % full.width - woi_veg.x;
int wy = indices[1] / full.width - woi_veg.y;
int windx = wx + wy * woi_veg.width;
tvas[indices[0]][windx] = vector[pindx]; // all adjusted parameters, including offsets
} else {
tvas[indices[0]][ indices[1]] = vector[pindx]; // all adjusted parameters, including offsets
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return tvas;
}
public static double [] laplacian(
final boolean gaussian,
final double [] data_in,
......@@ -2262,7 +2257,7 @@ public class VegetationLMA {
return; // nothing to do
}
final int woi_length = woi.width * woi.height;
final int woi_veg_length = woi_veg.width * woi_veg.height;
final int woi_veg_length = (woi_veg == null) ? 0 : woi_veg.width * woi_veg.height;
elev_woi4 = new int [num_scenes][][];
elev_weights4 = new double [num_scenes][][];
elev_sum_weights = new double [num_scenes][];
......@@ -2385,7 +2380,6 @@ public class VegetationLMA {
int par_indx_elev = par_index[TVAO_ELEVATION][fnpix]; // ipx+ipy*full.width];
elev_dsum_weights[nScene][par_indx_elev-ind_pars[TVAO_ELEVATION]][wpindex] += dww;
contrib_thread.get(wpindex).add(par_indx_elev); // full parameter index
// pivot_thread[nthread][wvindex][par_indx_elev] = true;
}
}
}
......@@ -2484,7 +2478,7 @@ public class VegetationLMA {
terr_elevation0 = 0;
}
final double terr_elevation = terr_elevation0;
if ((terr_elevation == terr_elev_last) && (terr_elev_sum_weights != null) && !need_derivs) {// added && !need_derivs
if ((terr_elevation == terr_elev_last) && (terr_elev_sum_weights != null) && !need_derivs && (debugLevel > -2)) {// added && !need_derivs
System.out.println("Terrain elevation did not change, keeping "+terr_elevation);
return;
}
......@@ -2998,17 +2992,17 @@ public class VegetationLMA {
final boolean offset_terrain = !Double.isNaN(terr_elev_last) && (terr_elev_last != 0); // if 0, use terrain pixels directly
final int woi_length = woi.width * woi.height;
final int woi_veg_length = woi_veg.width * woi_veg.height;
final int woi_veg_length = (woi_veg == null) ? 0 : (woi_veg.width * woi_veg.height);
final int woi_terr_length = woi_terr.width * woi_terr.height;
// final int num_pixels = full.width * full.height;
final boolean need_derivs = (jt != null);
final boolean elevation_parameters = (num_pars[TVAO_ELEVATION] > 0);
final boolean vegetation_parameters = (num_pars[TVAO_VEGETATION] > 0);
final boolean alpha_parameters = (num_pars[TVAO_ALPHA] > 0);
final boolean elevation_parameters = (num_pars[TVAO_ELEVATION] > 0); // 0 when woi_veg==null
final boolean vegetation_parameters = (num_pars[TVAO_VEGETATION] > 0); // 0 when woi_veg==null
final boolean alpha_parameters = (num_pars[TVAO_ALPHA] > 0); // 0 when woi_veg==null
final boolean terrain_parameters = (num_pars[TVAO_TERRAIN] > 0);
final boolean terr_elev_parameters = (num_pars[TVAO_TERR_ELEV] > 0);
final boolean scenes_parameters = (num_pars[TVAO_SCENE_OFFSET] > 0);
final boolean scenes_parameters = (num_pars[TVAO_SCENE_OFFSET] > 0);
final AtomicInteger anum_elev_err = new AtomicInteger(0);
// final boolean use_hf = samples_pointers[SAMPLES_Y_HF][1]>0;
// using 0.5*(1-cos(alpha/2pi) instead of alpha. alpha < 0 -> 0, alpha > 1 -> 1. Depends on other terms for stability
......@@ -3117,65 +3111,66 @@ public class VegetationLMA {
} else {
scene_offset = tvao[TVAO_SCENE_OFFSET][nScene];
}
for (int wvindex = 0; wvindex < woi_veg_length; wvindex++) if (valid_vegetation[wvindex]) {
int wvx = wvindex % woi_veg.width; // relative to woi_veg
int wvy = wvindex / woi_veg.width; // relative to woi_veg
int x = wvx + woi_veg.x; // relative to full
int y = wvy + woi_veg.y; // relative to full
int npix = x + y * full.width;
if (npix == dbg_findx) {
System.out.println("getFxDerivs() 1: findx="+npix);
}
double vegetation;
double alpha;
int nvpar = -1;
int napar = -1;
if (vegetation_parameters) {
nvpar = par_index[TVAO_VEGETATION][npix];
if (nvpar >= 0) {
vegetation = vector[nvpar];
if (woi_veg != null) {
for (int wvindex = 0; wvindex < woi_veg_length; wvindex++) if (valid_vegetation[wvindex]) {
int wvx = wvindex % woi_veg.width; // relative to woi_veg
int wvy = wvindex / woi_veg.width; // relative to woi_veg
int x = wvx + woi_veg.x; // relative to full
int y = wvy + woi_veg.y; // relative to full
int npix = x + y * full.width;
if (npix == dbg_findx) {
System.out.println("getFxDerivs() 1: findx="+npix);
}
double vegetation;
double alpha;
int nvpar = -1;
int napar = -1;
if (vegetation_parameters) {
nvpar = par_index[TVAO_VEGETATION][npix];
if (nvpar >= 0) {
vegetation = vector[nvpar];
} else {
System.out.println("getFxDerivs(): BUG: par_index["+TVAO_VEGETATION+"]["+npix+"] ="+nvpar);
continue;
}
} else {
System.out.println("getFxDerivs(): BUG: par_index["+TVAO_VEGETATION+"]["+npix+"] ="+nvpar);
continue;
}
} else {
vegetation = tvao[TVAO_VEGETATION][npix];
}
if (alpha_parameters) {
napar = par_index[TVAO_ALPHA][npix];
if (napar >= 0) {
alpha = vector[napar];
vegetation = tvao[TVAO_VEGETATION][npix];
}
if (alpha_parameters) {
napar = par_index[TVAO_ALPHA][npix];
if (napar >= 0) {
alpha = vector[napar];
} else {
System.out.println("getFxDerivs(): BUG: par_index["+TVAO_ALPHA+"]["+npix+"] ="+napar);
continue;
}
} else {
System.out.println("getFxDerivs(): BUG: par_index["+TVAO_ALPHA+"]["+npix+"] ="+napar);
continue;
}
} else {
alpha = tvao[TVAO_ALPHA][npix];
}
int [] terrain_woi_ind = elev_woi4[nScene][wvindex];
if (terrain_woi_ind != null) {
double [] terrain_woi_weights = elev_weights4[nScene][wvindex];// same vegetation pixel, per terrain neighbor
for (int i = 0; i < terrain_woi_ind.length; i++) {
int windx = terrain_woi_ind[i];
if (windx >= 0) {
double w = terrain_woi_weights[i];
veget_woi[windx] += w * vegetation; // accumulate vegetation for the same terrain output pixel
alpha_woi[windx] += w * alpha; // accumulate alpha for the same terrain output pixel
if (need_derivs) {
if (nvpar >= 0) {
contrib_thread.get(windx).add(nvpar); // full parameter index - this result pixel depends on this vegetation parameter
dveget_woi[nvpar-ind_pars[TVAO_VEGETATION]][windx] += w; // this fX pixel's vegetation with respect to this vegetation parameter
}
if (napar >= 0) {
contrib_thread.get(windx).add(napar); // full parameter index - this result pixel depends on this alpha parameter
dalpha_woi[napar-ind_pars[TVAO_ALPHA]][windx] += w; // this fX pixel's alpha with respect to this alpha parameter
alpha = tvao[TVAO_ALPHA][npix];
}
int [] terrain_woi_ind = elev_woi4[nScene][wvindex];
if (terrain_woi_ind != null) {
double [] terrain_woi_weights = elev_weights4[nScene][wvindex];// same vegetation pixel, per terrain neighbor
for (int i = 0; i < terrain_woi_ind.length; i++) {
int windx = terrain_woi_ind[i];
if (windx >= 0) {
double w = terrain_woi_weights[i];
veget_woi[windx] += w * vegetation; // accumulate vegetation for the same terrain output pixel
alpha_woi[windx] += w * alpha; // accumulate alpha for the same terrain output pixel
if (need_derivs) {
if (nvpar >= 0) {
contrib_thread.get(windx).add(nvpar); // full parameter index - this result pixel depends on this vegetation parameter
dveget_woi[nvpar-ind_pars[TVAO_VEGETATION]][windx] += w; // this fX pixel's vegetation with respect to this vegetation parameter
}
if (napar >= 0) {
contrib_thread.get(windx).add(napar); // full parameter index - this result pixel depends on this alpha parameter
dalpha_woi[napar-ind_pars[TVAO_ALPHA]][windx] += w; // this fX pixel's alpha with respect to this alpha parameter
}
}
}
}
}
}
} // for (int wvindex = 0; wvindex < woi_veg_length; wvindex++) if (valid_vegetation[wvindex]) {
} // for (int wvindex = 0; wvindex < woi_veg_length; wvindex++) if (valid_vegetation[wvindex]) {
}
for (int wtindex = 0; wtindex < woi_terr_length; wtindex++) if (terr_elev_woi4[nScene][wtindex] != null) { //valid_terrain[wtindex]) {
int wtx = wtindex % woi_terr.width; // relative to woi_terr
int wty = wtindex / woi_terr.width; // relative to woi_terr
......@@ -3232,7 +3227,7 @@ public class VegetationLMA {
}
}
}
// }
for (int windx = 0; windx < woi_length; windx++) if (valid_terr_proj[windx]) {
if ((windx== dbg_windex) && (nScene ==dbg_scene)) {
......@@ -3257,7 +3252,7 @@ public class VegetationLMA {
}
double d = terrain; // combined from neighbors if needed
if (has_vegetation[windx]) {
if ((woi_veg != null) && has_vegetation[windx]) { // maybe is sufficient as it is always false
double sw = elev_sum_weights[nScene][windx];
if (sw == 0) {
anum_elev_err.getAndIncrement();
......@@ -3340,13 +3335,17 @@ public class VegetationLMA {
}
}
}
if (elevation_parameters) { // here - just derivatives as direct influence of elevations is already processed
// we have dsw_delevations (for all elevation parameters) - ,
HashSet<Integer> epars_set = elev_contribs.get(windx); // may have unrelated (from other scenes) but still a small number
if (elevation_parameters) {
/// here - just derivatives as direct influence of elevations is already processed
/// we have dsw_delevations (for all elevation parameters) - ,
HashSet<Integer> epars_set = elev_contribs.get(windx);
/// Which elevation parameters (full index) may have influenced this image pixel
/// may have unrelated (from other scenes) but still a small number
for (int npar: epars_set) { // elevation parameters - full
int nepar = npar-ind_pars[TVAO_ELEVATION];
if ((nepar >=0 ) && (nepar < num_pars[TVAO_ELEVATION])) {
int findx = par_rindex[npar][1]; // full image pixel;
/// find vegetation for the pixel which elevation influences this one
double veget_src = tvao[TVAO_VEGETATION][findx];
if (vegetation_parameters) {
int veg_indx = par_index[TVAO_VEGETATION][findx];
......@@ -3356,6 +3355,7 @@ public class VegetationLMA {
System.out.println("getFxDerivs(): BUG: par_index["+TVAO_VEGETATION+"]["+findx+"]="+veg_indx);
}
}
/// find alpha for the pixel which elevation influences this one
double alpha_src = tvao[TVAO_ALPHA][findx];
if (alpha_parameters) {
int alpha_indx = par_index[TVAO_ALPHA][findx];
......@@ -3368,15 +3368,29 @@ public class VegetationLMA {
// do not forget that no alpha derivatives if alpha outside of (0,1)
double dsw_dnepar = elev_dsum_weights[nScene][nepar][windx];
// d = terrain * (1.0 - k) + avg_veget * k;
// dd_depar = k * davg_veget_depar +dk_depar * (avg_veget-terrain)
// dk_depar = dk_dalpha_avg * dalpha_avg_depar
// dalpha_avg_depar = 1.0 | 0.5 * PI * sin(avg_alpha * PI) (depending on mode
/*
* avg_veget, avg_alpha - weighted-averaged (divided by sw) from elevated contributors
* result pixel value d combining vegetation and terrain:
* d = terrain * (1.0 - k) + avg_veget * k;
* derivative of the result pixel d with respect to iterated elevation parameter epar:
* dd_depar = k * davg_veget_depar +dk_depar * (avg_veget-terrain)
* derivative of k (vegetation contribution derived from alpha_avg) with respect
* to the iterated elevation parameter epar:
* dk_depar = dk_dalpha_avg * dalpha_avg_depar
* dk_dalpha_avg = 1.0 | 0.5 * PI * sin(avg_alpha * PI) (depending on mode)
* dalpha_avg_depar =dsw_dnepar/sw * (alpha_src - avg_alpha) ??
* dalpha_avg_depar= (d_swa_d_elev * sw - swa*dsw_delev)/ (sw * sw) =
* (d_swa_d_elev_i - (swa/sw) * dsw_delev) / sw =
* (d_swa_d_elev_i - avg_alpha * dsw_delev) / sw =
* (elev_dweights4[nScene][wvindex][dindx] - avg_alpha * elev_dweights4[nScene][windx][dindx])/ sw
*/
double davg_veget_depar= dsw_dnepar/sw * (veget_src - avg_veget);
double dd_depar = k * davg_veget_depar;
if ((avg_alpha >= 0) && (avg_alpha <= 1.0)) {
double dk_dalpha_avg = alpha_piece_linear ? 1.0 : (0.5 * Math.PI * Math.sin(avg_alpha*Math.PI));
double dalpha_avg_depar = dsw_dnepar/sw * (alpha_src - avg_alpha);
// double dalpha_avg_depar1 = (elev_dweights4[nScene][windx][dindx] - avg_alpha * elev_dsum_weights[nScene][windx][dindx])/ sw;
double dk_depar = dk_dalpha_avg * dalpha_avg_depar;
dd_depar += dk_depar * (avg_veget-terrain);
}
......@@ -3414,9 +3428,27 @@ public class VegetationLMA {
jt[ntpar][y_indx] = 1.0;
}
*/
/*
if (extra_data != null) {
extra_data[0][y_indx] = terrain + scene_offset;
}
*/
if (extra_data != null) {
double k = 0.0;
if (extra_data.length > 0) {
extra_data[0][y_indx] = k;
if (extra_data.length > 1) {
extra_data[1][y_indx] = terrain;
if (extra_data.length > 2) {
extra_data[2][y_indx] = terrain * (1.0 - k) + scene_offset;
if (extra_data.length > 3) {
extra_data[3][y_indx] = scene_offset; // avg_veget * k + scene_offset;
if (extra_data.length > 4) {
extra_data[4][y_indx] = 0;//sw;
}}}}}
}
}
fX[y_indx] = d + scene_offset;
/*
......@@ -4551,7 +4583,10 @@ public class VegetationLMA {
if (sample_type >= 0) {
if (samples_pointers[sample_type][1] > 0) { // th
Rectangle sample_woi = getSampleWoi(
sample_type); // int sample_type) ;
sample_type); // int sample_type);
if (sample_woi == null) {
continue;
}
int sample_par = getSamplePar(
sample_type); // int sample_type) ;
for (int n = 0; n < samples_pointers[sample_type][1]; n++) {
......@@ -4835,19 +4870,16 @@ public class VegetationLMA {
String dir,
String title, // no .par-tiff
double [] vector) {
// int woi_length = woi_veg.width*woi_veg.height;
int woi_length = woi_max.width*woi_max.height;
int ext_length = woi_length;
if (vector == null) {
vector = parameters_vector;
}
// int height = woi_veg.height;
int height = woi_max.height;
/// int num_scenes_extra = num_scenes+1; // add tgerrain offset - single value
if (num_scenes > woi_length) { // very unlikely but still may happen
height = (num_scenes + woi_veg.width - 1) / woi_veg.width;
ext_length = woi_veg.width * height;
height = (num_scenes + woi_max.width - 1) / woi_max.width;
ext_length = woi_max.width * height;
}
String [] titles = {"terrain","vegetation","alpha","elevation", "terr_elev", "offset",
"terrain-index","vegetation-index","alpha-index","elevation-index","terr_elev-index", "offset-index"};
......@@ -4861,7 +4893,6 @@ public class VegetationLMA {
int w = i % woi_max.width;
int h = i / woi_max.width;
indx = (h + woi_max.y) * full.width + (w + woi_max.x); // full index
// } else if (n < TVAO_SCENE_OFFSET) {
}
int pindx = par_index[n][indx];
......@@ -4870,7 +4901,7 @@ public class VegetationLMA {
if (tvao[n] == null) {
data[n][i] = Double.NaN;
} else {
data[n][i] = tvao[n][indx];
data[n][i] = tvao[n][indx]; // will be NaN for vegetation, alpha, elevation for terrain-only
}
} else {
data[n][i] = vector[pindx];
......@@ -4881,15 +4912,22 @@ public class VegetationLMA {
}
ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
data,
woi_veg.width,
woi_max.width,
height,
title, // +"-objects_"+scene_num,
titles); // test_titles,
imp.setProperty("NUM_SCENES", ""+num_scenes);
imp.setProperty("WOI_VEG_X", ""+woi_veg.x);
imp.setProperty("WOI_VEG_Y", ""+woi_veg.y);
imp.setProperty("WOI_VEG_WIDTH", ""+woi_veg.width);
imp.setProperty("WOI_VEG_HEIGHT", ""+woi_veg.height);
if (woi_veg != null) {
imp.setProperty("WOI_VEG_X", ""+woi_veg.x);
imp.setProperty("WOI_VEG_Y", ""+woi_veg.y);
imp.setProperty("WOI_VEG_WIDTH", ""+woi_veg.width);
imp.setProperty("WOI_VEG_HEIGHT", ""+woi_veg.height);
} else {
imp.setProperty("WOI_VEG_X", "-1");
imp.setProperty("WOI_VEG_Y", "-1");
imp.setProperty("WOI_VEG_WIDTH", "-1");
imp.setProperty("WOI_VEG_HEIGHT", "-1");
}
imp.setProperty("WOI_TERR_X", ""+woi_terr.x);
imp.setProperty("WOI_TERR_Y", ""+woi_terr.y);
imp.setProperty("WOI_TERR_WIDTH", ""+woi_terr.width);
......@@ -4917,6 +4955,10 @@ public class VegetationLMA {
imp.setProperty("FIT_DISABLE_ELEVATION", ""+fits_disable[TVAO_ELEVATION]);
imp.setProperty("FIT_DISABLE_TERR_ELEV", ""+fits_disable[TVAO_TERR_ELEV]);
imp.setProperty("FIT_DISABLE_SCENE_OFFSET", ""+fits_disable[TVAO_SCENE_OFFSET]);
imp.setProperty("TERR_ELEVATION_FULL", ""+terr_elevation_full);
imp.setProperty("ALPHA_LOSS", ""+alpha_loss);
imp.setProperty("ALPHA_LOSS_LIN", ""+alpha_loss_lin);
imp.setProperty("ALPHA_OFFSET", ""+alpha_offset);
......@@ -4993,6 +5035,7 @@ public class VegetationLMA {
imp.setProperty("IND_PARS_VEGETATION", ""+ind_pars[TVAO_VEGETATION]);
imp.setProperty("IND_PARS_ALPHA", ""+ind_pars[TVAO_ALPHA]);
imp.setProperty("IND_PARS_ELEVATION", ""+ind_pars[TVAO_ELEVATION]);
imp.setProperty("TVAO_TERR_ELEV", ""+ind_pars[TVAO_TERR_ELEV]);
imp.setProperty("IND_PARS_SCENES", ""+ind_pars[TVAO_SCENE_OFFSET]);
imp.setProperty("TERRAIN_OFFSET", ""+terrain_offset);
imp.setProperty("TERR_ELEV_LAST_SUCCESS", ""+terr_elev_last_success);
......@@ -5014,20 +5057,9 @@ public class VegetationLMA {
return;
}
/*
public static int getSaveIndex(int tvao_type) {
for (int i = 0; i < SAVE_TYPES.length; i++) {
if (SAVE_TYPES[i] == tvao_type) return i;
}
return -1;
}
*/
public double [][] restoreParametersFile( //FIXME: Not finished for real import !
String path,
boolean keep_settings,
/// Rectangle [] file_wois, // if not null, should be Rectangle[2] {woi_veg,woi} - will return woi data and not input parameters to this instance
double [] other_pars){
ImagePlus imp_pars = new ImagePlus (path);
if (imp_pars.getWidth()==0) {
......@@ -5038,8 +5070,8 @@ public class VegetationLMA {
if (num_slices != 12) { // with terrain common elevation
throw new IllegalArgumentException("Expecting an 12-slice file, got "+num_slices);
}
int width = imp_pars.getWidth(); // woi_veg.width
int height = imp_pars.getHeight(); // woi_veg.height
int width = imp_pars.getWidth(); // woi_max.width
int height = imp_pars.getHeight(); // woi_max.height
double [][] data = new double[TVAO_TYPES][width*height]; // woi_max
int [][] indices = new int[TVAO_TYPES][width*height];
for (int n = 0; n < TVAO_TYPES; n++) {
......@@ -5082,51 +5114,21 @@ public class VegetationLMA {
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_Y")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_HEIGHT")));
if ((woi_veg.width <= 0) || (woi_veg.height <=0)) {
woi_veg = null;
}
Rectangle woi_terr = new Rectangle (
Integer.parseInt((String) imp_pars.getProperty("WOI_TERR_X")),
Integer.parseInt((String) imp_pars.getProperty("WOI_TERR_Y")),
Integer.parseInt((String) imp_pars.getProperty("WOI_TERR_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("WOI_TERR_HEIGHT")));
/*
if (file_wois != null) {
file_wois[0] = woi_veg;
file_wois[1] = woi;
// Remove undefined values that were not adjusted for this woi
for (int n = 0; n < TVAO_TYPES; n++) {
for (int i = 0; i < data[n].length; i++) {
if (indices[n][i] < 0) {
data[n][i] = Double.NaN;
}
}
}
// Trim data to actual
double [] scene_offsets = new double [num_scenes];
System.arraycopy(data[getSaveIndex(TVAO_SCENE_OFFSET)], 0, scene_offsets, 0, scene_offsets.length);
for (int i = 0; i < scene_offsets.length; i++) {
if (indices[TVAO_SCENE_OFFSET][i] < 0) {
data[TVAO_SCENE_OFFSET][i] = Double.NaN;
}
}
for (int n = 0; n < SAVE_TYPES.length; n++) if (SAVE_TYPES[n] != TVAO_SCENE_OFFSET){
if (woi_veg.width * woi_veg.height < data[n].length ) {
double [] d = new double [woi_veg.width * woi_veg.height];
System.arraycopy(data[n], 0, d, 0, d.length);
data[n] = d;
}
}
data[TVAO_SCENE_OFFSET] = scene_offsets;
if ((other_pars != null) && (other_pars.length >0)){
if (imp_pars.getProperty("TERRAIN_OFFSET") != null) other_pars[0] = Double.parseDouble((String) imp_pars.getProperty("TERRAIN_OFFSET"));
}
} else
*/
//{
this.woi_veg = woi_veg;
this.woi_terr = woi_terr;
this.woi = woi;
woi_max = new Rectangle (woi);
woi_max.add(woi_veg);
if (woi_veg != null) {
woi_max.add(woi_veg);
}
woi_max.add(woi_terr);
if (!keep_settings) {
......@@ -5146,6 +5148,8 @@ public class VegetationLMA {
fits_disable[TVAO_ELEVATION] = getProperty(imp_pars,"FIT_DISABLE_ELEVATION", fits_disable[TVAO_ELEVATION]);
fits_disable[TVAO_SCENE_OFFSET] = getProperty(imp_pars,"FIT_DISABLE_SCENE_OFFSET", fits_disable[TVAO_SCENE_OFFSET]);
terr_elevation_full = getProperty(imp_pars,"TERR_ELEVATION_FULL", terr_elevation_full);
alpha_loss = Double.parseDouble((String) imp_pars.getProperty("ALPHA_LOSS"));
alpha_loss_lin = getProperty(imp_pars,"ALPHA_LOSS_LIN", alpha_loss_lin);
alpha_offset = getProperty(imp_pars,"ALPHA_OFFSET", alpha_offset);
......@@ -5223,12 +5227,20 @@ public class VegetationLMA {
ind_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_VEGETATION"));
ind_pars[TVAO_ALPHA] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_ALPHA"));
ind_pars[TVAO_ELEVATION] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_ELEVATION"));
ind_pars[TVAO_TERR_ELEV] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_TERR_ELEV"));
// bug fix (remove later)
if (imp_pars.getProperty("IND_PARS_TERR_ELEV") == null) {
ind_pars[TVAO_TERR_ELEV] = ind_pars[TVAO_ELEVATION]+num_pars[TVAO_ELEVATION];
} else {
ind_pars[TVAO_TERR_ELEV] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_TERR_ELEV"));
}
ind_pars[TVAO_SCENE_OFFSET] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_SCENES"));
par_index = new int[TVAO_TYPES][];
for (int n = 0; n < par_index.length; n++) {
if (n < TVAO_SCENE_OFFSET) {
//((n == TVAO_TERR_ELEV) && terr_elevation_full)
if (n == TVAO_TERR_ELEV) {
par_index[n] = new int[terr_elevation_full? image_length: 1]; // num_pars[TVAO_TERR_ELEV]?
} else if (n < TVAO_SCENE_OFFSET) {
par_index[n] = new int[image_length];
} else {
par_index[n] = new int[num_scenes]; // same as when creating original
......@@ -5266,12 +5278,12 @@ public class VegetationLMA {
parameters_vector = new double [num_pars];
par_rindex = new int [num_pars][2];
for (int n = 0; n < TVAO_TYPES; n++) {
for (int indx = 0; ((indx < indices[n].length) && (indx < par_index[n].length)); indx++) { // woi_veg
for (int indx = 0; ((indx < indices[n].length) && (indx < par_index[n].length)); indx++) { // woi_max
int findx = indx;
int pindx = indices[n][indx];
if (n < TVAO_SCENE_OFFSET) {
int x = (indx % woi_veg.width) + woi_veg.x;
int y = (indx / woi_veg.width) + woi_veg.y;
if ((n < TVAO_SCENE_OFFSET) && ((n != TVAO_TERR_ELEV) || terr_elevation_full)) {
int x = (indx % woi_max.width) + woi_max.x;
int y = (indx / woi_max.width) + woi_max.y;
findx = x + y * full.width;
}
par_index[n][findx] = pindx;
......@@ -5283,7 +5295,6 @@ public class VegetationLMA {
}
}
// TODO: build other data structures and make instance consistent, without it this does not allow reading from file
// }
return data;
}
......@@ -5299,8 +5310,13 @@ public class VegetationLMA {
throw new IllegalArgumentException("Could not read "+path);
}
int num_slices = imp_pars.getStack().getSize();
/*
if (num_slices != 10) {
throw new IllegalArgumentException("Expecting an 10-slice file, got "+num_slices);
}
*/
if (num_slices != 12) {
throw new IllegalArgumentException("Expecting an 12-slice file, got "+num_slices);
}
int width = imp_pars.getWidth(); // woi_veg.width
int height = imp_pars.getHeight(); // woi_veg.height
......@@ -5346,6 +5362,9 @@ public class VegetationLMA {
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_Y")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_WIDTH")),
Integer.parseInt((String) imp_pars.getProperty("WOI_VEG_HEIGHT")));
if ((woi_veg.width <= 0) || (woi_veg.height <=0)) {
woi_veg = null;
}
Rectangle woi_terr = new Rectangle (
getProperty(imp_pars,"WOI_TERR_X", woi.x), // use woi for old files
getProperty(imp_pars,"WOI_TERR_Y", woi.y), // use woi for old files
......@@ -5360,26 +5379,42 @@ public class VegetationLMA {
for (int i = 0; i < TVAO_NAMES.length; i++) {
disable_names[i]= "FIT_DISABLE_"+TVAO_NAMES[i];
}
boolean [][] valid_scene_pix = new boolean [3][]; // no overlaid
boolean [][] valid_scene_pix = new boolean [(woi_veg==null) ? 2 : 3][]; // no overlaid
valid_scene_pix[0] = new boolean [num_scenes];
for (int n = 0; n < num_scenes; n++) {
valid_scene_pix[0][n] = indices[TVAO_SCENE_OFFSET][n] >=0;
}
valid_scene_pix[1] = new boolean [woi.width*woi.height];
for (int n = 0; n < valid_scene_pix[1].length; n++) {
int wx = n % woi.width;
int wy = n / woi.width;
int wvindex = (wx + woi.x-woi_veg.x) + (wy + woi.y-woi_veg.y)*woi_veg.width;
valid_scene_pix[1][n] = indices[TVAO_TERRAIN][wvindex] >=0;
}
valid_scene_pix[2] = new boolean [woi_veg.width*woi_veg.height];
for (int n = 0; n < valid_scene_pix[2].length; n++) {
valid_scene_pix[2][n] = indices[TVAO_VEGETATION][n] >=0;
}
for (int n = 0; n < valid_scene_pix[1].length; n++) { // index inside woi
/// int wx = n % woi.width;
/// int wy = n / woi.width;
//// int wvindex = (wx + woi.x-woi_veg.x) + (wy + woi.y-woi_veg.y)*woi_veg.width;
/// int wmindex = (wx + woi.x-woi_max.x) + (wy + woi.y - woi_max.y) * woi_max.width;
int wmindex = getWoiIndex( // index inside woi_max and also the restored image
woi, // Rectangle woi_src,
woi_max, // Rectangle woi_dst,
full, // Rectangle woi_full,
n); // int indx)
valid_scene_pix[1][n] = indices[TVAO_TERRAIN][wmindex] >=0;
}
if (woi_veg != null) {
valid_scene_pix[2] = new boolean [woi_veg.width * woi_veg.height]; // here woi_veg, not woi_max
for (int n = 0; n < valid_scene_pix[2].length; n++) { // index in woi_veg
int wmindx = getWoiIndex( // index inside woi_max and also the restored image
woi_veg, // Rectangle woi_src,
woi_max, // Rectangle woi_dst,
full, // Rectangle woi_full,
n); // int indx)
valid_scene_pix[2][n] = indices[TVAO_VEGETATION][wmindx] >=0;
}
}
// int num_samples =
terr_elevation_full = getProperty(imp_pars,"TERR_ELEVATION_FULL", terr_elevation_full);
prepareLMA(
false, // final boolean keep_parameters,
woi, // final Rectangle woi,
/// Here woi_terr is always non-null and woi_veg may be null (if terrain-only)
woi_veg, // final Rectangle woi_veg_in, // used when loading from file (may be different)
woi_terr, // final Rectangle woi_terr_in, // used when loading from file (may be different)
getProperty(imp_pars,"MAX_WARP", max_warp), // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
......@@ -5396,6 +5431,7 @@ public class VegetationLMA {
getProperty(imp_pars, "FIT_SCENE_OFFSET", fits[TVAO_SCENE_OFFSET]),// final boolean adjust_scenes,
getProperty(imp_pars, "FIT_ELEVATION", fits[TVAO_ELEVATION]), // final boolean adjust_elevations,
getProperty(imp_pars, "FIT_TERR_ELEV", fits[TVAO_TERR_ELEV]), // final boolean adjust_terr_elev,
// getProperty(imp_pars,"TERR_ELEVATION_FULL", terr_elevation_full),
getProperty(imp_pars, disable_names, fits_disable), // final boolean [] fit_disable,
getProperty(imp_pars, "REG_WEIGHTS", reg_weights), // final double reg_weights, // fraction of the total weight used for regularization
getProperty(imp_pars, "ALPHA_LOSS", alpha_loss), // final double alpha_loss, // alpha quadratic growing loss for when out of [0,1] range
......@@ -5461,7 +5497,12 @@ public class VegetationLMA {
ind_pars[TVAO_VEGETATION] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_VEGETATION"));
ind_pars[TVAO_ALPHA] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_ALPHA"));
ind_pars[TVAO_ELEVATION] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_ELEVATION"));
ind_pars[TVAO_TERR_ELEV] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_TERR_ELEV"));
// bug fix (remove later)
if (imp_pars.getProperty("IND_PARS_TERR_ELEV") == null) {
ind_pars[TVAO_TERR_ELEV] = ind_pars[TVAO_ELEVATION]+num_pars[TVAO_ELEVATION];
} else {
ind_pars[TVAO_TERR_ELEV] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_TERR_ELEV"));
}
ind_pars[TVAO_SCENE_OFFSET] = Integer.parseInt((String) imp_pars.getProperty("IND_PARS_SCENES"));
par_index = new int[TVAO_TYPES][];
......@@ -5504,13 +5545,13 @@ public class VegetationLMA {
parameters_vector = new double [num_pars];
par_rindex = new int [num_pars][2];
for (int n = 0; n < TVAO_TYPES; n++) {
for (int indx = 0; ((indx < indices[n].length) && (indx < par_index[n].length)); indx++) { // woi_veg
for (int indx = 0; ((indx < indices[n].length) && (indx < par_index[n].length)); indx++) { // woi_max
int findx = indx;
int pindx = indices[n][indx];
// if (n < TVAO_SCENE_OFFSET) {
if (n < TVAO_TERR_ELEV) { //TVAO_TERR_ELEV and TVAO_SCENE_OFFSET - same, direct index
int x = (indx % woi_veg.width) + woi_veg.x;
int y = (indx / woi_veg.width) + woi_veg.y;
int x = (indx % woi_max.width) + woi_max.x;
int y = (indx / woi_max.width) + woi_max.y;
findx = x + y * full.width;
}
par_index[n][findx] = pindx;
......@@ -5763,7 +5804,7 @@ public class VegetationLMA {
debug_path, // String debug_path,
debug_save_improved, // boolean debug_save_improved, // Save debug image after successful LMA step.");
debug_save_worsened); //boolean debug_save_worsened) // Save debug image after unsuccessful LMA step.");
if (!woi_veg.contains(woi)) {
if ((woi_veg != null) && !woi_veg.contains(woi)) {
System.out.println("****** readAllSegments(): bad data, woi_veg does not contain woi!");
System.out.println("----- readAllSegments() segment "+(n+1)+" (of "+par_files.length+")");
System.out.println("----- woi="+woi.toString()+", woi_veg="+woi_veg.toString());
......@@ -5799,7 +5840,11 @@ public class VegetationLMA {
Runtime runtime = Runtime.getRuntime();
runtime.gc();
System.out.println("----- readAllSegments() segment "+(n+1)+" (of "+par_files.length+") --- Free memory="+runtime.freeMemory()+" (of "+runtime.totalMemory()+")");
System.out.println("----- woi="+woi.toString()+", woi_veg="+woi_veg.toString());
if (woi_veg == null) {
System.out.println("----- woi="+woi.toString()+", woi_veg= null (terrain-only)");
} else {
System.out.println("----- woi="+woi.toString()+", woi_veg="+woi_veg.toString());
}
System.out.println("----- "+par_files[n].getPath());
}
}
......@@ -6006,24 +6051,24 @@ public class VegetationLMA {
if (nw < samples_pointers[SAMPLES_Y_HF][0]) { // DC differences
weights[nw] = scene_weights[y_src[nw][YSRC_SCENE]] * k;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 1");
System.out.println("setupWeights() weights["+nw+"]=NaN - 1");
}
} else if (nw < samples_pointers[SAMPLES_Y_AVG][0]) { // HF differences if exist
weights[nw] = scene_weights[y_src_hf[nw-y_src.length][YSRC_SCENE]] * k * hifreq_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 2");
System.out.println("setupWeights() weights["+nw+"]=NaN - 2");
}
} else if (nw < samples_pointers[SAMPLES_EXTRA][0]) { // y_wavg if exists
weights[nw] = k * terrain_correction_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 3");
System.out.println("setupWeights() weights["+nw+"]=NaN - 3");
}
} else {
weights[nw] = reg_sample_weight;
if (Double.isNaN(weights[nw])) {
System.out.println("weights["+nw+"]=NaN - 4");
System.out.println("setupWeights() weights["+nw+"]=NaN - 4");
}
}
}
......@@ -6048,6 +6093,9 @@ public class VegetationLMA {
public double [] getElevation ( // 0.0 in undefined pixels
double [] vector_in,
boolean only_parameters) {
if (woi_veg == null) {
return null;
}
final double [] vector = (vector_in != null) ? vector_in : parameters_vector;
final int woi_veg_length = woi_veg.width*woi_veg.height;
final double [] elevations = new double [woi_veg_length];
......@@ -6088,6 +6136,9 @@ public class VegetationLMA {
double [] vector_in,
boolean only_parameters) {
final double [] vector = (vector_in != null) ? vector_in : parameters_vector;
if (woi_veg==null) {
return null;
}
final int woi_veg_length = woi_veg.width*woi_veg.height;
final double [] alphas = new double [woi_veg_length];
Arrays.fill(alphas, Double.NaN);
......@@ -6127,6 +6178,9 @@ public class VegetationLMA {
public double [] getVegetation ( // NaN in undefined pixels
double [] vector_in,
boolean only_parameters) {
if (woi_veg == null) {
return null;
}
final double [] vector = (vector_in != null) ? vector_in : parameters_vector;
final int woi_veg_length = woi_veg.width*woi_veg.height;
final double [] vegetations = new double [woi_veg_length];
......@@ -6318,14 +6372,13 @@ public class VegetationLMA {
final double [][][] transparency_data) { // double [3][][]
final double [] border_weights = {0.01, 0.03, 0.1, 0.3};
final boolean apply_transparency_fade = true;
// final int woi_veg_length = woi_veg.width * woi_veg.height;
final int woi_length = woi.width * woi.height;
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
final double [][] transparency = getTransparency((vector==null)? parameters_vector:vector, false);
final double [][] transparency_raw = transparency.clone(); // shallow
double [][] transparency_fade = null;
if (apply_transparency_fade) {
if ((apply_transparency_fade) && (woi_veg != null)) {
transparency_fade = getSceneTransparencyFade(
vector, // final double [] vector, // parameters vector or null
border_weights); // final double [] border_weights);
......@@ -6407,6 +6460,9 @@ public class VegetationLMA {
public double [] getVegetationFade(
final double [] vector, // parameters vector or null
final double [] border_weights) {
if (woi_veg == null) {
return null;
}
final int woi_veg_length = woi_veg.width * woi_veg.height;
double [] alphas = getAlpha (vector, true);
double [] wnd = new double [woi_veg_length];
......@@ -6458,6 +6514,9 @@ public class VegetationLMA {
double [][] getSceneTransparencyFade(
final double [] vector, // parameters vector or null
final double [] border_weights) {
if (woi_veg == null) {
return null;
}
final int woi_veg_length = woi_veg.width * woi_veg.height;
final double [] vector_fade = (vector == null) ? parameters_vector.clone() : vector.clone();
double [] vegetation_fade = getVegetationFade(
......@@ -6538,7 +6597,7 @@ public class VegetationLMA {
final boolean ttop_no_border,// true; // No maximums on the border allowed
final String dbg_prefix,
final int debugLevel) {
if (!ttop_en) {
if (!ttop_en || (woi_veg == null)) {
return null;
}
final int woi_veg_length = woi_veg.width*woi_veg.height;
......@@ -7282,21 +7341,6 @@ public class VegetationLMA {
private void setupParametersVector() {
// setup terrain parameters (use inner woi)
/*
for (int drow = 0; drow < woi.height; drow++) {
int row = woi.y + drow;
for (int dcol = 0; dcol < woi.width; dcol++) {
int col = woi.x + dcol;
int indx = row*full.width + col;
if (par_index[TVAO_TERRAIN][indx] >= 0) {
parameters_vector[par_index[TVAO_TERRAIN][indx]] = tvao[TVAO_TERRAIN][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_TERRAIN][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_TERRAIN+"]["+indx+"]]=NaN");
}
}
}
}
*/
for (int drow = 0; drow < woi_terr.height; drow++) {
int row = woi_terr.y + drow;
for (int dcol = 0; dcol < woi_terr.width; dcol++) {
......@@ -7310,30 +7354,32 @@ public class VegetationLMA {
}
}
}
for (int drow = 0; drow < woi_veg.height; drow++) {
int row = woi_veg.y + drow;
for (int dcol = 0; dcol < woi_veg.width; dcol++) {
int col = woi_veg.x + dcol;
int indx = row*full.width + col;
if (par_index[TVAO_VEGETATION][indx] >= 0) {
parameters_vector[par_index[TVAO_VEGETATION][indx]] = tvao[TVAO_VEGETATION][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_VEGETATION][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_VEGETATION+"]["+indx+"]]=NaN");
if (woi_veg != null) { // otherwise - terrain-only
for (int drow = 0; drow < woi_veg.height; drow++) {
int row = woi_veg.y + drow;
for (int dcol = 0; dcol < woi_veg.width; dcol++) {
int col = woi_veg.x + dcol;
int indx = row*full.width + col;
if (par_index[TVAO_VEGETATION][indx] >= 0) {
parameters_vector[par_index[TVAO_VEGETATION][indx]] = tvao[TVAO_VEGETATION][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_VEGETATION][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_VEGETATION+"]["+indx+"]]=NaN");
}
}
}
if (par_index[TVAO_ALPHA][indx] >= 0) {
parameters_vector[par_index[TVAO_ALPHA][indx]] = tvao[TVAO_ALPHA][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_ALPHA][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_ALPHA+"]["+indx+"]]=NaN");
if (par_index[TVAO_ALPHA][indx] >= 0) {
parameters_vector[par_index[TVAO_ALPHA][indx]] = tvao[TVAO_ALPHA][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_ALPHA][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_ALPHA+"]["+indx+"]]=NaN");
}
}
}
if (par_index[TVAO_ELEVATION][indx] >= 0) {
parameters_vector[par_index[TVAO_ELEVATION][indx]] = tvao[TVAO_ELEVATION][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_ELEVATION][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_ELEVATION+"]["+indx+"]]=NaN");
if (par_index[TVAO_ELEVATION][indx] >= 0) {
parameters_vector[par_index[TVAO_ELEVATION][indx]] = tvao[TVAO_ELEVATION][indx];
if (Double.isNaN(parameters_vector[par_index[TVAO_ELEVATION][indx]])) {
System.out.println("parameters_vector[par_index["+TVAO_ELEVATION+"]["+indx+"]]=NaN");
}
}
}
}
......@@ -7351,7 +7397,7 @@ public class VegetationLMA {
}
private void setupParametersIndices(
boolean [] fits,
boolean [] fits, // should have disabled vegetation, alphja, elevation when woi_veg = null
final int debugLevel) {
par_index = new int [TVAO_TYPES][];
par_index[TVAO_TERRAIN] = new int [image_length];
......@@ -7375,18 +7421,12 @@ public class VegetationLMA {
int par_num = 0;
ind_pars[TVAO_TERRAIN] = 0;
if (fits[TVAO_TERRAIN]) {
// for (int drow = 0; drow < woi.height; drow++) { // use inner woi for terrain
for (int drow = 0; drow < woi_terr.height; drow++) { // terrain woi for terrain
// int row = woi.y + drow;
int row = woi_terr.y + drow;
// for (int dcol = 0; dcol < woi.width; dcol++) {
for (int dcol = 0; dcol < woi_terr.width; dcol++) {
// int col = woi.x + dcol;
int col = woi_terr.x + dcol;
// int windx =dcol + drow * woi.width;
int wtindx =dcol + drow * woi_terr.width;
int findx = row * full.width + col;
// if (valid_terr_proj[windx]) { // woi
if (valid_terrain[wtindx]) { // woi
par_rindex[par_num][0] = TVAO_TERRAIN;
par_rindex[par_num][1] = findx;
......@@ -7891,40 +7931,59 @@ public class VegetationLMA {
// woi_veg_new.y=amin_y.get();
// woi_veg_new.width= amax_x.get()-amin_x.get()+1;
// woi_veg_new.height= amax_y.get()-amin_y.get()+1;
if (!woi_veg_new.contains(woi)) {
System.out.println("\n***** BUG FIX:woi_veg_new="+woi_veg_new.toString()+" does not contain woi="+woi.toString()+", increasing woi_veg_new");
Rectangle r = new Rectangle(woi_veg_new);
r.add(woi);
woi_veg_new.x=r.x;
woi_veg_new.y=r.y;
woi_veg_new.width= r.width;
woi_veg_new.height= r.height;
System.out.println("Updated woi_veg_new="+woi_veg_new.toString()+"\n");
boolean continue_no_veg = true;
boolean terrain_only = (woi_veg_new.width <= 0) || (woi_veg_new.width <= 0);
if (terrain_only) {
System.out.println("woi_veg_new="+woi_veg_new.toString()+", no vegetation in woi! *****");
if (!continue_no_veg) {
return null;
}
woi_veg_new = null;
} else {
if (!woi_veg_new.contains(woi)) {
System.out.println("\n***** BUG FIX:woi_veg_new="+woi_veg_new.toString()+" does not contain woi="+woi.toString()+", increasing woi_veg_new");
Rectangle r = new Rectangle(woi_veg_new);
r.add(woi);
woi_veg_new.x=r.x;
woi_veg_new.y=r.y;
woi_veg_new.width= r.width;
woi_veg_new.height= r.height;
System.out.println("Updated woi_veg_new="+woi_veg_new.toString()+"\n");
}
}
if (woi_veg.width == 0) {
if (woi_veg_new != null) {
woi_veg.x = woi_veg_new.x;
woi_veg.y = woi_veg_new.y;
woi_veg.width = woi_veg_new.width;
woi_veg.height = woi_veg_new.height;
}
// copy num_used to a smaller array
} else {
System.out.println("Using provided woi_veg="+woi_veg.toString()+"\n");
if (!woi_veg.equals(woi_veg_new)) {
System.out.println("***** Provided woi_veg="+woi_veg.toString()+" does not match calculated one="+woi_veg_new.toString());
if (terrain_only || !woi_veg.equals(woi_veg_new)) {
if (terrain_only) {
System.out.println("***** Provided woi_veg="+woi_veg.toString()+" does not match calculated one=null");
} else {
System.out.println("***** Provided woi_veg="+woi_veg.toString()+" does not match calculated one="+woi_veg_new.toString());
}
System.out.println("***** Using the provided one");
}
}
final boolean [] valid_vegetation = new boolean [woi_veg.width*woi_veg.height];
for (int row = 0; row < woi_veg.height; row++) {
int row_src = row + woi_veg.y - woi_ext.y;
int col_src = woi_veg.x - woi_ext.x;
System.arraycopy(
veg_scene_used,
col_src + row_src * woi_ext.width,
valid_vegetation,
row*woi_veg.width,
woi_veg.width);
final boolean [] valid_vegetation = terrain_only? null : new boolean [woi_veg.width*woi_veg.height];
if (valid_vegetation != null) {
for (int row = 0; row < woi_veg.height; row++) {
int row_src = row + woi_veg.y - woi_ext.y;
int col_src = woi_veg.x - woi_ext.x;
System.arraycopy(
veg_scene_used,
col_src + row_src * woi_ext.width,
valid_vegetation,
row*woi_veg.width,
woi_veg.width);
}
}
......@@ -7938,7 +7997,7 @@ public class VegetationLMA {
final boolean [] terr_scene_used_prefilter = new boolean [woi_terr_ext_len]; // which of the source terrain pixel may be used
final boolean [] terr_scene_used = new boolean [woi_terr_ext_len]; // which of the source terrain pixel may be used
final boolean [][][] has_terr_thread = new boolean [threads.length][num_scenes][woi_length];
final boolean [][] has_terr_scene = new boolean [num_scenes][woi_length]; // which image pixels in woi have source terrain
/// final boolean [][] has_terr_scene = new boolean [num_scenes][woi_length]; // which image pixels in woi have source terrain
ai.set(0);
ati.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
......@@ -7950,8 +8009,8 @@ public class VegetationLMA {
int x = wtindx % woi_terr_ext.width + woi_terr_ext.x;
int findx = x + y * full.width;
double radius = elev_radius[findx]; // reuse same as for vegetation =1.5
double radius2 = radius*radius;
// int iradius = (int) Math.ceil (radius);
/// double radius2 = radius*radius;
/// int iradius = (int) Math.ceil (radius);
double terrain = tvao[TVAO_TERRAIN][findx];
if (!Double.isNaN(terrain)) {
for (int nscene = 0; nscene < num_scenes; nscene++) if (valid_scenes[nscene]){
......@@ -8004,6 +8063,7 @@ public class VegetationLMA {
};
}
ImageDtt.startAndJoin(threads);
/*
// combine from threads - which image pixels in woi may have source terrain
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
......@@ -8020,24 +8080,24 @@ public class VegetationLMA {
};
}
ImageDtt.startAndJoin(threads);
*/
boolean [] has_terrain = new boolean [woi_length]; // which image pixels in woi have source terrain
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int wIndx = ai.getAndIncrement(); wIndx < woi_length; wIndx = ai.getAndIncrement()){
for (int wpix = 0; wpix < valid_vegetation.length; wpix++) {
for (int nscene = 0; nscene < num_scenes; nscene++) if (valid_scenes[nscene]){
has_terrain[wIndx] |= has_terr_scene[nscene][wIndx];
for (int nscene = 0; nscene < num_scenes; nscene++) if (valid_scenes[nscene]){
for (int nthread =0; nthread < has_veg_thread.length; nthread++) {
has_terrain[wIndx] |=has_terr_thread[nthread][nscene][wIndx];
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
// *****************************************************
final AtomicInteger atmax_x = new AtomicInteger(0);
final AtomicInteger atmax_y = new AtomicInteger(0);
......@@ -8143,7 +8203,7 @@ public class VegetationLMA {
// delete scenes that have too high warp
AtomicInteger abad_warp = new AtomicInteger(0);
if ((warps != null) && (max_warp > 1.0)) {
if ((warps != null) && (max_warp > 1.0) && !terrain_only) {
boolean [] valid_prewarp = valid_scenes.clone();
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
......@@ -8200,20 +8260,20 @@ public class VegetationLMA {
};
}
ImageDtt.startAndJoin(threads);
ai.set(0);
int woi_veg_length = woi_veg.width*woi_veg.height;
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int wPix = ai.getAndIncrement(); wPix < woi_veg_length; wPix = ai.getAndIncrement()) {
if (valid_vegetation[wPix]) astats[2].getAndIncrement();
if (!terrain_only) {
ai.set(0);
int woi_veg_length = woi_veg.width*woi_veg.height;
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int wPix = ai.getAndIncrement(); wPix < woi_veg_length; wPix = ai.getAndIncrement()) {
if (valid_vegetation[wPix]) astats[2].getAndIncrement();
}
}
}
};
}
ImageDtt.startAndJoin(threads);
};
}
ImageDtt.startAndJoin(threads);
}
ai.set(0);
int woi_terr_length = woi_terr.width*woi_terr.height;
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
......@@ -8236,7 +8296,7 @@ public class VegetationLMA {
stats[5] = astats[5].get(); // number of Y pixels (woi) that are influenced by the terrain
stats[6] = abad_warp.get(); // number of scenes removed for bad warp
}
if ((warps != null) && (max_warp_scene_pix != null)) {
if ((warps != null) && (max_warp_scene_pix != null) && !terrain_only) {
final int [][] max_warp_scene_pix_thread = new int [threads.length][];
final double [] max_warp_thread = new double [threads.length];
ai.set(0);
......
......@@ -1625,8 +1625,8 @@ public class VegetationModel {
boolean debug_save_worsened = clt_parameters.imp.terr_debug_worsened;
int debug_length = clt_parameters.imp.terr_debug_length;
boolean rebuild_elev = clt_parameters.imp.terr_rebuild_elev;
int elevations1_grow = clt_parameters.imp.terr_elev_grow;
// boolean restore_mode = false;
boolean save_par_files = true; // false;
......@@ -1730,7 +1730,11 @@ public class VegetationModel {
*/
double dir_sigma = 16;
if ((elevations == null) || (scale_dirs == null)){
if ((elevations == null) || (scale_dirs == null) || rebuild_elev){
if ((debugLevel > -10) && rebuild_elev) {
System.out.println("***** Forced elevations rebuild. Turn it off next time! *****");
}
//Moving it here to generate needed vegetation_inv_warp_md
if (debugLevel > -3) { // 3) { //-2) {
// probably will not use these, but as optional
......@@ -1847,7 +1851,7 @@ public class VegetationModel {
reference_scene+"-max_min_offsets.tiff",
new String[] {"max_offsets", "min_offsets"});
int elevations1_grow = 20; // 64
// int elevations1_grow = 1024; // 20; // 64
double dir_sigma_scales = 128; // 8; //
int radius_outliers = 8; // 8;
double min_frac = 0.02; // 0.2; // minimal fraction of the full square to keep (0.25 for the corners
......@@ -1857,6 +1861,11 @@ public class VegetationModel {
double min_elevation = 2.0; // for scales - use only elevations avove this.
// double [][] elevation_scales = new double[vegetation_inv_warp_md.length][];
double [][][] elevation_scale_dirs = new double[vegetation_inv_warp_md.length][][];
if (debugLevel > -3) {
System.out.println("***** Will grow elevation/sceles by "+elevations1_grow+" pixels (ortho).");
}
double [] elevations = enhanceElevations(
max_offsets, // final double [] elevations,
vegetation_inv_warp_md, // final double [][][] mag_dirs,
......@@ -2088,10 +2097,10 @@ public class VegetationModel {
woi, // final Rectangle woi,
null, // final Rectangle woi_veg_in, // used when loading from file (may be different)
null, // final Rectangle woi_terr_in, // used when loading from file (may be different)
max_warp, // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
max_warp, // final double max_warp, // 1.8 - do not use scenes where distance between vegetation projection exceeds this
max_elevation, // final int max_offset, // maximal "elevation" to consider
max_elev_terr, // final int max_elev_terr, // maximal terrain "elevation" to consider
max_elev_terr_chg, // final double max_elev_terr_chg, // 0.5 maximal terrain elevation change from last successfully used
max_elev_terr_chg, // final double max_elev_terr_chg,// 0.5 maximal terrain elevation change from last successfully used
elevation_radius, // final double elevation_radius, // Radius of elevation/vegetation influence.
null, // final boolean [] valid_scene_pix,
hifreq_weight, //final double hifreq_weight, // 22.5 0 - do not use high-freq. Relative weight of laplacian components
......@@ -2382,7 +2391,7 @@ public class VegetationModel {
final int area = size* size;
final int min_num = (int) Math.round(area * min_frac);
final boolean [] keep = new boolean [num_pixels];
final int dbg_pix = -(640*171+172);
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
......@@ -2391,6 +2400,9 @@ public class VegetationModel {
TileNeibs tn = new TileNeibs(width, height);
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if (!Double.isNaN(data[nPix])){
if (nPix == dbg_pix) {
System.out.println("removeLocalOutliers(): nPix="+nPix);
}
int num_below = 0, num_above=0, num=0;
double d = data[nPix];
for (int dy = -radius; dy <= radius; dy++) {
......@@ -2403,9 +2415,9 @@ public class VegetationModel {
if (d1 <= d) num_below++; // equal should go to both
}
}
if ((num >= min_num) && (num_above >= num*remove_frac_hi) && (num_below >= num * remove_frac_lo)){
keep[nPix] = true;
}
}
if ((num >= min_num) && (num_above >= num*remove_frac_hi) && (num_below >= num * remove_frac_lo)){
keep[nPix] = true;
}
}
}
......@@ -2444,6 +2456,7 @@ public class VegetationModel {
final double remove_frac_lo, // total,
final double [][][] elevation_scale_dirs,
final boolean debug) {
final int debugLevelFillNan = 1;
final int num_scenes = mag_dirs.length;
final int num_pixels = elevations.length;
final String [] titles_top = {"scales","outliers_removed","ext_scales", "smooth_scales"};
......@@ -2498,6 +2511,7 @@ public class VegetationModel {
if (dbg_img != null) {
dbg_img[1][nscene] = scales[nscene].clone();
}
/*
scales[nscene] = TileProcessor.fillNaNs(
scales[nscene], // final double [] data,
null, // final boolean [] prohibit,
......@@ -2505,10 +2519,33 @@ public class VegetationModel {
// CAREFUL ! Remaining NaN is grown by unsharp mask filter ************* !
grow, // 100, // 2*width, // 16, // final int grow,
0.7, // double diagonal_weight, // relative to ortho
100, // int num_passes,
0.03); // final double max_rchange, // = 0.01 - does not need to be accurate
10, // 100, // int num_passes,
0.03); // final double max_rchange, // = 0.01 - does not need to be accurate
*/
int decimate_step = 16;
int num_decimate = 1;
String debugTitle = null; // "fillNaN-"+nscene;
scales[nscene] = TileProcessor.fillNaNs(
scales[nscene], // final double [] data,
width, // int width_full,
decimate_step, // final int decimate_step, // 16
num_decimate, // final int num_decimate,
100, // 100, // int num_passes,
0.03, // final double max_rchange, // = 0.01 - does not need to be accurate
debugTitle, // String debugTitle);//
debugLevelFillNan); // final int debugLevel) { // 0 - none, 1 - when done, 2 - all iterations
if (debug) {
System.out.println("enhanceElevations() nscene="+nscene);
/*
ShowDoubleFloatArrays.showArrays(
scales[nscene],
width,
scales[nscene].length/width,
"scales-"+nscene);
*/
}
}
ai.set(0);
......@@ -2623,6 +2660,7 @@ public class VegetationModel {
}
ImageDtt.startAndJoin(threads);
if (elevation_scale_dirs != null) {
/*
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
......@@ -2638,11 +2676,115 @@ public class VegetationModel {
}
ImageDtt.startAndJoin(threads);
// System.arraycopy(scales, 0, elevation_scales, 0, num_scenes);
*/
int decimate_step = 16;
int num_decimate = 1;
String debugTitle = null;
fillScaleDirs(
mag_dirs, // final double [][][] mag_dirs,
scales, // final double [][] scales,
elevation_scale_dirs, // final double [][][] elevation_scale_dirs,
width, // final int width,
decimate_step, // final int decimate_step, // 16
num_decimate, // final int num_decimate,
100, // final int num_passes,
0.03, // final double max_rchange, //
debugTitle, // final String debugTitle,
1); // final int debugLevel)
}
// IJ.getNumber("Any number", 0);
return elevations_out;
}
/*
* Fill NaNs in mag_dirs and copy results to elevation_scale_dirs[num_scenes][][]
* @param mag_dirs per scene, per pixel - null or a pair of {magnitude, direction}
* @param scales filtered no-NaN scales to be used as magnitudes
* @param elevation_scale_dirs array initialized with number of scenes of nulls to accommodate parirs of {magnitude,direction}
* @param width image width
*/
/**
* Fill NaNs in mag_dirs and copy results to elevation_scale_dirs[num_scenes][][]
* @param mag_dirs per scene, per pixel - null or a pair of {magnitude, direction}
* @param scales filtered no-NaN scales to be used as magnitudes
* @param elevation_scale_dirs array initialized with number of scenes of nulls to accommodate parirs of {magnitude,direction}
* @param width image width
* @param decimate_step decimation step (such as 16)
* @param num_decimate number of decimation steps (should be >=1). If 1 just two passes
* @param num_passes number of passes for each decimation step (100)
* @param max_rchange maximal relative change to exit
* @param debugTitle Generate images if non-null
* @param debugLevel debug inner method: 0 - none, 1 - when done, 2 - all iterations
*/
public static void fillScaleDirs(
final double [][][] mag_dirs,
final double [][] scales,
final double [][][] elevation_scale_dirs,
final int width,
final int decimate_step, // 16
final int num_decimate,
final int num_passes,
final double max_rchange, //
final String debugTitle,
final int debugLevel) {
final int num_scenes = mag_dirs.length;
final int num_pixels = mag_dirs[0].length;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final double [][] scales_xy = new double [2][num_pixels];
for (int nscene = 0; nscene < num_scenes; nscene++) {
final int fnscene = nscene;
if (debugLevel > -1) {
System.out.println("fillScaleDirs(): "+(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()))+
" processing scene "+fnscene);
}
for (int i = 0; i < scales_xy.length; i++) {
Arrays.fill(scales_xy[i], Double.NaN);
}
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) if ((mag_dirs[fnscene][nPix] != null) &&( !Double.isNaN(scales[fnscene][nPix]))) {
scales_xy[0][nPix] = scales[fnscene][nPix] * Math.cos(mag_dirs[fnscene][nPix][1]);
scales_xy[1][nPix] = scales[fnscene][nPix] * Math.sin(mag_dirs[fnscene][nPix][1]);
}
}
};
}
ImageDtt.startAndJoin(threads);
for (int i = 0; i < scales_xy.length; i++) {
scales_xy[i] = TileProcessor.fillNaNs(
scales_xy[i], // final double [] data,
width, // int width_full,
decimate_step, // final int decimate_step, // 16
num_decimate, // final int num_decimate,
100, // int num_passes,
0.03, // final double max_rchange, // = 0.01 - does not need to be accurate
debugTitle, // String debugTitle);//
debugLevel); // final int debugLevel) { // 0 - none, 1 - when done, 2 - all iterations
}
elevation_scale_dirs[fnscene] = new double [num_pixels][2];
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) { // first sum for pairs
threads[ithread] = new Thread() {
public void run() {
for (int nPix = ai.getAndIncrement(); nPix < num_pixels; nPix = ai.getAndIncrement()) {
elevation_scale_dirs[fnscene][nPix][0] = Math.sqrt (scales_xy[0][nPix]*scales_xy[0][nPix] + scales_xy[1][nPix] *scales_xy[1][nPix]);
elevation_scale_dirs[fnscene][nPix][1] = Math.atan2(scales_xy[1][nPix],scales_xy[0][nPix]);
}
}
};
}
ImageDtt.startAndJoin(threads);
}
return;
}
public static double [] getScenesOverlap(
final double [][][] mag_dirs,
final boolean [][] reliable, // or null
......
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