Loading src/main/java/com/elphel/imagej/cameras/CLTParameters.java +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading src/main/java/com/elphel/imagej/ims/Imx5.java +12 −2 Original line number Diff line number Diff line Loading @@ -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; } } src/main/java/com/elphel/imagej/readers/ElphelTiffWriter.java +2 −3 Original line number Diff line number Diff line Loading @@ -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(); Loading src/main/java/com/elphel/imagej/tileprocessor/QuadCLTCPU.java +93 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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){ Loading Loading @@ -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 ) { Loading Loading @@ -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}; Loading Loading @@ -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, Loading Loading @@ -16299,6 +16327,7 @@ public class QuadCLTCPU { suffix, debugLevel); } public boolean writeLwirPreview( final CLTParameters clt_parameters, double [] data, Loading @@ -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) Loading @@ -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 ) { Loading Loading @@ -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 src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +101 −28 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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, Loading @@ -3103,7 +3176,7 @@ public class TexturedModel { debugLevel); // int debugLevel) } } } } } } Loading Loading
src/main/java/com/elphel/imagej/cameras/CLTParameters.java +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
src/main/java/com/elphel/imagej/ims/Imx5.java +12 −2 Original line number Diff line number Diff line Loading @@ -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; } }
src/main/java/com/elphel/imagej/readers/ElphelTiffWriter.java +2 −3 Original line number Diff line number Diff line Loading @@ -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(); Loading
src/main/java/com/elphel/imagej/tileprocessor/QuadCLTCPU.java +93 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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){ Loading Loading @@ -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 ) { Loading Loading @@ -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}; Loading Loading @@ -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, Loading Loading @@ -16299,6 +16327,7 @@ public class QuadCLTCPU { suffix, debugLevel); } public boolean writeLwirPreview( final CLTParameters clt_parameters, double [] data, Loading @@ -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) Loading @@ -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 ) { Loading Loading @@ -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
src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java +101 −28 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -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, Loading @@ -3103,7 +3176,7 @@ public class TexturedModel { debugLevel); // int debugLevel) } } } } } } Loading