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

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

parent 98e487e9
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -509,6 +509,8 @@ public class CLTParameters {
	public int        gmap_crop_extra =      20;
	public int        gmap_crop_extra =      20;
	public int []     gmap_tex_pals =        {0,1,2};
	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_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_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)
	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_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_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_alt",              this.gmap_save_alt+"");              // boolean 
		properties.setProperty(prefix+"gmap_save_tiff32",           this.gmap_save_tiff32+"");           // boolean 
		properties.setProperty(prefix+"gmap_save_tiff32",           this.gmap_save_tiff32+"");           // boolean 
		properties.setProperty(prefix+"gmap_save_tiff",             this.gmap_save_tiff+"");             // 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_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_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_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_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"));
   		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,
		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'");
				"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
		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).");
				"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
		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_crop_extra= (int) gd.getNextNumber();
		this.gmap_tex_pals =        CLTParameters.str_to_iarr(gd.getNextString());
		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_alt=         gd.getNextBoolean();
		this.gmap_save_tiff32=      gd.getNextBoolean();
		this.gmap_save_tiff32=      gd.getNextBoolean();
		this.gmap_save_tiff=        gd.getNextBoolean();
		this.gmap_save_tiff=        gd.getNextBoolean();
+160 −0
Original line number Original line Diff line number Diff line
@@ -112,6 +112,7 @@ import com.elphel.imagej.lwir.LwirReader;
import com.elphel.imagej.orthomosaic.ComboMatch;
import com.elphel.imagej.orthomosaic.ComboMatch;
import com.elphel.imagej.readers.ChangeImageResolution;
import com.elphel.imagej.readers.ChangeImageResolution;
import com.elphel.imagej.readers.DumpImageMetadata;
import com.elphel.imagej.readers.DumpImageMetadata;
import com.elphel.imagej.readers.ElphelTiffReader;
import com.elphel.imagej.readers.EyesisTiff;
import com.elphel.imagej.readers.EyesisTiff;
import com.elphel.imagej.tensorflow.TensorflowInferModel;
import com.elphel.imagej.tensorflow.TensorflowInferModel;
import com.elphel.imagej.tileprocessor.Clt1d;
import com.elphel.imagej.tileprocessor.Clt1d;
@@ -844,6 +845,8 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
			addButton("Show mice", panelLWIRWorld, color_process);
			addButton("Show mice", panelLWIRWorld, color_process);
			addButton("Set pair",  panelLWIRWorld, color_process);
			addButton("Set pair",  panelLWIRWorld, color_process);
			addButton("Warp 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);
			plugInFrame.add(panelLWIRWorld);
			
			
		}
		}
