Commit 2e50bfb7 authored by Andrey Filippov's avatar Andrey Filippov

converting kernels

parent 4ca23a78
...@@ -106,6 +106,10 @@ public class EyesisCorrectionParameters { ...@@ -106,6 +106,10 @@ public class EyesisCorrectionParameters {
public double referenceExposure=0.0003; // 3/10000 sec, used in absolute mode only public double referenceExposure=0.0003; // 3/10000 sec, used in absolute mode only
public double relativeExposure=0.5; // 0.0 - use shortest (darken), 1.0 - use longest (brighten) public double relativeExposure=0.5; // 0.0 - use shortest (darken), 1.0 - use longest (brighten)
public String cltKernelDirectory="";
public String cltKernelPrefix="clt-";
public String cltSuffix=".clt-tiff";
public void setProperties(String prefix,Properties properties){ public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"split",this.split+""); properties.setProperty(prefix+"split",this.split+"");
...@@ -188,6 +192,10 @@ public class EyesisCorrectionParameters { ...@@ -188,6 +192,10 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"relativeExposure", this.relativeExposure+""); properties.setProperty(prefix+"relativeExposure", this.relativeExposure+"");
properties.setProperty(prefix+"swapSubchannels01", this.swapSubchannels01+""); properties.setProperty(prefix+"swapSubchannels01", this.swapSubchannels01+"");
properties.setProperty(prefix+"cltKernelDirectory", this.cltKernelDirectory);
properties.setProperty(prefix+"cltKernelPrefix", this.cltKernelPrefix);
properties.setProperty(prefix+"cltSuffix", this.cltSuffix);
} }
public void getProperties(String prefix,Properties properties){ public void getProperties(String prefix,Properties properties){
...@@ -273,6 +281,12 @@ public class EyesisCorrectionParameters { ...@@ -273,6 +281,12 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"referenceExposure") !=null) this.referenceExposure= Double.parseDouble(properties.getProperty(prefix+"referenceExposure")); if (properties.getProperty(prefix+"referenceExposure") !=null) this.referenceExposure= Double.parseDouble(properties.getProperty(prefix+"referenceExposure"));
if (properties.getProperty(prefix+"relativeExposure") !=null) this.relativeExposure= Double.parseDouble(properties.getProperty(prefix+"relativeExposure")); if (properties.getProperty(prefix+"relativeExposure") !=null) this.relativeExposure= Double.parseDouble(properties.getProperty(prefix+"relativeExposure"));
if (properties.getProperty(prefix+"swapSubchannels01")!=null) this.swapSubchannels01=Boolean.parseBoolean(properties.getProperty(prefix+"swapSubchannels01")); if (properties.getProperty(prefix+"swapSubchannels01")!=null) this.swapSubchannels01=Boolean.parseBoolean(properties.getProperty(prefix+"swapSubchannels01"));
if (properties.getProperty(prefix+"cltKernelDirectory")!= null) this.cltKernelDirectory=properties.getProperty(prefix+"cltKernelDirectory");
if (properties.getProperty(prefix+"cltKernelPrefix")!= null) this.cltKernelPrefix=properties.getProperty(prefix+"cltKernelPrefix");
if (properties.getProperty(prefix+"cltSuffix")!= null) this.cltSuffix=properties.getProperty(prefix+"cltSuffix");
} }
public boolean showDialog(String title) { public boolean showDialog(String title) {
...@@ -338,6 +352,9 @@ public class EyesisCorrectionParameters { ...@@ -338,6 +352,9 @@ public class EyesisCorrectionParameters {
gd.addStringField ("Aberration kernels for DCT directory", this.dctKernelDirectory, 60); gd.addStringField ("Aberration kernels for DCT directory", this.dctKernelDirectory, 60);
gd.addCheckbox ("Select aberration kernels for DCT directory", false); gd.addCheckbox ("Select aberration kernels for DCT directory", false);
gd.addStringField ("Aberration kernels for CLT directory", this.cltKernelDirectory, 60);
gd.addCheckbox ("Select aberration kernels for CLT directory", false);
gd.addStringField("Equirectangular maps directory (may be empty)", this.equirectangularDirectory, 60); gd.addStringField("Equirectangular maps directory (may be empty)", this.equirectangularDirectory, 60);
gd.addCheckbox("Select equirectangular maps directory", false); gd.addCheckbox("Select equirectangular maps directory", false);
gd.addStringField("Results directory", this.resultsDirectory, 40); gd.addStringField("Results directory", this.resultsDirectory, 40);
...@@ -356,6 +373,8 @@ public class EyesisCorrectionParameters { ...@@ -356,6 +373,8 @@ public class EyesisCorrectionParameters {
gd.addStringField("DCT kernel files prefix", this.dctKernelPrefix, 40); gd.addStringField("DCT kernel files prefix", this.dctKernelPrefix, 40);
gd.addStringField("DCT symmetical kernel files", this.dctSymSuffix, 40); gd.addStringField("DCT symmetical kernel files", this.dctSymSuffix, 40);
gd.addStringField("DCT asymmetrical kernel files suffix", this.dctAsymSuffix, 40); gd.addStringField("DCT asymmetrical kernel files suffix", this.dctAsymSuffix, 40);
gd.addStringField("CLT kernel files prefix", this.cltKernelPrefix, 40);
gd.addStringField("CLT symmetical kernel files", this.cltSuffix, 40);
gd.addStringField("Equirectangular maps prefix", this.equirectangularPrefix, 40); gd.addStringField("Equirectangular maps prefix", this.equirectangularPrefix, 40);
gd.addStringField("Equirectangular maps suffix", this.equirectangularSuffix, 40); gd.addStringField("Equirectangular maps suffix", this.equirectangularSuffix, 40);
...@@ -417,6 +436,7 @@ public class EyesisCorrectionParameters { ...@@ -417,6 +436,7 @@ public class EyesisCorrectionParameters {
this.sharpKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectSharpKernelDirectory(false, false); this.sharpKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectSharpKernelDirectory(false, false);
this.smoothKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectSmoothKernelDirectory(false, true); this.smoothKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectSmoothKernelDirectory(false, true);
this.dctKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectDCTKernelDirectory(false, true); this.dctKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectDCTKernelDirectory(false, true);
this.cltKernelDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectCLTKernelDirectory(false, true);
this.equirectangularDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectEquirectangularDirectory(false, false); this.equirectangularDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectEquirectangularDirectory(false, false);
this.resultsDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectResultsDirectory(false, true); this.resultsDirectory= gd.getNextString(); if (gd.getNextBoolean()) selectResultsDirectory(false, true);
this.sourcePrefix= gd.getNextString(); this.sourcePrefix= gd.getNextString();
...@@ -431,6 +451,8 @@ public class EyesisCorrectionParameters { ...@@ -431,6 +451,8 @@ public class EyesisCorrectionParameters {
this.dctKernelPrefix= gd.getNextString(); this.dctKernelPrefix= gd.getNextString();
this.dctSymSuffix= gd.getNextString(); this.dctSymSuffix= gd.getNextString();
this.dctAsymSuffix= gd.getNextString(); this.dctAsymSuffix= gd.getNextString();
this.cltKernelPrefix= gd.getNextString();
this.cltSuffix= gd.getNextString();
this.equirectangularPrefix= gd.getNextString(); this.equirectangularPrefix= gd.getNextString();
this.equirectangularSuffix= gd.getNextString(); this.equirectangularSuffix= gd.getNextString();
this.equirectangularCut= gd.getNextBoolean(); this.equirectangularCut= gd.getNextBoolean();
...@@ -483,6 +505,8 @@ public class EyesisCorrectionParameters { ...@@ -483,6 +505,8 @@ public class EyesisCorrectionParameters {
public int getChannelFromDCTTiff(String path, int type){return getChannelFromTiff(path, (type==0)?this.dctSymSuffix:this.dctAsymSuffix);} public int getChannelFromDCTTiff(String path, int type){return getChannelFromTiff(path, (type==0)?this.dctSymSuffix:this.dctAsymSuffix);}
public String getNameFromDCTTiff(String path, int type){return getNameFromTiff(path, (type==0)?this.dctSymSuffix:this.dctAsymSuffix);} public String getNameFromDCTTiff(String path, int type){return getNameFromTiff(path, (type==0)?this.dctSymSuffix:this.dctAsymSuffix);}
public int getChannelFromCLTTiff(String path){return getChannelFromTiff(path, this.cltSuffix);}
public String getNameFromCLTTiff(String path){return getNameFromTiff(path, this.cltSuffix);}
public boolean selectSourceFiles(boolean allFiles) { public boolean selectSourceFiles(boolean allFiles) {
return selectSourceFiles(allFiles, 1); // debug level 1 - modify here return selectSourceFiles(allFiles, 1); // debug level 1 - modify here
...@@ -826,8 +850,74 @@ public class EyesisCorrectionParameters { ...@@ -826,8 +850,74 @@ public class EyesisCorrectionParameters {
public String [] selectCLTChannelFiles(
int numChannels, // number of channels
int debugLevel) { // will only open dialog if directory or files are not found
String [] kernelFiles= selectCLTFiles(
debugLevel);
if (kernelFiles==null) return null;
String [] channelPaths=new String[numChannels];
for (int i=0;i<channelPaths.length;i++)channelPaths[i]=null;
for (int fileNum=0;fileNum<kernelFiles.length;fileNum++){
int chn=getChannelFromCLTTiff(kernelFiles[fileNum]);
if ((chn>=0) && (chn<numChannels)){
if (channelPaths[chn]==null){ // use first file for channel if there are multiple
channelPaths[chn]=kernelFiles[fileNum];
} else {
if (debugLevel>0) System.out.println("Multiple kernel files for channel "+
chn+": "+channelPaths[chn]+" and "+kernelFiles[fileNum]+". Using "+channelPaths[chn]);
}
}
}
return channelPaths;
}
public String [] selectCLTFiles(
int debugLevel) { // will only open dialog if directory or files are not found
String []defaultPaths = new String[1];
String kernelDirectory=this.cltKernelDirectory;
if ((kernelDirectory==null) || (kernelDirectory.length()<=1)){ // empty or "/"
defaultPaths[0]="";
} else {
defaultPaths[0]=kernelDirectory+Prefs.getFileSeparator();
}
String [] extensions={this.cltSuffix};
String kernelPrefix= this.cltKernelPrefix;
CalibrationFileManagement.MultipleExtensionsFileFilter kernelFilter =
new CalibrationFileManagement.MultipleExtensionsFileFilter(kernelPrefix,extensions,kernelPrefix+
"*"+extensions[0]+" CLT symmetrical kernel files");
if (debugLevel>1) System.out.println("selectKernelFiles("+debugLevel+"): defaultPaths[0]="+defaultPaths[0]+" "+kernelPrefix+"*"+extensions[0]);
String [] kernelFiles=null;
// try reading all matching files
File dir= new File (kernelDirectory);
File [] fileList=null;
if (dir.exists()) {
fileList=dir.listFiles(kernelFilter);
}
if ((fileList==null) || (fileList.length==0)){
kernelFiles=CalibrationFileManagement.selectFiles(false,
"Select CLT kernel files",
"Select",
kernelFilter,
defaultPaths); // String [] defaultPaths); //this.sourceDirectory // null
if ((kernelFiles!=null) && (kernelFiles.length>0)){
kernelDirectory=kernelFiles[0].substring(0, kernelFiles[0].lastIndexOf(Prefs.getFileSeparator()));
dir= new File (kernelDirectory);
fileList=dir.listFiles(kernelFilter);
this.cltKernelDirectory= kernelDirectory;
}
}
if ((fileList==null) || (fileList.length==0)) return null;
if (debugLevel>1) System.out.println("CLT kernel directory "+kernelDirectory+" has "+fileList.length+" matching files.");
kernelFiles = new String[fileList.length];
for (int i=0;i<kernelFiles.length;i++) kernelFiles[i]=fileList[i].getPath();
String directory=kernelFiles[0].substring(0, kernelFiles[0].lastIndexOf(Prefs.getFileSeparator()));
String prefix=kernelFiles[0].substring(directory.length()+1, kernelFiles[0].length()-extensions[0].length()-2); // all but NN
this.cltKernelDirectory=directory;
this.cltKernelPrefix=prefix;
return kernelFiles;
}
public String selectSourceDirectory(boolean smart, boolean newAllowed) { // normally newAllowed=false public String selectSourceDirectory(boolean smart, boolean newAllowed) { // normally newAllowed=false
String dir= CalibrationFileManagement.selectDirectory( String dir= CalibrationFileManagement.selectDirectory(
...@@ -880,13 +970,25 @@ public class EyesisCorrectionParameters { ...@@ -880,13 +970,25 @@ public class EyesisCorrectionParameters {
smart, smart,
newAllowed, // save newAllowed, // save
"DCT aberration kernels directory (sym and asym files)", // title "DCT aberration kernels directory (sym and asym files)", // title
"Select DCT aberration kernelsdirectory", // button "Select DCT aberration kernel sdirectory", // button
null, // filter null, // filter
this.dctKernelDirectory); //this.sourceDirectory); this.dctKernelDirectory); //this.sourceDirectory);
if (dir!=null) this.dctKernelDirectory=dir; if (dir!=null) this.dctKernelDirectory=dir;
return dir; return dir;
} }
public String selectCLTKernelDirectory(boolean smart, boolean newAllowed) {
String dir= CalibrationFileManagement.selectDirectory(
smart,
newAllowed, // save
"CLT aberration kernels directory", // title
"Select CLT aberration kernels directory", // button
null, // filter
this.cltKernelDirectory); //this.sourceDirectory);
if (dir!=null) this.cltKernelDirectory=dir;
return dir;
}
public String selectEquirectangularDirectory(boolean smart, boolean newAllowed) { public String selectEquirectangularDirectory(boolean smart, boolean newAllowed) {
String dir= CalibrationFileManagement.selectDirectory( String dir= CalibrationFileManagement.selectDirectory(
smart, smart,
...@@ -1780,6 +1882,8 @@ public class EyesisCorrectionParameters { ...@@ -1780,6 +1882,8 @@ public class EyesisCorrectionParameters {
public double fat_zero = 0.0; // modify phase correlation to prevent division by very small numbers public double fat_zero = 0.0; // modify phase correlation to prevent division by very small numbers
public double corr_sigma =0.8; // LPF correlarion sigma public double corr_sigma =0.8; // LPF correlarion sigma
public boolean norm_kern = true; // normalize kernels
public CLTParameters(){} public CLTParameters(){}
public void setProperties(String prefix,Properties properties){ public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"transform_size",this.transform_size+""); properties.setProperty(prefix+"transform_size",this.transform_size+"");
...@@ -1820,7 +1924,7 @@ public class EyesisCorrectionParameters { ...@@ -1820,7 +1924,7 @@ public class EyesisCorrectionParameters {
gd.addNumericField("Tile Y to extract (0..122)", this.tileY, 0); gd.addNumericField("Tile Y to extract (0..122)", this.tileY, 0);
gd.addNumericField("dbg_mode: 0 - normal, +1 - no DCT/IDCT, just fold", this.dbg_mode, 0); gd.addNumericField("dbg_mode: 0 - normal, +1 - no DCT/IDCT, just fold", this.dbg_mode, 0);
gd.addNumericField("ishift_x: shift source image by this pixels left", this.ishift_x, 0); gd.addNumericField("ishift_x: shift source image by this pixels left", this.ishift_x, 0);
gd.addNumericField("ishift_x: shift source image by this pixels down", this.ishift_y, 0); gd.addNumericField("ishift_y: shift source image by this pixels down", this.ishift_y, 0);
gd.addNumericField("Modify phase correlation to prevent division by very small numbers", this.fat_zero, 4); gd.addNumericField("Modify phase correlation to prevent division by very small numbers", this.fat_zero, 4);
gd.addNumericField("LPF correlarion sigma ", this.corr_sigma, 3); gd.addNumericField("LPF correlarion sigma ", this.corr_sigma, 3);
WindowTools.addScrollBars(gd); WindowTools.addScrollBars(gd);
......
...@@ -38,6 +38,7 @@ public class EyesisDCT { ...@@ -38,6 +38,7 @@ public class EyesisDCT {
public EyesisCorrectionParameters.CorrectionParameters correctionsParameters=null; public EyesisCorrectionParameters.CorrectionParameters correctionsParameters=null;
public EyesisCorrectionParameters.DCTParameters dctParameters = null; public EyesisCorrectionParameters.DCTParameters dctParameters = null;
public DCTKernels [] kernels = null; public DCTKernels [] kernels = null;
double [][][][][][] clt_kernels = null;
public ImagePlus eyesisKernelImage = null; public ImagePlus eyesisKernelImage = null;
public long startTime; public long startTime;
...@@ -82,11 +83,162 @@ public class EyesisDCT { ...@@ -82,11 +83,162 @@ public class EyesisDCT {
return kernels != null; return kernels != null;
} }
public boolean createDCTKernels( public DCTKernels calculateDCTKernel (
EyesisCorrectionParameters.DCTParameters dct_parameters, final ImageStack kernelStack, // first stack with 3 colors/slices convolution kernels
final int kernelSize, // 64
final EyesisCorrectionParameters.DCTParameters dct_parameters,
/* /*
PixelMapping pixelMapping, final double [][] vignetting,
int vign_width,
int vign_height,
int vign_decimation,
*/ */
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int globalDebugLevel) // update status info
{
if (kernelStack==null) return null;
final int kernelWidth=kernelStack.getWidth();
final int kernelNumHor=kernelWidth/kernelSize;
final int kernelNumVert=kernelStack.getHeight()/kernelSize;
final int nChn=kernelStack.getSize();
// final int length=kernelNumHor*kernelNumVert* dct_parameters.dct_size * dct_parameters.dct_size;// size of kernel data
final DCTKernels dct_kernel = new DCTKernels();
dct_kernel.size = dct_parameters.dct_size;
dct_kernel.img_step = kernelSize/2/dct_parameters.decimation ; // May be wrong
dct_kernel.sym_kernels = new double [nChn][kernelNumHor*kernelNumVert*dct_parameters.dct_size * dct_parameters.dct_size];
dct_kernel.asym_kernels = new double [nChn][kernelNumHor*kernelNumVert*dct_parameters.asym_size * dct_parameters.asym_size];
dct_kernel.asym_nonzero = dct_parameters.asym_pixels;
// currently each 64x64 kernel corresponds to 16x16 original pixels tile, 2 tiles margin each side
final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels= kernelNumHor*kernelNumVert*nChn;
final int numberOfKernelsInChn=kernelNumHor*kernelNumVert;
final int dct_size = dct_parameters.dct_size;
final int preTargetSize = 4 * dct_size;
final int targetSize = 2 * dct_size; // normally 16
final double [] anitperiodic_window = createAntiperiodicWindow(dct_size);
// final int chn_green = 2; // all others multiply by 4 as there 1 in 4 Bayer for those, green - by 2
final long startTime = System.nanoTime();
System.out.println("calculateDCTKernel():numberOfKernels="+numberOfKernels);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
DoubleGaussianBlur gb=null;
if (dct_parameters.decimateSigma > 0) gb=new DoubleGaussianBlur();
float [] kernelPixels= null; // will be initialized at first use NOT yet?
double [] kernel= new double[kernelSize*kernelSize];
double [] pre_target_kernel= new double [preTargetSize * preTargetSize]; // before made antiperiodic
double [] target_kernel = new double [targetSize * targetSize]; // strictly antiperiodic in both x and y directions
FactorConvKernel factorConvKernel = new FactorConvKernel();
factorConvKernel.setDebugLevel (0); // globalDebugLevel);
factorConvKernel.setTargetWindowMode (dct_parameters.centerWindowToTarget);
factorConvKernel.numIterations = dct_parameters.LMA_steps;
factorConvKernel.setAsymCompactness (dct_parameters.compactness, dct_parameters.asym_tax_free);
factorConvKernel.setSymCompactness (dct_parameters.sym_compactness);
factorConvKernel.setDCWeight (dct_parameters.dc_weight);
int chn,tileY,tileX;
for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) {
chn=nTile/numberOfKernelsInChn;
tileY =(nTile % numberOfKernelsInChn)/kernelNumHor;
tileX = nTile % kernelNumHor;
if (tileX==0) {
if (updateStatus) IJ.showStatus("Processing kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+kernelNumVert);
if (globalDebugLevel>2) System.out.println("Processing kernels, channel "+(chn+1)+" of "+nChn+", row "+(tileY+1)+" of "+kernelNumVert+" : "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
}
kernelPixels=(float[]) kernelStack.getPixels(chn+1);
/* read convolution kernel */
extractOneKernel(
kernelPixels, // array of combined square kernels, each
kernel, // will be filled, should have correct size before call
kernelNumHor, // number of kernels in a row
tileX, // horizontal number of kernel to extract
tileY); // vertical number of kernel to extract
if ((dct_parameters.decimation == 2) && (dct_parameters.decimateSigma<0)) {
reformatKernel2( // averages by exactly 2 (decimate==2)
kernel,
pre_target_kernel, // expand/crop, blur/decimate result (32x32)
kernelSize,
preTargetSize); // 32
} else {
reformatKernel(
kernel, // will be blurred in-place
pre_target_kernel, // expand/crop, blur/decimate result (32x32)
kernelSize,
preTargetSize, // 32
dct_parameters.decimation,
dct_parameters.decimateSigma,
gb);
}
if (dct_parameters.normalize) { // or should it be normalized after antiperiodic?
double s =0.0;
for (int i = 0; i < pre_target_kernel.length; i++){
s+=pre_target_kernel[i];
}
s = 1.0 / s;
for (int i = 0; i < pre_target_kernel.length; i++){
pre_target_kernel[i] *= s;
}
if (globalDebugLevel > 1){ // was already close to 1.0
System.out.println(tileX+"/"+tileY+ " s="+s);
}
}
// make exactly anitperiodic
makeAntiperiodic(
dct_size,
pre_target_kernel, // 16*dct_zize*dct_zize
anitperiodic_window, // 16*dct_zize*dct_zize
target_kernel); // 4*dct_zize*dct_zize
factorConvKernel.calcKernels(
target_kernel,
dct_parameters.asym_size,
dct_parameters.dct_size,
dct_parameters.fact_precision,
dct_parameters.asym_pixels, // maximal number of non-zero pixels in asymmmetrical kernel
dct_parameters.asym_distance, // how far to seed a new pixel
dct_parameters.seed_size);
double [] sym_kernel = factorConvKernel.getSymKernel();
double [] asym_kernel = factorConvKernel.getAsymKernel();
int sym_kernel_inc_index = kernelNumHor * dct_parameters.dct_size;
int sym_kernel_start_index = (sym_kernel_inc_index * tileY + tileX) * dct_parameters.dct_size;
for (int i = 0; i<dct_parameters.dct_size;i++){
System.arraycopy(
sym_kernel,
i * dct_parameters.dct_size,
dct_kernel.sym_kernels[chn],
sym_kernel_start_index + i * sym_kernel_inc_index,
dct_parameters.dct_size);
}
int asym_kernel_inc_index = kernelNumHor * dct_parameters.asym_size;
int asym_kernel_start_index = (asym_kernel_inc_index * tileY + tileX)* dct_parameters.asym_size;
for (int i = 0; i<dct_parameters.asym_size;i++){
System.arraycopy(
asym_kernel,
i * dct_parameters.asym_size,
dct_kernel.asym_kernels[chn],
asym_kernel_start_index + i * asym_kernel_inc_index,
dct_parameters.asym_size);
}
}
}
};
}
ImageDtt.startAndJoin(threads);
if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
System.out.println("1.Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
/* prepare result stack to return */
return dct_kernel;
}
public boolean createDCTKernels(
EyesisCorrectionParameters.DCTParameters dct_parameters,
int srcKernelSize, int srcKernelSize,
int threadsMax, // maximal number of threads to launch int threadsMax, // maximal number of threads to launch
boolean updateStatus, boolean updateStatus,
...@@ -184,16 +336,11 @@ public class EyesisDCT { ...@@ -184,16 +336,11 @@ public class EyesisDCT {
} }
public DCTKernels calculateDCTKernel ( public double [][][][][] calculateCLTKernel ( // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
final ImageStack kernelStack, // first stack with 3 colors/slices convolution kernels final ImageStack kernelStack, // first stack with 3 colors/slices convolution kernels
final int kernelSize, // 64 final int kernelSize, // 64
final EyesisCorrectionParameters.DCTParameters dct_parameters, final EyesisCorrectionParameters.CLTParameters clt_parameters,
/*
final double [][] vignetting,
int vign_width,
int vign_height,
int vign_decimation,
*/
final int threadsMax, // maximal number of threads to launch final int threadsMax, // maximal number of threads to launch
final boolean updateStatus, final boolean updateStatus,
final int globalDebugLevel) // update status info final int globalDebugLevel) // update status info
...@@ -203,44 +350,48 @@ public class EyesisDCT { ...@@ -203,44 +350,48 @@ public class EyesisDCT {
final int kernelNumHor=kernelWidth/kernelSize; final int kernelNumHor=kernelWidth/kernelSize;
final int kernelNumVert=kernelStack.getHeight()/kernelSize; final int kernelNumVert=kernelStack.getHeight()/kernelSize;
final int nChn=kernelStack.getSize(); final int nChn=kernelStack.getSize();
// final int length=kernelNumHor*kernelNumVert* dct_parameters.dct_size * dct_parameters.dct_size;// size of kernel data final int dtt_size = clt_parameters.transform_size;
final DCTKernels dct_kernel = new DCTKernels(); final int dtt_len = dtt_size* dtt_size;
dct_kernel.size = dct_parameters.dct_size; final double [][][][][] clt_kernels = new double [nChn][kernelNumVert][kernelNumHor][5][];
dct_kernel.img_step = kernelSize/2/dct_parameters.decimation ; // May be wrong for (int chn = 0; chn < nChn; chn++){
dct_kernel.sym_kernels = new double [nChn][kernelNumHor*kernelNumVert*dct_parameters.dct_size * dct_parameters.dct_size]; for (int tileY = 0; tileY < kernelNumVert ; tileY++){
dct_kernel.asym_kernels = new double [nChn][kernelNumHor*kernelNumVert*dct_parameters.asym_size * dct_parameters.asym_size]; for (int tileX = 0; tileX < kernelNumHor ; tileX++){
dct_kernel.asym_nonzero = dct_parameters.asym_pixels; for (int n = 0; n<4; n++){
clt_kernels[chn][tileY][tileX][n] = new double [dtt_len];
}
clt_kernels[chn][tileY][tileX][4] = new double [2];
}
}
}
// currently each 64x64 kernel corresponds to 16x16 original pixels tile, 2 tiles margin each side // currently each 64x64 kernel corresponds to 16x16 original pixels tile, 2 tiles margin each side
final Thread[] threads = ImageDtt.newThreadArray(threadsMax); final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0); final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels= kernelNumHor*kernelNumVert*nChn; final int numberOfKernels= kernelNumHor*kernelNumVert*nChn;
final int numberOfKernelsInChn=kernelNumHor*kernelNumVert; final int numberOfKernelsInChn=kernelNumHor*kernelNumVert;
final int dct_size = dct_parameters.dct_size; final double [] norm_sym_weights = clt_parameters.norm_kern ? new double [dtt_size*dtt_size]:null;
final int preTargetSize = 4 * dct_size; if (norm_sym_weights != null) {
final int targetSize = 2 * dct_size; // normally 16 for (int i = 0; i < dtt_size; i++){
final double [] anitperiodic_window = createAntiperiodicWindow(dct_size); for (int j = 0; j < dtt_size; j++){
// final int chn_green = 2; // all others multiply by 4 as there 1 in 4 Bayer for those, green - by 2 norm_sym_weights[i*dtt_size+j] = Math.cos(Math.PI*i/(2*dtt_size))*Math.cos(Math.PI*j/(2*dtt_size));
}
}
}
final long startTime = System.nanoTime(); final long startTime = System.nanoTime();
System.out.println("calculateDCTKernel():numberOfKernels="+numberOfKernels); System.out.println("calculateDCTKernel():numberOfKernels="+numberOfKernels);
for (int ithread = 0; ithread < threads.length; ithread++) { for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() { threads[ithread] = new Thread() {
public void run() { public void run() {
DoubleGaussianBlur gb=null;
if (dct_parameters.decimateSigma > 0) gb=new DoubleGaussianBlur();
float [] kernelPixels= null; // will be initialized at first use NOT yet? float [] kernelPixels= null; // will be initialized at first use NOT yet?
double [] kernel= new double[kernelSize*kernelSize]; double [] kernel= new double[kernelSize*kernelSize];
double [] pre_target_kernel= new double [preTargetSize * preTargetSize]; // before made antiperiodic int centered_len = (2*dtt_size-1) * (2*dtt_size-1);
double [] target_kernel = new double [targetSize * targetSize]; // strictly antiperiodic in both x and y directions double [] kernel_centered = new double [centered_len +2];
ImageDtt image_dtt = new ImageDtt();
FactorConvKernel factorConvKernel = new FactorConvKernel();
factorConvKernel.setDebugLevel (0); // globalDebugLevel);
factorConvKernel.setTargetWindowMode (dct_parameters.centerWindowToTarget);
factorConvKernel.numIterations = dct_parameters.LMA_steps;
factorConvKernel.setAsymCompactness (dct_parameters.compactness, dct_parameters.asym_tax_free);
factorConvKernel.setSymCompactness (dct_parameters.sym_compactness);
factorConvKernel.setDCWeight (dct_parameters.dc_weight);
int chn,tileY,tileX; int chn,tileY,tileX;
DttRad2 dtt = new DttRad2(dtt_size);
showDoubleFloatArrays sdfa_instance = null;
if (globalDebugLevel > -1) sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) { for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) {
chn=nTile/numberOfKernelsInChn; chn=nTile/numberOfKernelsInChn;
tileY =(nTile % numberOfKernelsInChn)/kernelNumHor; tileY =(nTile % numberOfKernelsInChn)/kernelNumHor;
...@@ -258,75 +409,285 @@ public class EyesisDCT { ...@@ -258,75 +409,285 @@ public class EyesisDCT {
kernelNumHor, // number of kernels in a row kernelNumHor, // number of kernels in a row
tileX, // horizontal number of kernel to extract tileX, // horizontal number of kernel to extract
tileY); // vertical number of kernel to extract tileY); // vertical number of kernel to extract
if ((globalDebugLevel > 0) && (tileY == clt_parameters.tileY/2) && (tileX == clt_parameters.tileX/2)) {
if ((dct_parameters.decimation == 2) && (dct_parameters.decimateSigma<0)) { int length=kernel.length;
reformatKernel2( // averages by exactly 2 (decimate==2) int size=(int) Math.sqrt(length);
sdfa_instance.showArrays(
kernel, kernel,
pre_target_kernel, // expand/crop, blur/decimate result (32x32) size,
kernelSize, size,
preTargetSize); // 32 "raw_kernel-"+chn+"-X"+(clt_parameters.tileX/2)+"-Y"+(clt_parameters.tileY/2));
} else { }
reformatKernel(
kernel, // will be blurred in-place // now has 64x64
pre_target_kernel, // expand/crop, blur/decimate result (32x32) image_dtt.clt_convert_double_kernel( // converts double resolution kernel
kernelSize, kernel, // double [] src_kernel, //
preTargetSize, // 32 kernel_centered, // double [] dst_kernel, // should be (2*dtt_size-1) * (2*dtt_size-1) +2 size - kernel and dx, dy to the nearest 1/2 pixels
dct_parameters.decimation, kernelSize, // int src_size, // 64
dct_parameters.decimateSigma, dtt_size); // 8
gb); if ((globalDebugLevel > 0) && (tileY == clt_parameters.tileY/2) && (tileX == clt_parameters.tileX/2)) {
int length=kernel_centered.length;
int size=(int) Math.sqrt(length);
sdfa_instance.showArrays(
kernel_centered,
size,
size,
"kernel_centered-"+chn+"-X"+(clt_parameters.tileX/2)+"-Y"+(clt_parameters.tileY/2));
}
if (norm_sym_weights != null) {
image_dtt.clt_normalize_kernel( //
kernel_centered, // double [] kernel, // should be (2*dtt_size-1) * (2*dtt_size-1) +2 size (last 2 are not modified)
norm_sym_weights, // double [] window, // normalizes result kernel * window to have sum of elements == 1.0
dtt_size); // 8
if ((globalDebugLevel > 0) && (tileY == clt_parameters.tileY/2) && (tileX == clt_parameters.tileX/2)) {
int length=kernel_centered.length;
int size=(int) Math.sqrt(length);
sdfa_instance.showArrays(
kernel_centered,
size,
size,
"kernel_normalized-"+chn+"-X"+(clt_parameters.tileX/2)+"-Y"+(clt_parameters.tileY/2));
}
}
image_dtt.clt_symmetrize_kernel( //
kernel_centered, // double [] kernel, // should be (2*dtt_size-1) * (2*dtt_size-1) +2 size (last 2 are not modified)
clt_kernels[chn][tileY][tileX], // double [][] sym_kernels, // set of 4 SS, AS, SA, AA kdernels, each dtt_size * dtt_size (may have 5-th with center shift
dtt_size); // 8
clt_kernels[chn][tileY][tileX][4][0] = kernel_centered [centered_len + 0];
clt_kernels[chn][tileY][tileX][4][1] = kernel_centered [centered_len + 1];
if ((globalDebugLevel > 0) && (tileY == clt_parameters.tileY/2) && (tileX == clt_parameters.tileX/2)) {
double [][] dbg_clt = {
clt_kernels[chn][tileY][tileX][0],
clt_kernels[chn][tileY][tileX][1],
clt_kernels[chn][tileY][tileX][2],
clt_kernels[chn][tileY][tileX][3]};
String [] titles = {"CC", "SC", "CS", "SS"};
int length=dbg_clt[0].length;
int size=(int) Math.sqrt(length);
sdfa_instance.showArrays(
dbg_clt,
size,
size,
true,
"pre_clt_kernels-"+chn,
titles);
}
image_dtt.clt_dtt3_kernel( //
clt_kernels[chn][tileY][tileX], // double [][] kernels, // set of 4 SS, AS, SA, AA kdernels, each dtt_size * dtt_size (may have 5-th with center shift
dtt_size, // 8
dtt);
if ((globalDebugLevel > 0) && (tileY == clt_parameters.tileY/2) && (tileX == clt_parameters.tileX/2)) {
double [][] dbg_clt = {
clt_kernels[chn][tileY][tileX][0],
clt_kernels[chn][tileY][tileX][1],
clt_kernels[chn][tileY][tileX][2],
clt_kernels[chn][tileY][tileX][3]};
String [] titles = {"CC", "SC", "CS", "SS"};
int length=dbg_clt[0].length;
int size=(int) Math.sqrt(length);
sdfa_instance.showArrays(
dbg_clt,
size,
size,
true,
"dbg_clt_kernels-"+chn,
titles);
System.out.println("calculateCLTKernel() chn="+chn+" "+
"tileX = "+clt_parameters.tileX+" ("+(clt_parameters.tileX/2)+") "+
"tileY = "+clt_parameters.tileY+" ("+(clt_parameters.tileY/2)+") "+
"center_x = "+clt_kernels[chn][tileY][tileX][4][0]+", "+
"center_y = "+clt_kernels[chn][tileY][tileX][4][1]);
} }
if (dct_parameters.normalize) { // or should it be normalized after antiperiodic?
double s =0.0;
for (int i = 0; i < pre_target_kernel.length; i++){
s+=pre_target_kernel[i];
} }
s = 1.0 / s;
for (int i = 0; i < pre_target_kernel.length; i++){
pre_target_kernel[i] *= s;
} }
if (globalDebugLevel > 1){ // was already close to 1.0 };
System.out.println(tileX+"/"+tileY+ " s="+s);
} }
ImageDtt.startAndJoin(threads);
if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
System.out.println("1.Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
/* prepare result stack to return */
return clt_kernels;
} }
// make exactly anitperiodic
makeAntiperiodic(
dct_size,
pre_target_kernel, // 16*dct_zize*dct_zize
anitperiodic_window, // 16*dct_zize*dct_zize
target_kernel); // 4*dct_zize*dct_zize
public double [][] flattenCLTKernels ( // per color, save 4 kernelas and displacement as (2*dtt_size+1)*(2*dtt_size) tiles in an image (last row - shift x,y)
final double [][][][][] kernels, // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int globalDebugLevel) // update status info
{
if (kernels==null) return null;
final int nChn = kernels.length;
final int kernelNumVert=kernels[0].length;
final int kernelNumHor=kernels[0][0].length;
final int dtt_len = kernels[0][0][0][0].length;
final int dtt_size = (int) Math.sqrt(dtt_len);
final int tileWidth = 2 * dtt_size;
final int tileHeight = 2 * dtt_size + 1; // last row - shift with 0.5 pix steps
final int width = tileWidth * kernelNumHor;
final int height = tileHeight * kernelNumVert;
final double [][] clt_flat = new double [nChn][width * height];
// currently each 64x64 kernel corresponds to 16x16 original pixels tile, 2 tiles margin each side
final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels= kernelNumHor*kernelNumVert*nChn;
final int numberOfKernelsInChn=kernelNumHor*kernelNumVert;
factorConvKernel.calcKernels( final long startTime = System.nanoTime();
target_kernel, System.out.println("flattenCLTKernels():numberOfKernels="+numberOfKernels);
dct_parameters.asym_size, for (int ithread = 0; ithread < threads.length; ithread++) {
dct_parameters.dct_size, threads[ithread] = new Thread() {
dct_parameters.fact_precision, public void run() {
dct_parameters.asym_pixels, // maximal number of non-zero pixels in asymmmetrical kernel int chn,tileY,tileX;
dct_parameters.asym_distance, // how far to seed a new pixel for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) {
dct_parameters.seed_size); chn=nTile/numberOfKernelsInChn;
double [] sym_kernel = factorConvKernel.getSymKernel(); tileY =(nTile % numberOfKernelsInChn)/kernelNumHor;
double [] asym_kernel = factorConvKernel.getAsymKernel(); tileX = nTile % kernelNumHor;
int sym_kernel_inc_index = kernelNumHor * dct_parameters.dct_size; for (int i = 0; i < dtt_size; i++){
int sym_kernel_start_index = (sym_kernel_inc_index * tileY + tileX) * dct_parameters.dct_size;
for (int i = 0; i<dct_parameters.dct_size;i++){
System.arraycopy( System.arraycopy(
sym_kernel, kernels[chn][tileY][tileX][0],
i * dct_parameters.dct_size, i * dtt_size,
dct_kernel.sym_kernels[chn], clt_flat[chn],
sym_kernel_start_index + i * sym_kernel_inc_index, (tileY*tileHeight + i) * width + (tileX * tileWidth),
dct_parameters.dct_size); dtt_size);
System.arraycopy(
kernels[chn][tileY][tileX][1],
i * dtt_size,
clt_flat[chn],
(tileY*tileHeight + i) * width + (tileX * tileWidth) + dtt_size,
dtt_size);
System.arraycopy(
kernels[chn][tileY][tileX][2],
i * dtt_size,
clt_flat[chn],
(tileY*tileHeight + i + dtt_size) * width + (tileX * tileWidth),
dtt_size);
System.arraycopy(
kernels[chn][tileY][tileX][3],
i * dtt_size,
clt_flat[chn],
(tileY*tileHeight + i + dtt_size) * width + (tileX * tileWidth) + 1 * dtt_size,
dtt_size);
} }
int asym_kernel_inc_index = kernelNumHor * dct_parameters.asym_size;
int asym_kernel_start_index = (asym_kernel_inc_index * tileY + tileX)* dct_parameters.asym_size;
for (int i = 0; i<dct_parameters.asym_size;i++){
System.arraycopy( System.arraycopy(
asym_kernel, kernels[chn][tileY][tileX][4], // just 2 values
i * dct_parameters.asym_size, 0,
dct_kernel.asym_kernels[chn], clt_flat[chn],
asym_kernel_start_index + i * asym_kernel_inc_index, (tileY*tileHeight + 2 * dtt_size) * width + (tileX * tileWidth),
dct_parameters.asym_size); 2);
}
}
};
}
ImageDtt.startAndJoin(threads);
if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
System.out.println("1.Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
/* prepare result stack to return */
return clt_flat;
}
public void showCLTKernels(
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int globalDebugLevel) // update status info
{
for (int chn=0;chn < clt_kernels.length; chn++){
if (clt_kernels[chn]!=null){
// System.out.println("showKernels("+chn+")");
showCLTKernels(
chn,
threadsMax,
updateStatus,
globalDebugLevel);
}
}
}
public void showCLTKernels(
int chn,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int globalDebugLevel) // update status info
{
double [][] flat_kernels = flattenCLTKernels ( // per color, save 4 kernelas and displacement as (2*dtt_size+1)*(2*dtt_size) tiles in an image (last row - shift x,y)
clt_kernels[chn], // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
threadsMax, // maximal number of threads to launch
updateStatus,
globalDebugLevel); // update status info
int dtt_len = clt_kernels[chn][0][0][0][0].length;
int dtt_size= (int)Math.sqrt(dtt_len);
String [] titles = {"red", "blue", "green"};
showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays();
sdfa_instance.showArrays(
flat_kernels,
clt_kernels[chn][0][0].length*(2*dtt_size),
clt_kernels[chn][0].length*(2*dtt_size+1),
true,
"clt_kernels-"+chn,
titles);
}
public double [][][][][] extractCLTKernels ( // per color, save 4 kernelas and displacement as (2*dtt_size+1)*(2*dtt_size) tiles in an image (last row - shift x,y)
final float [][] flat_kernels, // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
final int width,
final int dtt_size,
final int threadsMax, // maximal number of threads to launch
final boolean updateStatus,
final int globalDebugLevel) // update status info
{
if (flat_kernels==null) return null;
final int nChn = flat_kernels.length;
final int height = flat_kernels[0].length/width;
final int tileWidth = 2 * dtt_size;
final int tileHeight = 2 * dtt_size + 1; // last row - shift with 0.5 pix steps
final int kernelNumHor = width / tileWidth;
final int kernelNumVert = height / tileHeight;
final int dtt_len = dtt_size*dtt_size;
final double [][][][][] clt_kernels = new double [nChn][kernelNumVert][kernelNumHor][5][];
for (int chn = 0; chn < nChn; chn++){
for (int tileY = 0; tileY < kernelNumVert ; tileY++){
for (int tileX = 0; tileX < kernelNumHor ; tileX++){
for (int n = 0; n<4; n++){
clt_kernels[chn][tileY][tileX][n] = new double [dtt_len];
}
clt_kernels[chn][tileY][tileX][4] = new double [2];
}
}
}
// currently each 64x64 kernel corresponds to 16x16 original pixels tile, 2 tiles margin each side
final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
final AtomicInteger ai = new AtomicInteger(0);
final int numberOfKernels= kernelNumHor*kernelNumVert*nChn;
final int numberOfKernelsInChn=kernelNumHor*kernelNumVert;
final long startTime = System.nanoTime();
System.out.println("flattenCLTKernels():numberOfKernels="+numberOfKernels);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
int chn,tileY,tileX;
for (int nTile = ai.getAndIncrement(); nTile < numberOfKernels; nTile = ai.getAndIncrement()) {
chn=nTile/numberOfKernelsInChn;
tileY =(nTile % numberOfKernelsInChn)/kernelNumHor;
tileX = nTile % kernelNumHor;
for (int i = 0; i < dtt_size; i++){
for (int j = 0; j<dtt_size; j++){
int indx = i*dtt_size+j;
int baddr = (tileY*tileHeight + i) * width + (tileX * tileWidth) + j;
clt_kernels[chn][tileY][tileX][0][indx] = flat_kernels[chn][baddr];
clt_kernels[chn][tileY][tileX][1][indx] = flat_kernels[chn][baddr + dtt_size];
clt_kernels[chn][tileY][tileX][2][indx] = flat_kernels[chn][baddr + dtt_size * width];
clt_kernels[chn][tileY][tileX][3][indx] = flat_kernels[chn][baddr + dtt_size * width + dtt_size];
} }
} }
clt_kernels[chn][tileY][tileX][4][0] = flat_kernels[chn][(tileY*tileHeight + 2 * dtt_size) * width + (tileX * tileWidth)];
clt_kernels[chn][tileY][tileX][4][1] = flat_kernels[chn][(tileY*tileHeight + 2 * dtt_size) * width + (tileX * tileWidth) + 1];
}
} }
}; };
} }
...@@ -334,12 +695,189 @@ public class EyesisDCT { ...@@ -334,12 +695,189 @@ public class EyesisDCT {
if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); if (globalDebugLevel > 1) System.out.println("Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
System.out.println("1.Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)); System.out.println("1.Threads done at "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
/* prepare result stack to return */ /* prepare result stack to return */
return dct_kernel; return clt_kernels;
}
/*
System.out.println("calculateCLTKernel() chn="+chn+" "+
"tileX = "+clt_parameters.tileX+" ("+(clt_parameters.tileX/2)+") "+
"tileY = "+clt_parameters.tileY+" ("+(clt_parameters.tileY/2)+") "+
"center_x = "+clt_kernels[chn][tileY][tileX][4][0]+", "+
"center_y = "+clt_kernels[chn][tileY][tileX][4][1]);
*/
public boolean createCLTKernels(
EyesisCorrectionParameters.CLTParameters clt_parameters,
int srcKernelSize,
int threadsMax, // maximal number of threads to launch
boolean updateStatus,
int debugLevel
){
String [] sharpKernelPaths= correctionsParameters.selectKernelChannelFiles(
0, // 0 - sharp, 1 - smooth
eyesisCorrections.usedChannels.length, // numChannels, // number of channels
eyesisCorrections.debugLevel);
if (sharpKernelPaths==null) return false;
for (int i=0;i<sharpKernelPaths.length;i++){
System.out.println(i+":"+sharpKernelPaths[i]);
}
if (clt_kernels == null){
clt_kernels = new double[eyesisCorrections.usedChannels.length][][][][][];
for (int chn=0;chn<eyesisCorrections.usedChannels.length;chn++){
clt_kernels[chn] = null;
}
}
showDoubleFloatArrays sdfa_instance = new showDoubleFloatArrays();
for (int chn=0;chn<eyesisCorrections.usedChannels.length;chn++){
if (eyesisCorrections.usedChannels[chn] && (sharpKernelPaths[chn]!=null) && (clt_kernels[chn]==null)){
ImagePlus imp_kernel_sharp=new ImagePlus(sharpKernelPaths[chn]);
if (imp_kernel_sharp.getStackSize()<3) {
System.out.println("Need a 3-layer stack with kernels");
sharpKernelPaths[chn]=null;
continue;
}
ImageStack kernel_sharp_stack= imp_kernel_sharp.getStack();
System.out.println("debugLevel = "+debugLevel+" kernel_sharp_stack.getWidth() = "+kernel_sharp_stack.getWidth()+
" kernel_sharp_stack.getHeight() = "+kernel_sharp_stack.getHeight());
double [][][][][] kernels = calculateCLTKernel ( // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
kernel_sharp_stack, // final ImageStack kernelStack, // first stack with 3 colors/slices convolution kernels
srcKernelSize, // final int kernelSize, // 64
clt_parameters, // final EyesisCorrectionParameters.CLTParameters clt_parameters,
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel); // update status info
double [][] flat_kernels = flattenCLTKernels ( // per color, save 4 kernelas and displacement as (2*dtt_size+1)*(2*dtt_size) tiles in an image (last row - shift x,y)
kernels, // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel); // update status info
int kernelNumHor=kernels[0][0].length;
int dtt_len = kernels[0][0][0][0].length;
int dtt_size = (int) Math.sqrt(dtt_len);
int tileWidth = 2 * dtt_size;
int width = tileWidth * kernelNumHor;
int height = flat_kernels[0].length/width;
String [] layerNames = {"red_clt_kernels","blue_clt_kernels","green_clt_kernels"};
ImageStack cltStack = sdfa_instance.makeStack(
flat_kernels,
width,
height,
layerNames);
String cltPath=correctionsParameters.cltKernelDirectory+
Prefs.getFileSeparator()+
correctionsParameters.cltKernelPrefix+
String.format("%02d",chn)+
correctionsParameters.cltSuffix;
String msg="Saving CLT convolution kernels to "+cltPath;
IJ.showStatus(msg);
if (debugLevel>0) System.out.println(msg);
ImagePlus imp_clt=new ImagePlus(imp_kernel_sharp.getTitle()+"-clt",cltStack);
if (debugLevel > 0) {
imp_clt.getProcessor().resetMinAndMax();
imp_clt.show();
}
FileSaver fs=new FileSaver(imp_clt);
fs.saveAsTiffStack(cltPath);
}
}
return true;
}
public boolean readCLTKernels(
EyesisCorrectionParameters.CLTParameters clt_parameters,
int threadsMax, // maximal number of threads to launch
boolean updateStatus,
int debugLevel
){
int dtt_size = clt_parameters.transform_size;
String [] cltKernelPaths = correctionsParameters.selectCLTChannelFiles(
// 0, // 0 - sharp, 1 - smooth
eyesisCorrections.usedChannels.length, // numChannels, // number of channels
eyesisCorrections.debugLevel);
if (cltKernelPaths==null) return false;
for (int i=0;i<cltKernelPaths.length;i++){
System.out.println(i+":"+cltKernelPaths[i]); // some may be null!
}
if (clt_kernels == null){
clt_kernels = new double[eyesisCorrections.usedChannels.length][][][][][];
for (int chn=0;chn<eyesisCorrections.usedChannels.length;chn++){
clt_kernels[chn] = null;
}
}
showDoubleFloatArrays sdfa_instance = null;
if (debugLevel>0){
sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
}
for (int chn=0;chn<eyesisCorrections.usedChannels.length;chn++){
if (eyesisCorrections.usedChannels[chn] && (cltKernelPaths[chn]!=null)){
ImagePlus imp_kernel_clt=new ImagePlus(cltKernelPaths[chn]);
if (imp_kernel_clt.getStackSize()<3) {
System.out.println("Need a 3-layer stack with symmetrical DCT kernels");
cltKernelPaths[chn]=null;
continue;
}
ImageStack kernel_clt_stack= imp_kernel_clt.getStack();
if (debugLevel>0){
System.out.println(" kernel_clt_stack.getWidth() = "+kernel_clt_stack.getWidth()+
" kernel_clt_stack.getHeight() = "+kernel_clt_stack.getHeight());
}
int nColors = kernel_clt_stack.getSize();
float [][] flat_kernels = new float [nColors][];
for (int nc = 0; nc < nColors; nc++){
flat_kernels[nc]= (float[]) kernel_clt_stack.getPixels(nc + 1);
}
clt_kernels[chn] = extractCLTKernels ( // per color, save 4 kernelas and displacement as (2*dtt_size+1)*(2*dtt_size) tiles in an image (last row - shift x,y)
flat_kernels, // per color/per tileY/ per tileX/per quadrant (plus offset as 5-th)/per pixel
kernel_clt_stack.getWidth(), // final int width,
dtt_size,
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel); // update status info
if (sdfa_instance != null){
for (int nc = 0; nc < clt_kernels[chn].length; nc++){
double [][] dbg_clt = {
clt_kernels[chn][nc][clt_parameters.tileY/2][clt_parameters.tileX/2][0],
clt_kernels[chn][nc][clt_parameters.tileY/2][clt_parameters.tileX/2][1],
clt_kernels[chn][nc][clt_parameters.tileY/2][clt_parameters.tileX/2][2],
clt_kernels[chn][nc][clt_parameters.tileY/2][clt_parameters.tileX/2][3]};
String [] titles = {"CC", "SC", "CS", "SS"};
int length=dbg_clt[0].length;
int size=(int) Math.sqrt(length);
sdfa_instance.showArrays(
dbg_clt,
size,
size,
true,
"dbg_clt-"+nc,
titles);
System.out.println("readCLTKernels() chn="+chn+", color="+nc+" "+
"tileX = "+clt_parameters.tileX+" ("+(clt_parameters.tileX/2)+") "+
"tileY = "+clt_parameters.tileY+" ("+(clt_parameters.tileY/2)+") "+
"center_x = "+clt_kernels[chn][nc][clt_parameters.tileY/2][clt_parameters.tileX/2][4][0]+", "+
"center_y = "+clt_kernels[chn][nc][clt_parameters.tileY/2][clt_parameters.tileX/2][4][1]);
}
}
}
}
return true;
} }
//processChannelImage
//convolveStackWithKernelStack
// mostly for testing
// mostly for testing
//eyesisKernelImage //eyesisKernelImage
public double [] extractOneKernelFromStack( public double [] extractOneKernelFromStack(
final int kernelSize, // 64 final int kernelSize, // 64
...@@ -562,6 +1100,10 @@ public class EyesisDCT { ...@@ -562,6 +1100,10 @@ public class EyesisDCT {
{ {
kernels = null; kernels = null;
} }
public void resetCLTKernels()
{
clt_kernels = null;
}
public boolean readDCTKernels( public boolean readDCTKernels(
EyesisCorrectionParameters.DCTParameters dct_parameters, EyesisCorrectionParameters.DCTParameters dct_parameters,
......
...@@ -490,9 +490,10 @@ private Panel panel1, ...@@ -490,9 +490,10 @@ private Panel panel1,
addButton("CLT stack", panelClt1, color_process); addButton("CLT stack", panelClt1, color_process);
addButton("Select second CLT image", panelClt1, color_configure); addButton("Select second CLT image", panelClt1, color_configure);
addButton("CLT correlate", panelClt1, color_process); addButton("CLT correlate", panelClt1, color_process);
addButton("CLT test 2", panelClt1, color_process); addButton("Create CLT kernels", panelClt1, color_process);
addButton("CLT test 3", panelClt1, color_process); addButton("Read CLT kernels", panelClt1, color_process);
addButton("CLT test 4", panelClt1, color_process); addButton("Reset CLT kernels", panelClt1, color_stop);
addButton("CLT process files", panelClt1, color_process);
add(panelClt1); add(panelClt1);
} }
pack(); pack();
...@@ -4044,28 +4045,106 @@ private Panel panel1, ...@@ -4044,28 +4045,106 @@ private Panel panel1,
DBG_IMP.getTitle()+"-C"+suffix, titles_rbg); DBG_IMP.getTitle()+"-C"+suffix, titles_rbg);
} }
//==============================================================================
} else if (label.equals("Create CLT kernels")) {
if (!CLT_PARAMETERS.showDialog()) return;
if (EYESIS_DCT == null){
EYESIS_DCT = new EyesisDCT (
EYESIS_CORRECTIONS,
CORRECTION_PARAMETERS,
DCT_PARAMETERS);
}
String configPath=null;
if (EYESIS_CORRECTIONS.correctionsParameters.saveSettings) {
configPath=EYESIS_CORRECTIONS.correctionsParameters.selectResultsDirectory(
true,
true);
if (configPath==null){
String msg="No results directory selected, command aborted";
System.out.println("Warning: "+msg);
IJ.showMessage("Warning",msg);
return;
}
configPath+=Prefs.getFileSeparator()+"autoconfig";
try {
saveTimestampedProperties(
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
} catch (Exception e){
String msg="Failed to save configuration to "+configPath+", command aborted";
System.out.println("Error: "+msg);
IJ.showMessage("Error",msg);
return;
}
}
EYESIS_CORRECTIONS.initSensorFiles(DEBUG_LEVEL);
/* EYESIS_DCT.createCLTKernels(
double [][] iclt_data = new double [clt_data.length][]; CLT_PARAMETERS,
for (int chn=0; chn<iclt_data.length;chn++){ CONVOLVE_FFT_SIZE/2,
iclt_data[chn] = image_dtt.iclt_2d( THREADS_MAX,
clt_data[chn], // scanline representation of dcd data, organized as dct_size x dct_size tiles UPDATE_STATUS, // update status info
CLT_PARAMETERS.transform_size, // final int DEBUG_LEVEL);
CLT_PARAMETERS.clt_window, //window_type
CLT_PARAMETERS.iclt_mask, //which of 4 to transform back //"Reset DCT kernels"
CLT_PARAMETERS.dbg_mode, //which of 4 to transform back } else if (label.equals("Reset CLT kernels")) {
THREADS_MAX, // maximal number of threads to launch if (EYESIS_DCT != null){
DEBUG_LEVEL); // globalDebugLevel) EYESIS_DCT.resetCLTKernels();
} }
SDFA_INSTANCE.showArrays( } else if (label.equals("Read CLT kernels")) {
iclt_data, if (!CLT_PARAMETERS.showDialog()) return;
(tilesX + 1) * CLT_PARAMETERS.transform_size, if (EYESIS_DCT == null){
(tilesY + 1) * CLT_PARAMETERS.transform_size, EYESIS_DCT = new EyesisDCT (
EYESIS_CORRECTIONS,
CORRECTION_PARAMETERS,
DCT_PARAMETERS);
}
String configPath=null;
if (EYESIS_CORRECTIONS.correctionsParameters.saveSettings) {
configPath=EYESIS_CORRECTIONS.correctionsParameters.selectResultsDirectory(
true, true,
DBG_IMP.getTitle()+"-ICLT-"+CLT_PARAMETERS.iclt_mask); true);
*/ if (configPath==null){
String msg="No results directory selected, command aborted";
System.out.println("Warning: "+msg);
IJ.showMessage("Warning",msg);
return;
}
configPath+=Prefs.getFileSeparator()+"autoconfig";
try {
saveTimestampedProperties(
configPath, // full path or null
null, // use as default directory if path==null
true,
PROPERTIES);
} catch (Exception e){
String msg="Failed to save configuration to "+configPath+", command aborted";
System.out.println("Error: "+msg);
IJ.showMessage("Error",msg);
return;
}
}
EYESIS_CORRECTIONS.initSensorFiles(DEBUG_LEVEL);
EYESIS_DCT.readCLTKernels(
CLT_PARAMETERS,
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
if (DEBUG_LEVEL > -1){
EYESIS_DCT.showCLTKernels(
THREADS_MAX,
UPDATE_STATUS, // update status info
DEBUG_LEVEL);
}
return; return;
// End of buttons code // End of buttons code
......
...@@ -929,7 +929,7 @@ public class ImageDtt { ...@@ -929,7 +929,7 @@ public class ImageDtt {
System.out.println("clt_shift():tilesX= "+tilesX); System.out.println("clt_shift():tilesX= "+tilesX);
System.out.println("clt_shift():tilesY= "+tilesY); System.out.println("clt_shift():tilesY= "+tilesY);
} }
/* /* Direct matrix Z1: X2 ~= Z1 * Shift
* {{+cc -sc -cs +ss}, * {{+cc -sc -cs +ss},
* {+sc +cc -ss -cs}, * {+sc +cc -ss -cs},
* {+cs -ss +cc -sc}, * {+cs -ss +cc -sc},
...@@ -1329,6 +1329,113 @@ public class ImageDtt { ...@@ -1329,6 +1329,113 @@ public class ImageDtt {
return dct_data_out; return dct_data_out;
} }
void clt_convert_double_kernel( // converts double resolution kernel
double [] src_kernel, //
double [] dst_kernel, // should be (2*dtt_size-1) * (2*dtt_size-1) +2 size - kernel and dx, dy to the nearest 1/2 pixels
int src_size, // 64
int dtt_size) // 8
{
int [] indices = {0,-src_size,-1,1,src_size,-src_size-1,-src_size+1,src_size-1,src_size+1};
double [] weights = {0.25,0.125,0.125,0.125,0.125,0.0625,0.0625,0.0625,0.0625};
int src_center = src_size / 2; // 32
// Find center
double sx=0.0, sy = 0.0, s = 0.0;
int indx = 0;
for (int i= -src_center; i < src_center; i++){
for (int j = -src_center; j < src_center; j++){
double d = src_kernel[indx++];
sx+= j*d;
sy+= i*d;
s += d;
}
}
int src_x = (int) Math.round(sx / s) + src_center;
int src_y = (int) Math.round(sy / s) + src_center;
// make sure selected area (2*dst_size-1) * (2*dst_size-1) fits into src_kernel, move center if not
if (src_x < 2 * dtt_size) src_x = 2 * dtt_size - 1; // 15
else if (src_x > (src_size - 2* dtt_size)) src_x = src_size - 2* dtt_size;
if (src_y < 2 * dtt_size) src_y = 2 * dtt_size - 1; // 15
else if (src_y > (src_size - 2* dtt_size)) src_y = src_size - 2* dtt_size;
indx = 0;
// downscale, copy
for (int i = -dtt_size + 1; i < dtt_size; i++){
int src_i = (src_y + 2 * i) * src_size + src_x;
for (int j = -dtt_size + 1; j < dtt_size; j++){
double d = 0.0;
for (int k = 0; k < indices.length; k++){
d += weights[k]*src_kernel[src_i + 2 * j + indices[k]];
}
dst_kernel[indx++] = d;
}
}
dst_kernel[indx++] = 0.5*(src_x - src_center);
dst_kernel[indx++] = 0.5*(src_y - src_center);
}
void clt_normalize_kernel( //
double [] kernel, // should be (2*dtt_size-1) * (2*dtt_size-1) +2 size (last 2 are not modified)
double [] window, // normalizes result kernel * window to have sum of elements == 1.0
final int dtt_size) // 8
{
double s = 0.0;
int indx = 0;
for (int i = -dtt_size + 1; i < dtt_size; i++){
int ai = (i < 0)? -i: i;
for (int j = -dtt_size + 1; j < dtt_size; j++){
int aj = (j < 0)? -j: j;
s += kernel[indx++] * window[ai*dtt_size+aj];
}
}
s = 1.0/s;
indx = 0;
for (int i = 0; i < (dtt_size * dtt_size); i++) {
kernel[indx++] *= s;
}
}
void clt_symmetrize_kernel( //
double [] kernel, // should be (2*dtt_size-1) * (2*dtt_size-1) +2 size (last 2 are not modified)
double [][] sym_kernels, // set of 4 SS, AS, SA, AA kdernels, each dtt_size * dtt_size (may have 5-th with center shift
final int dtt_size) // 8
{
int in_size = 2*dtt_size-1;
int dtt_size_m1 = dtt_size - 1;
int center = dtt_size_m1 * in_size + dtt_size_m1;
for (int i = 0; i < dtt_size; i++){
for (int j = 0; j < dtt_size; j++){
int indx0 = center - i * in_size - j;
int indx1 = center - i * in_size + j;
int indx2 = center + i * in_size - j;
int indx3 = center + i * in_size + j;
sym_kernels[0][i*dtt_size+j] = 0.25*( kernel[indx0] + kernel[indx1] + kernel[indx2] + kernel[indx3]);
if (j > 0) sym_kernels[1][i*dtt_size+j-1] = 0.25*(-kernel[indx0] + kernel[indx1] - kernel[indx2] + kernel[indx3]);
if (i > 0) sym_kernels[2][(i-1)*dtt_size+j] = 0.25*(-kernel[indx0] - kernel[indx1] + kernel[indx2] + kernel[indx3]);
if ((i > 0) && (j > 0)) sym_kernels[3][i*dtt_size+j] = 0.25*(-kernel[indx0] + kernel[indx1] - kernel[indx2] + kernel[indx3]);
}
sym_kernels[1][i*dtt_size + dtt_size_m1] = 0.0;
sym_kernels[2][dtt_size_m1*dtt_size + i] = 0.0;
sym_kernels[3][i*dtt_size + dtt_size_m1] = 0.0;
sym_kernels[3][dtt_size_m1*dtt_size + i] = 0.0;
}
}
void clt_dtt3_kernel( //
double [][] kernels, // set of 4 SS, AS, SA, AA kdernels, each dtt_size * dtt_size (may have 5-th with center shift
final int dtt_size, // 8
DttRad2 dtt)
{
if (dtt == null) dtt = new DttRad2(dtt_size);
for (int quad = 0; quad < 4; quad ++){
kernels[quad] = dtt.dttt_iiie(kernels[quad], quad, dtt_size);
}
}
public double [][][][] mdctScale( public double [][][][] mdctScale(
final ImageStack imageStack, final ImageStack imageStack,
final int subcamera, // final int subcamera, //
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment