Commit ff164bbf authored by Andrey Filippov's avatar Andrey Filippov
Browse files

More on output of geolocated TIFFs with transparency

parent 9b0ad10d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -486,6 +486,9 @@ public class CLTParameters {
	public int        gmap_crop_extra =      20;
	public int []     gmap_tex_pals =        {0,1,2};
	public boolean    gmap_save_alt =        true;  // save height map (meters ASL)  
	public boolean    gmap_save_tiff =       true;  // save transparent TIFF with geo metadata (top left corner)
	public int        gmap_tiff_pal =        0;     // LWIR palette for TIFF  
	
	
	public boolean    generate_bg =      true;  // Generate background image for 3dmodels
+12 −2
Original line number Diff line number Diff line
@@ -257,5 +257,15 @@ public class Imx5 {
		return ned;
	}

	
	/*
	 * Offset Latitude, Longitude, Altitude by North, East, Up (in meters) 
	 */
	public static double [] offsetLla(double [] lla, double [] ned) {
		double [] offset_lla = new double [] {
				lla[0] + (ned[0]/EARTH_RADIUS / Math.PI * 180 / Math.cos(lla[0])), // degrees
				lla[1] + (ned[1]/EARTH_RADIUS / Math.PI * 180), // degrees
				lla[2] - ned[2]
		};
		return offset_lla;
	}
}
+2 −3
Original line number Diff line number Diff line
@@ -78,9 +78,8 @@ public class ElphelTiffWriter {
			int           debugLevel
			) {
	    File outputFile = new File(path);
	    if (debugLevel > 0) {
	    	System.out.println("saveTiffARGB32(): will write to "+outputFile);
	    	System.out.println("ElphelTiffWriter.saveTiffARGB32");
	    if (debugLevel > -3) {
	    	System.out.println("ElphelTiffWriter.saveTiffARGB32(): will write to "+outputFile);
	    }
	    ImageWriter tiffWriter = ImageIO.getImageWritersByFormatName("tiff").next();
	    ImageWriteParam tiffWriteParam = tiffWriter.getDefaultWriteParam();
+93 −4
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -72,6 +73,7 @@ import com.elphel.imagej.ims.Did_ins_2;
import com.elphel.imagej.ims.Did_pimu;
import com.elphel.imagej.ims.EventLogger;
import com.elphel.imagej.ims.Imx5;
import com.elphel.imagej.readers.ElphelTiffWriter;
import com.elphel.imagej.readers.ImagejJp4Tiff;
import com.elphel.imagej.x3d.export.TriMesh;
import com.elphel.imagej.x3d.export.WavefrontExport;
@@ -227,6 +229,13 @@ public class QuadCLTCPU {
		return dxyzatyr;
	}
	public double [] getLla() {
		return did_ins_2.lla;
	}
	
	public LocalDateTime getLocalDateTime() {
		return did_ins_2.getLocalDateTime();
	}
	public static double [][] scaleDtToErs(
			CLTParameters clt_parameters,
			double [][] cam_dxyzatr){
@@ -413,7 +422,7 @@ public class QuadCLTCPU {
    		double        discard_rdisp,  // discard above/below this fraction of average height
    		double        pix_size,       // in meters
    		int           max_image_width,// increase pixel size as a power of 2 until image fits
    		double []     x0y0,        // initialize to double[2] to return width, height
    		double []     x0y0,           // top level offset in meters
    		int []        whs,            // initialize to int[3] to return {width, height, scale reduction}
    		int debug_level
    		) {
@@ -745,7 +754,7 @@ public class QuadCLTCPU {
    			max_disparity,            // double    max_disparity,
    			discard_low,              // double    discard_low,    // fraction of all pixels
    			discard_high,             // double    discard_high,   // fraction of all pixels
    			xy_range,                 // double [][] xy_range,     // should be double[2][];
    			xy_range,                 // double [][] xy_range,     // should be double[2][]; meters
    			debug_level);             // int debug_level)
    	// camera position and orientation relative to the same lat/long on the ground below it 
//    	double [][] scene_abs_xyzatr_enu = new double [][] {new double[] {0,0,-agl},	scene_abs_atr_enu};
@@ -3247,6 +3256,25 @@ public class QuadCLTCPU {
		return imp;
	}
	public ImagePlus saveDoubleArrayInTopModelDirectory(
			String      suffix,
			String []   labels, // or null
			double [][] data,
			int         width,
			int         height)
	{
		String x3d_path = getX3dTopDirectory();
		String file_name = image_name + suffix;
		String file_path = x3d_path + Prefs.getFileSeparator() + file_name + ".tiff";
		ImageStack imageStack = ShowDoubleFloatArrays.makeStack(data, width, height, labels);
		ImagePlus imp = new ImagePlus( file_name, imageStack);
		FileSaver fs=new FileSaver(imp);
		fs.saveAsTiff(file_path);
		System.out.println("saveDoubleArrayInModelDirectory(): saved "+file_path);
		return imp;
	}
	
	
	public ImagePlus saveDoubleArrayInModelDirectory(
			String      suffix,
			double []   data,
@@ -16299,6 +16327,7 @@ public class QuadCLTCPU {
				  suffix,
				  debugLevel);
	  }
	  
	  public boolean writeLwirPreview(
			  final CLTParameters  clt_parameters,
			  double []            data,
@@ -16315,7 +16344,6 @@ public class QuadCLTCPU {
		  for (int i = 0; i < rendered_texture[0].length; i++) {
			  rendered_texture[1][i] = Double.isNaN(rendered_texture[0][i])? 0.0: 1.0;
		  }
//		  double [] minmax = scene.getColdHot(); // used in linearStackToColor (from this current scene)
		  if (!suffix.equals("")) {
			  if (minmax == null) { // to replace standard preview file name
				  minmax = scene.getColdHot(); // used in linearStackToColor (from this current scene)
@@ -16324,7 +16352,6 @@ public class QuadCLTCPU {
				  suffix +="-RANGE"+(minmax[1]-minmax[0]);
			  }
		  }
//		  int width = getTileProcessor().getTilesX() *getTileProcessor().getTileSize(); 
		  int height = data.length/width;
		  String set_name = getImageName();
		  if (set_name == null ) {
@@ -16367,6 +16394,68 @@ public class QuadCLTCPU {
		  return true;
	  }
	 
	  public boolean writeLwirGeoTiffARGB(
			  final CLTParameters  clt_parameters,
			  double []            data,
			  double []            lla,  // latitude, longitude, altitude (or null)
			  LocalDateTime        dt,   // local date/time or null
			  double               pix_in_meters,
			  int                  width,
			  double []            minmax, // null for auto
			  QuadCLT              scene,
			  int                  tex_palette,
			  String               suffix, // include "-geo"
			  int                  debugLevel) {
		  if (scene == null) {
			  scene = (QuadCLT) this;
		  }
		  double [][] rendered_texture = new double[][] {data, new double[data.length]};
		  for (int i = 0; i < rendered_texture[0].length; i++) {
			  rendered_texture[1][i] = Double.isNaN(rendered_texture[0][i])? 0.0: 1.0;
		  }
		  if (!suffix.equals("")) {
			  if (minmax == null) { // to replace standard preview file name
				  minmax = scene.getColdHot(); // used in linearStackToColor (from this current scene)
				  suffix +="-AUTORANGE";
			  } else {
				  suffix +="-RANGE"+(minmax[1]-minmax[0]);
			  }
		  }
		  int height = data.length/width;
		  String set_name = getImageName();
		  if (set_name == null ) {
			  QuadCLTCPU.SetChannels [] set_channels = setChannels(debugLevel);
			  set_name = set_channels[0].set_name;
		  }
		  String model_dir= correctionsParameters.selectX3dDirectory(
				  set_name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
				  null,
				  true,  // smart,
				  true);  //newAllowed, // save\
		  String title = getImageName()+suffix;
		  ImagePlus imp =  	  QuadCLTCPU.linearStackToColorLWIR(
				  clt_parameters, // CLTParameters  clt_parameters,
				  tex_palette, // int            lwir_palette, // <0 - do not convert
				  minmax, // double []      minmax,
				  title, // String         name,
				  "", // String         suffix, // such as disparity=...
				  true, // boolean        toRGB,
				  rendered_texture, // faded_textures[nslice], // double [][]    texture_data,
				  width, // int            width, // int tilesX,
				  height, // int            height, // int tilesY,
				  debugLevel); // int            debugLevel )
		  String image_path = model_dir +  Prefs.getFileSeparator() + title+".tiff";
		  ElphelTiffWriter.saveTiffARGB32(
				  imp,
				  image_path,
				  lla,           // double []     lla,  // latitude, longitude, altitude (or null)
				  dt,            // LocalDateTime dt,   // local date/time or null
				  pix_in_meters, //double        pix_in_meters, // resolution or Double.NaN
				  false,         // imageJTags,
				  debugLevel);
		  return true;
	  }
	  
	  
	/** broke  
	  public boolean writeRatingFile( // USED in lwir
+101 −28
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ package com.elphel.imagej.tileprocessor;
//import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -39,6 +40,7 @@ import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.correction.EyesisCorrections;
import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.ims.Imx5;
import com.elphel.imagej.x3d.export.GlTfExport;
import com.elphel.imagej.x3d.export.Render3D;
import com.elphel.imagej.x3d.export.TriMesh;
@@ -2468,6 +2470,10 @@ public class TexturedModel {
		final boolean   crop_empty =      clt_parameters.gmap_crop_empty ; //true;
		final int       crop_extra =      clt_parameters.gmap_crop_extra ; //20;
		final int []    tex_pals =        clt_parameters.gmap_tex_pals ; //{0,1,2};
		final boolean   gmap_save_alt =   clt_parameters.gmap_save_alt;  // true;  // save height map (meters ASL)  
		final boolean   gmap_save_tiff =  clt_parameters.gmap_save_tiff; // true;  // save transparent TIFF with geo metadata (top left corner)
		final int       gmap_tiff_pal =   clt_parameters.gmap_tiff_pal;  // 0;     // LWIR palette for TIFF  
		
		
		final double  range_disparity_offset = clt_parameters.imp.range_disparity_offset;// double  range_disparity_offset
		final boolean batch_mode =        clt_parameters.multiseq_run; // batch_run;
@@ -3046,15 +3052,15 @@ public class TexturedModel {
							hdr_whs[0],            // int          out_width,    // output rendered image width in pixels
							hdr_whs[1]);           // int          out_height);   // output rendered image height in pixels
					boolean last_is_alpha = true; // last channel in textures slices is alpha
					double [][] full_render;
					double [][] full_render_z;
					if (use_parallel_proj) {
						full_render =render3D.render3dPlaneParallelProj(
						full_render_z =render3D.render3dPlaneParallelProj(
								tri_meshes,            // final ArrayList<TriMesh> tri_meshes,
								last_is_alpha,         // final boolean            last_is_alpha,
								//							scenes[ref_index],     //final QuadCLT            ref_scene,    // all coordinates relative to this scene
								debugLevel);           //int                      debugLevel)
					} else {
						full_render =render3D.render3dPlaneCenterProj(
						full_render_z =render3D.render3dPlaneCenterProj(
								tri_meshes,            // final ArrayList<TriMesh> tri_meshes,
								last_is_alpha,         // final boolean            last_is_alpha,
								//						scenes[ref_index],     //final QuadCLT            ref_scene,    // all coordinates relative to this scene
@@ -3069,33 +3075,100 @@ public class TexturedModel {
					scenes[ref_index].saveDoubleArrayInModelDirectory(
							suffix+"-FULL", // String      suffix,
							null, // String []   labels, // or null
							full_render, // double [][] data,
							full_render_z, // double [][] data, // including Z as it was
							hdr_whs[0], // int            width, // int tilesX,
							hdr_whs[1]); // int            height, // int tilesY,
					double [][] img_cropped_z = full_render_z;
//					int []  wh = hdr_whs.clone();
					if (crop_empty || (crop_extra > 0)) {
						int []  wh = new int[2];
						double [][] img_cropped = Render3D.cropRectified(
						int []  ltwh = new int[4];
						img_cropped_z = Render3D.cropRectified(
								crop_empty,    // boolean crop_empty,
								last_is_alpha, // boolean last_is_alpha,
//								last_is_alpha, // boolean last_is_alpha,
								full_render_z.length - 2, // last is Z, previous is alpha
								crop_extra,    // int     crop_extra,
								hdr_whs[0],    // int     width,
								wh,            // int []  wh, // should be initialized to int [2]
								full_render);  // double [][] img_src) 
						if (img_cropped != null) { // has NaN and alpha 0-1
							scenes[ref_index].saveDoubleArrayInModelDirectory(
								ltwh,            // int []  wh, // should be initialized to int [2]
								full_render_z);  // double [][] img_src)
						if (img_cropped_z != null) { // has NaN and alpha 0-1
							hdr_whs[0] = ltwh[2]; // cropped width
							hdr_whs[1] = ltwh[3]; // cropped height
							hdr_x0y0[0] +=ltwh[0]* scaled_pixel_size; // meters corrected by pixels
							hdr_x0y0[1] +=ltwh[1]* scaled_pixel_size; // meters corrected by pixels
							scenes[ref_index].saveDoubleArrayInModelDirectory( // save with Z
									suffix+"-CROP", // String      suffix,
									null,           // String []   labels, // or null
									img_cropped,    // double [][] data,
									wh[0],          // int            width, // int tilesX,
									wh[1]);         // int            height, // int tilesY,
							//				for (int tex_palette = tex_palette_start; tex_palette <= tex_palette_end; tex_palette++) {
									img_cropped_z,    // double [][] data,
									hdr_whs[0], // int            width, // int tilesX,
									hdr_whs[1]); // int            height, // int tilesY,
						} else {
							img_cropped_z = full_render_z; // restore
						}
					}
					// Here use cropped or full (non-cropped) if not calculated and save separately
					// textures and altitude ASL
					if (img_cropped_z != null) { // has NaN and alpha 0-1
						double [][] img_cropped = new double [img_cropped_z.length - 1][];
						for (int i = 0; i < img_cropped.length; i++) {
							img_cropped[i] = img_cropped_z[i];
						}
						double [][] cropped_z = new double [][] {img_cropped_z[img_cropped_z.length-1].clone(), img_cropped_z[img_cropped_z.length-2]};
						// scale units, add altitude, add NaNs
						double [] ref_lla = scenes[ref_index].getLla();
						if (ref_lla == null) {
							ref_lla = new double[3];
						}
						// correct GPS coordinates to top-left corner of the result (full) image
						double [] top_left_lla_offset_ned = new double[] {
							hdr_x0y0[1], // North // hdr_x0y0 - in meters !
							hdr_x0y0[0], // East
							0}; // no altitude offset here
						double [] top_left_lla = Imx5.offsetLla(ref_lla,top_left_lla_offset_ned);
						int num_pix = 0;
						double sum_z = 0.0;
						for (int i = 0; i < cropped_z[0].length; i++) {
							if (cropped_z[1][i] <= 0.0) {
								cropped_z[0][i] = Double.NaN;
							} else {
								cropped_z[0][i] = ref_lla[2] - cropped_z[0][i] * scaled_pixel_size;
								num_pix++;
								sum_z += cropped_z[0][i]; 
							}
						}
						double avg_z = sum_z/num_pix;
						top_left_lla[2] = avg_z; // average altitude. Maybe keep drone altitude?
						if (gmap_save_alt) {
							scenes[ref_index].saveDoubleArrayInTopModelDirectory( // save with Z
									suffix+"-ALT", // String      suffix,
									null,          // String []   labels, // or null
									new double[][] {cropped_z[0]},    // double [][] data,
									hdr_whs[0],    // int            width, // int tilesX,
									hdr_whs[1]);   // int            height, // int tilesY,
						}
						double [] minmax =  tex_um_fixed ? (new double[] {-tex_um_range/2, tex_um_range/2}): null;				
						if (gmap_save_tiff && (gmap_tiff_pal >=0)) {
							LocalDateTime dt = scenes[ref_index].getLocalDateTime(); 
							scenes[ref_index].writeLwirGeoTiffARGB(
									clt_parameters,                     // final CLTParameters  clt_parameters,
									img_cropped[0],                     // double []            data,
									top_left_lla,                       // double []            lla,  // latitude, longitude, altitude (or null)
									dt,                                 // LocalDateTime        dt,   // local date/time or null
									scaled_pixel_size,                  // double               pix_in_meters,
									hdr_whs[0],                         // int     width,
									minmax,                             // double []            minmax, // null for auto
									null,                               // QuadCLT              scene,
									gmap_tiff_pal,                      // int                  tex_palette,
									suffix+"-GEO"+"-PAL"+gmap_tiff_pal, // String               suffix,
									debugLevel);                        // int                  debugLevel)
						}
						
						for (int tex_palette: tex_pals) {
							// try with fixed range?
								double [] minmax =  tex_um_fixed ? (new double[] {-tex_um_range/2, tex_um_range/2}): null;				
//							double [] minmax =  tex_um_fixed ? (new double[] {-tex_um_range/2, tex_um_range/2}): null;				
							scenes[ref_index].writeLwirPreview(
									clt_parameters, // final CLTParameters  clt_parameters,
									img_cropped[0], // double []            data,
										wh[0],          // int            width, // int tilesX,
									hdr_whs[0],    // int     width,
									minmax, // 			  double []            minmax, // null for auto
									null, // QuadCLT              scene,
									tex_palette, // int                  tex_palette,
@@ -3103,7 +3176,7 @@ public class TexturedModel {
									debugLevel); // int                  debugLevel)
						}
					}
					}

				}
			}
		}
Loading