@@ -5683,8 +5686,165 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
			DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
			DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
			EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
			EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
			ComboMatch.testPair();
			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) {
	public boolean editIMU(boolean aux) {
+591 −14

File changed.

Preview size limit exceeded, changes collapsed.

+382 −0
Original line number Original line Diff line number Diff line
package com.elphel.imagej.orthomosaic;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;

import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.ims.Imx5;
import com.elphel.imagej.readers.ElphelTiffReader;
import com.elphel.imagej.tileprocessor.ImageDtt;

import Jama.Matrix;
import ij.ImagePlus;
import ij.Prefs;
import ij.gui.PointRoi;

public class ComboMap {
	public final String               name;  // timestamp
	public String                     path;        // full path to the model directory (including /vXX?)
	public double []                  lla;      // lat/long/alt
	public LocalDateTime              dt;
	private double [][]               affine = new double[][] {{1,0,0},{0,1,0}}; // relative to vert_meters[]
	public double                     orig_pix_meters;
	public double []                  vert_meters;   // offset of the image vertical in meters (scale-invariant)
	public FloatImageData             orig_image;
	public int                        orig_zoom_level;
	public boolean                    orig_zoom_valid;
	public double                     need_extra_zoom;
	HashMap <Integer, FloatImageData> images;

// Generate ALT image path from the GEO
	public static String getNameFromPath(String path) {
		int p1 = path.lastIndexOf(Prefs.getFileSeparator());
		if (p1 < 0) return null;
		int p2 = path.indexOf("-", p1+1);
		if (p2 < 0) return null;
		return path.substring(p1+1, p2);
	}
	
	public ComboMap (String path) {
		this.path = path;
		name = getNameFromPath(path);
		Properties imp_prop = null;
		try {
			imp_prop = ElphelTiffReader.getTiffMeta(path);				
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		lla = ElphelTiffReader.getLLA(imp_prop);
		dt = ElphelTiffReader.getLocalDateTime(imp_prop);
		vert_meters =     ElphelTiffReader.getXYOffsetMeters(imp_prop);
		orig_pix_meters = ElphelTiffReader.getPixelSize(imp_prop)[0];
		orig_zoom_level = FloatImageData.getZoomLevel(orig_pix_meters);
		orig_zoom_valid = FloatImageData.isZoomValid(orig_pix_meters);
		need_extra_zoom = FloatImageData.needZoomIn(orig_pix_meters);
		images = new HashMap <Integer, FloatImageData>();
	}
	
	public void setAffine(double [][] affine) {
		this.affine = affine;
	}
	public double [][] getAffine(){
		return affine;
	}
	public boolean readImageData() {
		ImagePlus imp = new ImagePlus(path);
		int width = imp.getWidth();
		int height = imp.getHeight();
		orig_image = new FloatImageData (
				width, // int       width,
				height, // int       height,
				orig_zoom_level, // int       zoom_lev,
				vert_meters, // double [] vert, // x,y pixel offset of the point under the camera
				(float[]) (imp.getProcessor().getPixels())); //    data);
		if (orig_zoom_valid) {
			images.put(orig_zoom_level, orig_image);
		}
		return true;
	}
	public ImagePlus getOriginalImage(boolean show_markers) {
		if (orig_image != null) {
			String full_name = path.substring(path.lastIndexOf(Prefs.getFileSeparator()) + 1);
			ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
					orig_image.data, // float[] pixels,
					orig_image.width,
					orig_image.height,
					full_name);
			if (show_markers) {
				PointRoi roi = new PointRoi();
				roi.addPoint(orig_image.vert[0],orig_image.vert[1]);
				roi.setOptions("label");
				imp.setRoi(roi);
			}
			return imp;
		}
		return null;
	}
	
	public double [] enuOffsetTo(ComboMap other) {
		return Imx5.enuFromLla(other.lla, lla);
	}
	
	public static double getPixelSizeMeters (int zoom_level ) {
		double ps = 0.01; // 1 cm;
		if (zoom_level >0) {
			for (int i = 0; i < zoom_level; i++) {
				ps /= 2;
			}
		} else {
			for (int i = 0; i > zoom_level; i++) {
				ps *= 2;
			}
		}
		return ps;
	}
	//	private double [][]               affine = new double[2][3];
	// vert_meters =     ElphelTiffReader.getXYOffsetMeters(imp_prop);
	public double [][] getBoundsMeters (boolean inverse){ // inverse - from source to rectified
		// orig_pix_meters
		double width_meters = orig_image.width * orig_pix_meters;
		double height_meters = orig_image.height * orig_pix_meters;
		double [][] corners = new double[][] { // CW from TL
			{               vert_meters[0],                 vert_meters[1]},
			{width_meters - vert_meters[0],                 vert_meters[1]},
			{width_meters - vert_meters[0], height_meters - vert_meters[1]},
			{               vert_meters[0], height_meters - vert_meters[1]}};
		double [][] aff_corners = new double [4][2];
		for (int n = 0; n < aff_corners.length; n++) {
			aff_corners[n][0] = affine[0][0]*corners[n][0] + affine[0][1]*corners[n][1] + affine[0][2]; 
			aff_corners[n][1] = affine[1][0]*corners[n][0] + affine[1][1]*corners[n][1] + affine[1][2]; 
		}
		double [][] bounds = new double [2][2]; // rows: x,y. Columns: min,max.
		for (int n = 0; n < 2; n++) {
			bounds[n][0] = aff_corners[0][0];
			bounds[n][1] = bounds[n][0];
			for (int i = 1; i < aff_corners.length; i++) {
				bounds[n][0]=Math.min(bounds[n][0], aff_corners[i][n]);
				bounds[n][1]=Math.max(bounds[n][1], aff_corners[i][n]);
			}
		}
		return bounds;
	}
	public static double [][] getBoundsMeters(ComboMap [] maps){ // maps[0] as a reference
		double [][] bounds = maps[0].getBoundsMeters(false);
		for (int nmap = 1; nmap < maps.length; nmap++) {
			double [][] bounds_other = maps[nmap].getBoundsMeters(false);
			double [] enuOffset = maps[0].enuOffsetTo(maps[nmap]);
			double [] rd = {enuOffset[0], -enuOffset[1]}; // {right,down} of the image 
			for (int n = 0; n < bounds.length; n++) {
				bounds[n][0] = Math.min(bounds[n][0],bounds_other[n][0]+ rd[n]);
				bounds[n][1] = Math.max(bounds[n][1],bounds_other[n][1]+ rd[n]);
			}
		}
		return bounds;
	}
	public static int [][] getBoundsPixels(
			ComboMap [] maps,
			int zoom_level){ // maps[0] as a reference
		double [][] bounds_meters = getBoundsMeters(maps);
		double pix_size = getPixelSizeMeters (zoom_level);
		int [][] bounds_pix = new int[2][2];
		for (int n = 0; n < bounds_pix.length; n++) {
			bounds_pix[n][0] = (int) Math.floor(bounds_meters[n][0]/pix_size);
			bounds_pix[n][1] = (int) Math.ceil (bounds_meters[n][1]/pix_size);
		}
		return bounds_pix;
	}

	public static double [][] invertAffine(double [][] affine){
		Matrix A = new Matrix (
				new double [][] {{affine[0][0],affine[0][1]},{affine[1][0],affine[1][1]}});
		Matrix Ai = A.inverse();
		Matrix B = new Matrix(new double [][] {{affine[0][2]},{affine[1][2]}});
		Matrix AiB = Ai.times(B);
		double [][] iaffine = {
				{Ai.get(0,0),Ai.get(0,1), -AiB.get(0,0)},
				{Ai.get(1,0),Ai.get(1,1), -AiB.get(1,0)}};
		return iaffine;
	}
	
	public void removeZoomLevel(int zoom_level) { // either to save memory or remove to later replace
		images.remove(zoom_level);
	}
	public boolean downScaleForGPU (int zoom_level){
		if (orig_image == null) {
			System.out.println("Original image is null");
			return false;
		}
		if (!orig_zoom_valid) {
			System.out.println("Original zoom level is invalid, need_extra_zoom = "+need_extra_zoom);
			return false;
		}
		if (zoom_level > orig_zoom_level) {
			System.out.println("Requested zoom level is too high ("+zoom_level+" > "+orig_zoom_level+")");
			return false;
		}
		if (images.get(zoom_level) != null) {
			return true; // already exists
		}
		int rscale = 1;
		for (int i = orig_zoom_level; i > zoom_level; i--) {
			rscale *= 2;
		}
		final int frscale = rscale;
		int swidth =  orig_image.width;
		int sheight = orig_image.height;
		final float [] spix = orig_image.data;
		final int width = (swidth+frscale-1)/frscale;
		final int height = (sheight+frscale-1)/frscale;
		final int tiles = width * height;
		final float [] opix = new float [tiles];
		Arrays.fill(opix, Float.NaN);
		final double [][] wnd = new double [frscale] [frscale];
		for (int i = 0; i <frscale; i++) {
			for (int j = 0; j <frscale; j++) {
				wnd[i][j] = Math.sin((i+0.5)/frscale*Math.PI);
			}
		}
		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 tile = ai.getAndIncrement(); tile < tiles; tile = ai.getAndIncrement()) {
                    	int tileX = tile%width;
                    	int tileY = tile/width;
                    	int tileW= (frscale*(tileX+1) <= swidth) ? frscale:(swidth - frscale*tileX);  
                    	int tileH= (frscale*(tileY+1) <= sheight) ? frscale:(sheight - frscale*tileY);
                    	double sw = 0.0, swd = 0.0;
                    	for (int py = 0; py < tileH; py++) {
                    		int ls = (tileY*frscale + py)*swidth;
                    		for (int px = 0; px < tileW; px++) {
                    			double d = spix[ls + tileX*frscale+px];
                    			if (!Double.isNaN(d)) {
                    				double w = wnd[py][px];
                    				sw += w;
                    				swd += w*d;
                    			}
                    			if (sw > 0) {
                    				opix[tileY * width + tileX] = (float) (swd/sw);
                    			}
                    		}
                    	}
                    }
                }
            };
        }		      
        ImageDtt.startAndJoin(threads);
        images.put(zoom_level, new FloatImageData (
				width, // int       width,
				height, // int       height,
				zoom_level, // int       zoom_lev,
				vert_meters, // double [] vert, // x,y pixel offset of the point under the camera
				opix)); //    data);
		return true;
	}
	
	/**
	 * Copy prepared scaled image to the top-left corner of the fixed-size
	 * float[] array for the GPU input
	 * @param zoom_level
	 * @param gpu_width
	 * @param gpu_height
	 * @return
	 */
	public float [] getPaddedGPU (
			int zoom_level,
			int gpu_width,
			int gpu_height){
		boolean got_image = downScaleForGPU (zoom_level); // will create if does not exist
		if (!got_image) {
			System.out.println("getPaddedGPU(): failed to prepare a scaled image");
			return null;
		}
		final float [] padded_gpu = new float[gpu_width*gpu_height];
		final int swidth =  orig_image.width;
		final int sheight = orig_image.height;
		final float [] spix = orig_image.data;
		Arrays.fill(padded_gpu, Float.NaN);
		final int cheight = Math.min(sheight,gpu_height);
		final int cwidth =  Math.min(swidth, gpu_width);

		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 row = ai.getAndIncrement(); row < cheight; row = ai.getAndIncrement()) {
        				System.arraycopy(
        						spix,
        						row*swidth,
        						padded_gpu,
        						row*gpu_width,
        						cwidth);
                    }
                }
            };
        }		      
        ImageDtt.startAndJoin(threads);
		return padded_gpu;
	}
	
	
	public static float [][] renderMulti (
			ComboMap [] maps,
			int zoom_level){ // maps[0] as a reference
		
		int [][] bounds = getBoundsPixels(
				maps,
				zoom_level);
		int width =  bounds[0][1] - bounds[0][0]; // bounds[x][0] - negative 
		int height = bounds[1][1] - bounds[1][0]; 
		final float [][] fpixels = new float [maps.length][width * height];
		for (int nmap = 0; nmap< maps.length; nmap++) {
			final int fnmap = nmap;
			Arrays.fill(fpixels[nmap], Float.NaN);
			final double scale = getPixelSizeMeters(maps[nmap].orig_zoom_level)/getPixelSizeMeters(zoom_level);
			double [][] inv_bounds = maps[nmap].getBoundsMeters(true);
			double [] enu_offset = maps[0].enuOffsetTo(maps[nmap]);
			final double [] scaled_out_center = { // xy center to apply affine to
					-bounds[0][0]+scale * enu_offset[0],
					-bounds[1][0]+scale * enu_offset[1]};
			final int [][] ibounds = new int [2][2];
			for (int n = 0; n< 2; n++) {
				ibounds[n][0] = (int) Math.floor(-bounds[n][0] + scale*(inv_bounds[n][0] + enu_offset[n]));
				ibounds[n][1] = (int) Math.ceil (-bounds[n][0] + scale*(inv_bounds[n][0] + enu_offset[n]));
			}
			final int local_width =  ibounds[0][1] - ibounds[0][0];
			final int local_height = ibounds[1][1] - ibounds[1][0];
			final int local_len = local_width * local_height; 
			double [][] src_bounds=maps[nmap].getBoundsMeters (false);
			final double [] src_center = {-src_bounds[0][0],-src_bounds[1][0]}; // x,y center offset in the source image
			final double [][] affine = maps[nmap].affine;
			final int src_width = maps[nmap].orig_image.width;
			final int src_height = maps[nmap].orig_image.height;
			final float [] src_img = maps[nmap].orig_image.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 nPix = ai.getAndIncrement(); nPix < local_len; nPix = ai.getAndIncrement()) {
							int opX = nPix % local_width + ibounds[0][0]; // absolute output pX, pY
							int opY = nPix / local_width + ibounds[1][0];
							double dX = (opX - scaled_out_center[0]) /scale; // in original image scale 
							double dY = (opY - scaled_out_center[1]) /scale;
							double [] xy_src = {
									affine[0][0]*dX+affine[0][1]*dY+affine[0][2]+src_center[0],
									affine[1][0]*dX+affine[1][1]*dY+affine[1][2]+src_center[1]};
							// limit to the source image
							if      (xy_src[0] < 0)               xy_src[0] = 0;
							else if (xy_src[0] >= (src_width-1))  xy_src[0] = src_width-2; // to be on the safe side
							if      (xy_src[1] < 0)               xy_src[1] = 0;
							else if (xy_src[1] >= (src_height-1)) xy_src[1] = src_height-2;
							int [] ixy_src = {(int) Math.floor(xy_src[0]), (int)Math.floor(xy_src[1]) };
							double [] kxy = {xy_src[0]-ixy_src[0], xy_src[1]-ixy_src[1]}; 
							double d00 = src_img[ixy_src[0] + ixy_src[1]*src_width];
							if (!Double.isNaN(d00)) {
								double d01 = src_img[ixy_src[0] + 1 + ixy_src[1]*src_width];
								double d10 = src_img[ixy_src[0] + (ixy_src[1] + 1) *src_width];
								double d11 = src_img[ixy_src[0] + 1 + (ixy_src[1] + 1) *src_width];
								double d = d00*(1.0 - kxy[0])*(1.0 - kxy[1])+
										   d01*       kxy[0] *(1.0 - kxy[1])+
										   d10*(1.0 - kxy[0])*       kxy[1]+
										   d11*       kxy[0] *       kxy[1];
								fpixels[fnmap][opX + opY*width] = (float) d;
							}
						}
					}
				};
			}		      
			ImageDtt.startAndJoin(threads);
		}
		return fpixels;
	}
	
}
+579 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading