Commit 590d3aba authored by Andrey Filippov's avatar Andrey Filippov

More untested mapping code, bug fix in variable DSI average disparity

parent 98e487e9
......@@ -509,6 +509,8 @@ public class CLTParameters {
public int gmap_crop_extra = 20;
public int [] gmap_tex_pals = {0,1,2};
public boolean gmap_gnss_vert = true; // reference ll to the point below (false - top left corner)
// use Tiff XPosition, YPosition to specify offset to the vertical in the image
public boolean gmap_save_alt = true; // save height map (meters ASL)
public boolean gmap_save_tiff32 = true; // save float TIFF (NaN for transparency) with geo metadata (top left corner)
public boolean gmap_save_tiff = true; // save transparent TIFF with geo metadata (top left corner)
......@@ -1687,6 +1689,7 @@ public class CLTParameters {
properties.setProperty(prefix+"gmap_crop_extra", this.gmap_crop_extra+""); // int
properties.setProperty(prefix+"gmap_tex_pals", CLTParameters.arr_to_str(this.gmap_tex_pals)); // int[]
properties.setProperty(prefix+"gmap_gnss_vert", this.gmap_gnss_vert+""); // boolean
properties.setProperty(prefix+"gmap_save_alt", this.gmap_save_alt+""); // boolean
properties.setProperty(prefix+"gmap_save_tiff32", this.gmap_save_tiff32+""); // boolean
properties.setProperty(prefix+"gmap_save_tiff", this.gmap_save_tiff+""); // boolean
......@@ -2737,6 +2740,7 @@ public class CLTParameters {
if (properties.getProperty(prefix+"gmap_crop_extra")!=null) this.gmap_crop_extra=Integer.parseInt(properties.getProperty(prefix+ "gmap_crop_extra"));// int
if (properties.getProperty(prefix+"gmap_tex_pals")!=null) this.gmap_tex_pals=CLTParameters.str_to_iarr(properties.getProperty(prefix+"gmap_tex_pals"));
if (properties.getProperty(prefix+"gmap_gnss_vert")!=null) this.gmap_gnss_vert=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_gnss_vert"));
if (properties.getProperty(prefix+"gmap_save_alt")!=null) this.gmap_save_alt=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_save_alt"));
if (properties.getProperty(prefix+"gmap_save_tiff32")!=null) this.gmap_save_tiff32=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_save_tiff32"));
if (properties.getProperty(prefix+"gmap_save_tiff")!=null) this.gmap_save_tiff=Boolean.parseBoolean(properties.getProperty(prefix+ "gmap_save_tiff"));
......@@ -4055,6 +4059,8 @@ public class CLTParameters {
gd.addStringField ("LWIR palettes to render the maps", CLTParameters.arr_to_str(this.gmap_tex_pals), 40,
"Enter space-separated list of the palette numbers, such as, such as '0 1 2'");
gd.addCheckbox ("Reference GNSS LLA to below the camera", this.gmap_gnss_vert, // true; // enable change FG pixel to opaque from transparent
"If false - to the top left image corner(NW). Use Tiff XPosition, YPosition for the offset to the vertical.");
gd.addCheckbox ("Save height map (meters ASL)", this.gmap_save_alt, // true; // enable change FG pixel to opaque from transparent
"Save height map (meters Above Seal Level) as a floating-point single-slice TIFF (NAN for transparency).");
gd.addCheckbox ("Save float Tiff with transparency and Geo",this.gmap_save_tiff32, // true; // enable change FG pixel to opaque from transparent
......@@ -5315,6 +5321,7 @@ public class CLTParameters {
this.gmap_crop_extra= (int) gd.getNextNumber();
this.gmap_tex_pals = CLTParameters.str_to_iarr(gd.getNextString());
this.gmap_gnss_vert= gd.getNextBoolean();
this.gmap_save_alt= gd.getNextBoolean();
this.gmap_save_tiff32= gd.getNextBoolean();
this.gmap_save_tiff= gd.getNextBoolean();
......
......@@ -112,6 +112,7 @@ import com.elphel.imagej.lwir.LwirReader;
import com.elphel.imagej.orthomosaic.ComboMatch;
import com.elphel.imagej.readers.ChangeImageResolution;
import com.elphel.imagej.readers.DumpImageMetadata;
import com.elphel.imagej.readers.ElphelTiffReader;
import com.elphel.imagej.readers.EyesisTiff;
import com.elphel.imagej.tensorflow.TensorflowInferModel;
import com.elphel.imagej.tileprocessor.Clt1d;
......@@ -844,6 +845,8 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
addButton("Show mice", panelLWIRWorld, color_process);
addButton("Set pair", panelLWIRWorld, color_process);
addButton("Warp pair", panelLWIRWorld, color_process);
addButton("Read Tiff", panelLWIRWorld, color_process);
addButton("Set pair GPS", panelLWIRWorld, color_process);
plugInFrame.add(panelLWIRWorld);
}
......@@ -5683,9 +5686,166 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
ComboMatch.testPair();
} else if (label.equals("Read Tiff")) {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
ImagePlus imp_sel = WindowManager.getCurrentImage();
if (imp_sel == null) {
IJ.showMessage("Error", "No images selected");
return;
}
String orig_path = imp_sel.getOriginalFileInfo().getFilePath();
try {
ElphelTiffReader.getTiffMeta(orig_path);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// ComboMatch.testReadTiff();
} else if (label.equals("Set pair GPS")) {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
/*
boolean run_pre = true; // false;
if (run_pre) {
String path = loadProperties(null, CORRECTION_PARAMETERS.resultsDirectory, true, PROPERTIES);
if (path != null) {
getAllProperties(PROPERTIES);
if (DEBUG_LEVEL > -3)
System.out.println("Configuration parameters are restored from " + path);
} else {
if (DEBUG_LEVEL > -10)
System.out.println("Failed to restore configuration parameters");
return;
}
}
*/
if (GPU_TILE_PROCESSOR == null) {
try {
GPU_TILE_PROCESSOR = new GPUTileProcessor(CORRECTION_PARAMETERS.tile_processor_gpu);
} catch (Exception e) {
System.out.println("Failed to initialize GPU class");
// TODO Auto-generated catch block
e.printStackTrace();
return;
} // final int debugLevel);
}
/*
if (!run_pre) {
String path = loadProperties(null, CORRECTION_PARAMETERS.resultsDirectory, true, PROPERTIES);
if (path != null) {
getAllProperties(PROPERTIES);
if (DEBUG_LEVEL > -3)
System.out.println("Configuration parameters are restored from " + path);
} else {
if (DEBUG_LEVEL > -10)
System.out.println("Failed to restore configuration parameters");
return;
}
}
*/
//////////////////////
// Temporarily initialize on scene GPU
boolean init_scene = false; // true;
if (init_scene) {
debugInitOneScene();
}
ComboMatch.openTestPairGps(
CLT_PARAMETERS, // CLTParameters clt_parameters,
GPU_TILE_PROCESSOR,
DEBUG_LEVEL);
}
}
public boolean debugInitOneScene() {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
if (EYESIS_CORRECTIONS_AUX == null) {
EYESIS_CORRECTIONS_AUX = new EyesisCorrections(SYNC_COMMAND.stopRequested,
CORRECTION_PARAMETERS.getAux());
}
EYESIS_CORRECTIONS_AUX.setDebug(DEBUG_LEVEL);
if (QUAD_CLT_AUX == null) {
QUAD_CLT_AUX = new QuadCLT(QuadCLT.PREFIX_AUX, PROPERTIES, EYESIS_CORRECTIONS_AUX,
CORRECTION_PARAMETERS.getAux());
if (DEBUG_LEVEL > 0) {
System.out.println("Created new QuadCLT AUX instance, will need to read CLT kernels");
}
}
String configPath = getSaveCongigPath();
if (configPath.equals("ABORT"))
return false;
EYESIS_CORRECTIONS_AUX.initSensorFiles(DEBUG_LEVEL, false, // boolean missing_ok,
true, // boolean all_sensors, Otherwise - Eyesis
COLOR_PROC_PARAMETERS_AUX.correct_vignetting); // boolean correct_vignetting
int numChannels = EYESIS_CORRECTIONS_AUX.getNumChannels();
// NONLIN_PARAMETERS.modifyNumChannels(numChannels);
CHANNEL_GAINS_PARAMETERS_AUX.modifyNumChannels(numChannels);
if (!QUAD_CLT_AUX.CLTKernelsAvailable()) {
if (DEBUG_LEVEL > 0) {
System.out.println("Reading AUX CLT kernels");
}
QUAD_CLT_AUX.readCLTKernels(CLT_PARAMETERS, THREADS_MAX, UPDATE_STATUS, // update status info
DEBUG_LEVEL);
if (DEBUG_LEVEL > 1) {
QUAD_CLT_AUX.showCLTKernels(THREADS_MAX, UPDATE_STATUS, // update status info
DEBUG_LEVEL);
}
}
if (!QUAD_CLT_AUX.geometryCorrectionAvailable()) {
if (DEBUG_LEVEL > 0) {
System.out.println("Calculating geometryCorrection");
}
if (!QUAD_CLT_AUX.initGeometryCorrection(DEBUG_LEVEL + 2)) {
return false;
}
}
// After kernels and GeometryCorrection
if (CLT_PARAMETERS.useGPU()) { // only init GPU instances if it is used
if (GPU_TILE_PROCESSOR == null) {
try {
GPU_TILE_PROCESSOR = new GPUTileProcessor(CORRECTION_PARAMETERS.tile_processor_gpu);
} catch (Exception e) {
System.out.println("Failed to initialize GPU class");
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} // final int debugLevel);
}
/*
* if (CLT_PARAMETERS.useGPU(false) && (QUAD_CLT != null) && (GPU_QUAD == null))
* { // if GPU main is needed try { GPU_QUAD = new GpuQuad( GPU_TILE_PROCESSOR,
* QUAD_CLT); } catch (Exception e) {
* System.out.println("Failed to initialize GpuQuad class"); // TODO
* Auto-generated catch block e.printStackTrace(); return; // false; } //final
* int debugLevel); QUAD_CLT.setGPU(GPU_QUAD); }
*/
if (CLT_PARAMETERS.useGPU(true) && (QUAD_CLT_AUX != null) && (GPU_QUAD_AUX == null)) { // if GPU AUX is
try {
GPU_QUAD_AUX = new GpuQuad(//
GPU_TILE_PROCESSOR, QUAD_CLT_AUX, CLT_PARAMETERS.gpu_debug_level);
} catch (Exception e) {
System.out.println("Failed to initialize GpuQuad class");
// TODO Auto-generated catch block
e.printStackTrace();
return false; // false;
} // final int debugLevel);
QUAD_CLT_AUX.setGPU(GPU_QUAD_AUX);
}
}
return true;
}
/* ======================================================================== */
public boolean editIMU(boolean aux) {
if (aux) {
......
This diff is collapsed.
package com.elphel.imagej.orthomosaic;
public class FloatImageData {
public int width;
public int height;
public int zoom_lev;
public double [] vert = new double[2]; // x,y offset (in meters) of the point under the camera
public float[] data;
public FloatImageData (
int width,
int height,
int zoom_lev,
double [] vert, // x,y pixel offset of the point under the camera
float[] data) {
this.width = width;
this.height = height;
this.zoom_lev = zoom_lev;
this.vert = vert.clone();
this.data = data;
}
public static int getZoomLevel(
double pix_in_meters) {
return getZoomLevel (pix_in_meters, null, null);
}
public static boolean isZoomValid(double pix_in_meters) {
boolean [] is_zoom_valid = new boolean[1];
getZoomLevel(pix_in_meters,is_zoom_valid, null);
return is_zoom_valid[0];
}
public static double needZoomIn(double pix_in_meters) {
double [] extra_zoom = new double[1];
getZoomLevel(pix_in_meters,null, extra_zoom);
return extra_zoom[0];
}
/**
* Find scale level (0: 1pix/cm, 1 - 2pix/cm, -1 - 0.5 pix/cm) from pixel size in meters
* If scale does not match, provide false in optional valid_zoom[0]
* zoom_in_extra
* @param pix_size_in_meters pixel size in meters (e.g. 0.02 means 2cm/pix)
* @param valid_zoom if provided boolean[1] will return true for valid scale
* @param zoom_in_extra enlarge (1.0x..2.0x) (reduce pixel size) to get to the standard scale
* @return zoom level (the higher - the more detailed) 0: - 1cm/pix,-1: 2cm/pix, 1: 0.5 cm/pix
*/
public static int getZoomLevel(
double pix_size_in_meters, // pixel size in meters
boolean [] valid_zoom,
double [] zoom_in_extra) {
int zl = 0;
double e = 1E-6;
double pix_size_in_cm = 100 * pix_size_in_meters; // pixel size in cm
boolean vz = true;
double ze = 1.0;
if (pix_size_in_cm > (1.0-e)) { // low resolution, pixel size > 1cm
zl++;
while (pix_size_in_cm > (1.0-e)) {
zl--;
pix_size_in_cm /= 2;
} // exits with (1-e) >= pix_in_cm > 0.5 - e/2
vz = pix_size_in_cm < (0.5+e);
if (!vz) {
ze = 2.0 * pix_size_in_cm;
}
} else { // high resolution, pixel size < 1
zl--;
while (pix_size_in_cm <= (1.0-e)) {
zl++;
pix_size_in_cm *= 2;
}// exits with (2-2*e) >= pix_in_cm > (1-e)
vz = pix_size_in_cm > (2.0 - e);
if (!vz) {
ze = pix_size_in_cm;
}
}
if (valid_zoom != null) {
valid_zoom[0] = vz;
}
if (zoom_in_extra != null) {
zoom_in_extra[0] = ze;
}
return zl;
}
}
......@@ -28,7 +28,8 @@ import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.plugins.tiff.TIFFDirectory;
import javax.imageio.plugins.tiff.TIFFField;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
......@@ -136,6 +137,9 @@ public class DumpImageMetadata
IIOMetadata metadata = reader.getImageMetadata(0);
indent(1);
System.out.println("Image metadata");
TIFFDirectory ifd = TIFFDirectory.createFromMetadata(metadata);
TIFFField [] tf = ifd.getTIFFFields();
// TIFFField f1 = ifd.get​TIFFField(286);
dumpMetadata(metadata);
IIOMetadata smetadata = reader.getStreamMetadata();
if (smetadata != null)
......
......@@ -32,9 +32,22 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.plugins.tiff.TIFFDirectory;
import javax.imageio.plugins.tiff.TIFFField;
import javax.imageio.plugins.tiff.TIFFTag;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.plugins.tiff.ExifGPSTagSet;
import org.apache.commons.compress.utils.IOUtils;
import org.joda.time.DateTime;
......@@ -588,4 +601,170 @@ public class ElphelTiffReader extends TiffReader{ // BaseTiffReader {
return comment != null && comment.startsWith("ImageJ=");
}
private static String getFileExtension(File file)
{
String fileName = file.getName();
int lastDot = fileName.lastIndexOf('.');
return fileName.substring(lastDot + 1);
}
public static Properties getTiffMeta(String path) throws IOException {
Properties properties = new Properties();
File file = new File(path);
String extension = getFileExtension(file);
// System.out.println("\nProcessing " + file.getName() + ":\n");
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(extension);
ImageInputStream stream = null;
while (readers.hasNext())
{
ImageReader reader = readers.next();
stream = ImageIO.createImageInputStream(file);
reader.setInput(stream, true);
IIOMetadata metadata = reader.getImageMetadata(0);
TIFFDirectory ifd = TIFFDirectory.createFromMetadata(metadata);
TIFFField [] tfs = ifd.getTIFFFields();
for (TIFFField tf: tfs) {
parseField(tf, properties);
}
stream.close();
}
// Set<String> pnames = properties.stringPropertyNames();
// for (String pn:pnames) {
// System.out.println(pn+": "+properties.getProperty(pn));
// }
return properties;
}
private static void parseField(TIFFField tf, Properties properties) {
if (tf.hasDirectory()) {
TIFFField [] stfs = tf.getDirectory().getTIFFFields();
if ("GPSInfoIFDPointer".equals(tf.getTag().getName())) {
TIFFDirectory gifd = tf.getDirectory();
long [][] lat = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_LATITUDE).getAsRationals();
double dlat = 1.0*lat[0][0]/lat[0][1]+1.0/60*lat[1][0]/lat[1][1]+1.0/3600*lat[2][0]/lat[2][1];
String lat_ref = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_LATITUDE_REF).getValueAsString(0);
if (!lat_ref.equals("N")) {
dlat =- dlat;
}
long [][] lon = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_LONGITUDE).getAsRationals();
double dlon = 1.0*lon[0][0]/lon[0][1]+1.0/60*lon[1][0]/lon[1][1]+1.0/3600*lon[2][0]/lon[2][1];
String lon_ref = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_LONGITUDE_REF).getValueAsString(0);
if (!lon_ref.equals("E")) {
dlon =- dlon;
}
long [] alt = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_ALTITUDE).getAsRational(0);
double dalt = 1.0 *alt[0]/alt[1];
String alt_ref = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_ALTITUDE_REF).getValueAsString(0);
if (!alt_ref.equals("0")) {
dalt =- dalt;
}
String [] date_stamp = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_DATE_STAMP).getValueAsString(0).split(":");
long [][] gts = gifd.getTIFFField(ExifGPSTagSet.TAG_GPS_TIME_STAMP).getAsRationals();
double secs = 3600.0*gts[0][0]/gts[0][1]+60.0*gts[1][0]/gts[1][1]+1.0*gts[2][0]/gts[2][1];
int isecs = (int) Math.floor(secs);
int nanos = (int) Math.round((secs - isecs)*1E9);
LocalDateTime dt = LocalDateTime.of(
Integer.parseInt(date_stamp[0]), // year
Integer.parseInt(date_stamp[1]), // month
Integer.parseInt(date_stamp[2]), // day
0,0,0);
dt = dt.plusSeconds(isecs);
dt = dt.plusNanos(nanos);
properties.setProperty ("GPSLatitude", ""+dlat);
properties.setProperty ("GPSLongitude", ""+dlon);
properties.setProperty ("GPSAltitude", ""+dalt);
properties.setProperty ("GPSDateTime", ""+dt.toString());
} else {
for (TIFFField stf: stfs) {
parseField(stf, properties);
}
}
} else { // will not parse long tags (>3)
if (tf.getCount() == 1) {
switch (tf.getType()) {
case TIFFTag.TIFF_RATIONAL:
{
long [] ndn = tf.getAsRational(0);
double v = 1.0*ndn[0]/ndn[1];
properties.setProperty(tf.getTag().getName(), ""+v);
}
break;
case TIFFTag.TIFF_SRATIONAL:
{
int [] ndn = tf.getAsSRational(0);
double v = 1.0*ndn[0]/ndn[1];
properties.setProperty(tf.getTag().getName(), ""+v);
}
break;
case TIFFTag.TIFF_ASCII:
case TIFFTag.TIFF_BYTE:
case TIFFTag.TIFF_DOUBLE:
case TIFFTag.TIFF_FLOAT:
case TIFFTag.TIFF_LONG:
case TIFFTag.TIFF_SHORT:
case TIFFTag.TIFF_SBYTE:
case TIFFTag.TIFF_SLONG:
case TIFFTag.TIFF_SSHORT:
properties.setProperty(tf.getTag().getName(), tf.getValueAsString(0));
break;
default:
System.out.println("not processed: "+tf.getTag().getName());
}
}
}
}
public static double [] getLLA(Properties properties) {
double [] lla = new double [3];
lla[0] = Double.parseDouble(properties.getProperty("GPSLatitude"));
lla[1] = Double.parseDouble(properties.getProperty("GPSLongitude"));
lla[2] = Double.parseDouble(properties.getProperty("GPSAltitude"));
return lla;
}
public static LocalDateTime getLocalDateTime(Properties properties) {
LocalDateTime dt = LocalDateTime.parse(properties.getProperty("GPSDateTime"));
return dt;
}
public static double [] getPixelSize(Properties properties) {
int res_unit = Integer.parseInt(properties.getProperty("ResolutionUnit"));
double unit_size = 0;
switch(res_unit) {
case 2: unit_size = 0.0254; break;
case 3: unit_size = 0.01; break;
default:
System.out.println("Wrong ResolutionUnit="+res_unit);
return null;
}
double [] xy_pixel_in_meters = new double[2];
xy_pixel_in_meters[0] = unit_size/Double.parseDouble(properties.getProperty("XResolution"));
xy_pixel_in_meters[1] = unit_size/Double.parseDouble(properties.getProperty("YResolution"));
return xy_pixel_in_meters;
}
public static double [] getXYOffsetMeters(Properties properties) {
int res_unit = Integer.parseInt(properties.getProperty("ResolutionUnit"));
double unit_size = 0;
switch(res_unit) {
case 2: unit_size = 0.0254; break;
case 3: unit_size = 0.01; break;
default:
System.out.println("Wrong ResolutionUnit="+res_unit);
return null;
}
double [] xy_offset_meters = new double[2];
xy_offset_meters[0] = unit_size * Double.parseDouble(properties.getProperty("XPosition"));
xy_offset_meters[1] = unit_size * Double.parseDouble(properties.getProperty("YPosition"));
return xy_offset_meters;
}
public static double [] getXYOffsetPixels(Properties properties) {
double [] xy_offset_pixels = new double[2];
xy_offset_pixels[0] = Double.parseDouble(properties.getProperty("XPosition")) * Double.parseDouble(properties.getProperty("XResolution"));
xy_offset_pixels[1] = Double.parseDouble(properties.getProperty("YPosition")) * Double.parseDouble(properties.getProperty("YResolution"));
return xy_offset_pixels;
}
}
......@@ -79,6 +79,7 @@ public class ElphelTiffWriter {
ImagePlus imp,
String path, // full path to save image
double [] lla, // latitude, longitude, altitude (or null)
double [] xy_center, // X,Y of top left to vertical (negative meters)
LocalDateTime dt, // local date/time or null
double pix_in_meters, // resolution or Double.NaN
boolean imageJTags, // later will use it to encode from properties
......@@ -149,7 +150,7 @@ public class ElphelTiffWriter {
ifd.appendChild(gpsRootNode);
}
addResolutionMetadata(ifd,pix_in_meters,cm_dig_after); // NOP if pix_in_meters is NaN
addXYPositionMetadata(ifd,xy_center,3);
if (debugLevel > 0) {
System.out.println("\n=== ifd ===:");DumpImageMetadata.displayMetadataNode(ifd, 1);
System.out.println("\n=== root_new ===:"); DumpImageMetadata.displayMetadataNode(root_new, 1);
......@@ -447,6 +448,42 @@ public class ElphelTiffWriter {
ifd.appendChild(node_y_resolution);
}
private static void addXYPositionMetadata(
IIOMetadataNode ifd,
double [] xy_position, // both should be negative
int digits_after) {
if (xy_position == null) {
return;
}
double xpos = Math.max(-xy_position[0] * 100, 0); // cm, prevent negative rationals, use 0 if negative
double ypos = Math.max(-xy_position[1] * 100, 0); // cm, prevent negative rationals, use 0 if negative
int denom = 1;
for (int i = 0; i < digits_after; i++) denom *= 10;
int ixpos = (int) Math.round(denom * xpos); // XPosition numerator
int iypos = (int) Math.round(denom * ypos); // YPosition numerator
IIOMetadataNode node_x_position = new IIOMetadataNode(TIFF_FIELD_TAG);
node_x_position.setAttribute("number", "286");
node_x_position.setAttribute("name", "XPosition");
IIOMetadataNode node_x_rationals = new IIOMetadataNode(TIFF_RATIONALS_TAG);
IIOMetadataNode node_x_rational = new IIOMetadataNode(TIFF_RATIONAL_TAG);
node_x_rational.setAttribute(TIFF_FIELD_VALUE_ATTRIBUTE, ixpos+"/"+denom);
node_x_rationals.appendChild(node_x_rational);
node_x_position.appendChild(node_x_rationals);
ifd.appendChild(node_x_position);
IIOMetadataNode node_y_position = new IIOMetadataNode(TIFF_FIELD_TAG);
node_y_position.setAttribute("number", "287");
node_y_position.setAttribute("name", "YPosition");
IIOMetadataNode node_y_rationals = new IIOMetadataNode(TIFF_RATIONALS_TAG);
IIOMetadataNode node_y_rational = new IIOMetadataNode(TIFF_RATIONAL_TAG);
node_y_rational.setAttribute(TIFF_FIELD_VALUE_ATTRIBUTE, iypos+"/"+denom);
node_y_rationals.appendChild(node_y_rational);
node_y_position.appendChild(node_y_rationals);
ifd.appendChild(node_y_position);
}
/*
*
FileImageOutputStream outputStream = new FileImageOutputStream(outputFile);
......
......@@ -318,6 +318,7 @@ the type of pixel data in this file getPixelType()
imp,
path,
lla, // double [] lla, // latitude, longitude, altitude (or null)
null, //double [] xy_center, // X,Y of top left to vertical (negative meters)
dt, // LocalDateTime dt, // local date/time or null
pix_in_meters, //double pix_in_meters, // resolution or Double.NaN
imageJTags,
......@@ -337,6 +338,7 @@ the type of pixel data in this file getPixelType()
imp,
path,
lla, // double [] lla, // latitude, longitude, altitude (or null)
null, //double [] xy_center, // X,Y of top left to vertical (negative meters)
dt, // LocalDateTime dt, // local date/time or null
pix_in_meters, //double pix_in_meters, // resolution or Double.NaN
imageJTags,
......@@ -371,6 +373,7 @@ the type of pixel data in this file getPixelType()
imp_rgb,
path,
lla, // double [] lla, // latitude, longitude, altitude (or null)
null, //double [] xy_center, // X,Y of top left to vertical (negative meters)
dt, // LocalDateTime dt, // local date/time or null
pix_in_meters, //double pix_in_meters, // resolution or Double.NaN
imageJTags,
......
......@@ -353,7 +353,7 @@ public class Interscene {
}
invertInitialOrientation(
int n_unresolved = invertInitialOrientation(
clt_parameters, // final CLTParameters clt_parameters,
batch_mode, // final boolean batch_mode,
readjust, // final boolean readjust,
......@@ -381,6 +381,12 @@ public class Interscene {
System.out.println("Egomotion table saved to "+ego_path);
}
}
if (n_unresolved != 0) {
earliest_scene2 = -1;
System.out.println("invertInitialOrientation(). Consider more graceful bail out.");
start_ref_pointers[0] = start_ref_pointers1[0];
return earliest_scene2; // cent_index;
}
String cent_ts = quadCLTs[cent_index].getImageName();
......@@ -442,7 +448,8 @@ public class Interscene {
final int earliest_index, // only used with readjust
final int debugLevel
) {
//Readjust may be needed similar to compensateDSI() - top DSI was calculated for wider scene
// range and be offset from the single-scene DSI
if (debugLevel > -3) {
System.out.println("\ninvertInitialOrientation(): earliest_index "+earliest_index+", ref_index="+
ref_index+", last_index="+last_index+". readjust="+readjust+"\n");
......@@ -700,6 +707,12 @@ public class Interscene {
avg_z, // double avg_z,
last_index, // ref_index, // int ref_index, // >= earliest_scene
earliest_index); // int earliest_scene)
if (getFPNUnResolved(fpn_pairs) > 0) {
System.out.println("Unresolved FPN pairs:"+getFPNUnResolved(fpn_pairs));
return getFPNUnResolved(fpn_pairs);
}
// mitigating problem, that in the process of adjusting offset can fall below
// the minimum and coordinates will be NaN:
/*
......@@ -788,10 +801,6 @@ public class Interscene {
sb.append("Maximal RMSE= "+maximal_series_rms+"\n");
sb.append("------------------------\n\n");
quadCLTs[ref_index].saveStringInModelDirectory(sb.toString(), QuadCLT.ORIENTATION_LOGS_SUFFIX); // String suffix)
}
return 0;
}
......@@ -1408,7 +1417,13 @@ public class Interscene {
return fpn_pairs;
}