Commit 685a0667 authored by Andrey Filippov's avatar Andrey Filippov

implemented defected pixels processing during image correction

parent eeeeee41
......@@ -9775,8 +9775,8 @@ if (MORE_BUTTONS) {
5.0, // gapWidth,
2, // algorithmNumber,
6, // numInBase2, // number of neighbors (of 8) to use as a base if they all agree
3.0, // binWidth2, // absolute
5.0, // gapWidth2, // absolute
2.0, // binWidth2, // absolute
4.0, // gapWidth2, // absolute - will produce minimal defect of 5.0 (binWidth2/2+gapWidth2)
true, // processHot,
true, // processCold,
true, // updateSensorCalibrationFiles
......
......@@ -38,6 +38,8 @@ public class EyesisCorrectionParameters {
public boolean swapSubchannels01= true; // false; // (false: 0-1-2, true - 1-0-2)
public boolean split= true;
public boolean vignetting= true;
public boolean pixelDefects= true;
public double pixelDefectsThreshold= 8.0; // normally none with less than 5.0 are stored?
public boolean debayer= true;
public boolean showDebayerEnergy = false;
public boolean saveDebayerEnergy = true;
......@@ -103,6 +105,8 @@ public class EyesisCorrectionParameters {
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"split",this.split+"");
properties.setProperty(prefix+"vignetting",this.vignetting+"");
properties.setProperty(prefix+"pixelDefects",this.pixelDefects+"");
properties.setProperty(prefix+"pixelDefectsThreshold",this.pixelDefectsThreshold+"");
properties.setProperty(prefix+"debayer",this.debayer+"");
properties.setProperty(prefix+"showDebayerEnergy",this.showDebayerEnergy+"");
properties.setProperty(prefix+"saveDebayerEnergy",this.saveDebayerEnergy+"");
......@@ -176,6 +180,8 @@ public class EyesisCorrectionParameters {
public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"split")!=null) this.split=Boolean.parseBoolean(properties.getProperty(prefix+"split"));
if (properties.getProperty(prefix+"vignetting")!=null) this.vignetting=Boolean.parseBoolean(properties.getProperty(prefix+"vignetting"));
if (properties.getProperty(prefix+"pixelDefects")!=null) this.pixelDefects=Boolean.parseBoolean(properties.getProperty(prefix+"pixelDefects"));
if (properties.getProperty(prefix+"pixelDefectsThreshold")!=null) this.pixelDefectsThreshold=Double.parseDouble(properties.getProperty(prefix+"pixelDefectsThreshold"));
if (properties.getProperty(prefix+"debayer")!=null) this.debayer=Boolean.parseBoolean(properties.getProperty(prefix+"debayer"));
if (properties.getProperty(prefix+"showDebayerEnergy")!=null) this.showDebayerEnergy=Boolean.parseBoolean(properties.getProperty(prefix+"showDebayerEnergy"));
if (properties.getProperty(prefix+"saveDebayerEnergy")!=null) this.saveDebayerEnergy=Boolean.parseBoolean(properties.getProperty(prefix+"saveDebayerEnergy"));
......@@ -254,6 +260,8 @@ public class EyesisCorrectionParameters {
GenericDialog gd = new GenericDialog(title);
gd.addCheckbox ("Splt into Bayer stack (if false will exit)", this.split);
gd.addCheckbox ("Apply vignetting/color correction to source files",this.vignetting);
gd.addCheckbox ("Replace hot/warm/cold pixels with average of neighbors",this.pixelDefects);
gd.addNumericField("Pixel difference thershold to consider it \"bad\" on 255.0 scale (0 - use all)", this.pixelDefectsThreshold, 2,6,"8.0");
String [] choices={"none","absolute","relative"};
if (this.exposureCorrectionMode<0) this.exposureCorrectionMode=0;
else if (this.exposureCorrectionMode>=choices.length) this.exposureCorrectionMode=choices.length-1;
......@@ -338,13 +346,13 @@ public class EyesisCorrectionParameters {
WindowTools.addScrollBars(gd);
gd.showDialog();
if (gd.wasCanceled()) return false;
this.split= gd.getNextBoolean();
this.split= gd.getNextBoolean();
this.vignetting= gd.getNextBoolean();
this.pixelDefects= gd.getNextBoolean();
this.pixelDefectsThreshold= gd.getNextNumber();
this.exposureCorrectionMode= gd.getNextChoiceIndex();
this.referenceExposure=0.001*gd.getNextNumber();
this.relativeExposure= gd.getNextNumber();
this.debayer= gd.getNextBoolean();
this.showDebayerEnergy= gd.getNextBoolean();
this.saveDebayerEnergy= gd.getNextBoolean();
......
......@@ -53,6 +53,9 @@ public class EyesisCorrections {
public EyesisCorrectionParameters.CorrectionParameters correctionsParameters=null;
public boolean [] usedChannels;
public float [][] channelVignettingCorrection=null;
public int [][][] defectsXY=null; // per each channel: pixel defects coordinates list (starting with worst)
public double [][] defectsDiff=null; // per each channel: pixel defects value (diff from average of neighbors), matching defectsXY
public int [][] channelWidthHeight=null;
public ImagePlus [] imageNoiseGains=null;
public String [] sharpKernelPaths=null;
......@@ -392,9 +395,14 @@ public class EyesisCorrections {
public void createChannelVignetting(){
this.channelWidthHeight=new int [this.usedChannels.length][];
this.channelVignettingCorrection=new float [this.usedChannels.length][];
this.defectsXY=new int [this.usedChannels.length][][];
this.defectsDiff=new double [this.usedChannels.length][];
for (int nChn=0;nChn< this.usedChannels.length; nChn++){
this.channelWidthHeight[nChn]=null;
this.channelVignettingCorrection[nChn]=null;
this.defectsXY[nChn]=null;
this.defectsDiff[nChn]=null;
}
int [][] bayer={{1,0},{2,1}}; // GR/BG
ImagePlus imp=null,imp_composite=null;
......@@ -455,11 +463,29 @@ public class EyesisCorrections {
this.channelWidthHeight[srcChannel][1],
bayer);
if (this.debugLevel>0){
System.out.println("Creating vignetting info for channel "+srcChannel+
System.out.println("Created vignetting info for channel "+srcChannel+
" subchannel="+subChannel+" ("+
correctionsParameters.getSourcePaths()[nFile]+")");
System.out.println("imageWidth= "+this.channelWidthHeight[srcChannel][0]+" imageHeight="+this.channelWidthHeight[srcChannel][1]);
}
this.defectsXY[srcChannel]=this.pixelMapping.getDefectsXY(srcChannel);
this.defectsDiff[srcChannel]=this.pixelMapping.getDefectsDiff(srcChannel);
if (this.debugLevel>0){
if (this.defectsXY[srcChannel]==null){
System.out.println("No pixel defects info is availabele for channel "+srcChannel);
} else {
System.out.println("Extracted "+this.defectsXY[srcChannel].length+" pixel outlayers for channel "+srcChannel+
" (x:y:difference");
int numInLine=8;
for (int i=0;i<this.defectsXY[srcChannel].length;i++){
System.out.print(this.defectsXY[srcChannel][0]+":"+this.defectsXY[srcChannel][1]);
if ((this.defectsDiff[srcChannel]!=null) && (this.defectsDiff[srcChannel].length>i)){
System.out.print(":"+IJ.d2s(this.defectsDiff[srcChannel][i],3)+" ");
}
if (((i%numInLine)==(numInLine-1)) || (i == (this.defectsXY[srcChannel].length-1))) System.out.println();
}
}
}
}
}
}
......@@ -825,7 +851,38 @@ public class EyesisCorrections {
return imp_warped;
}
public int correctDefects(
ImagePlus imp,
int channel,
int debugLevel){
int numApplied=0;
if (this.correctionsParameters.pixelDefects && (this.defectsXY!=null)&& (this.defectsXY[channel]!=null)){
// apply pixel correction
float [] pixels=(float []) imp.getProcessor().getPixels();
int width=imp.getWidth();
int height=pixels.length/width;
int [] dirsRB={2,2*width,-2,-2*width};
int [] dirsG={width+1,width-1,-width-1,-width+1};
for (int i=0;i<this.defectsXY[channel].length;i++){
if ( // difference provided and is smaller than threshold
(this.defectsDiff != null) &&
(this.defectsDiff[channel]!=null) &&
(this.defectsDiff[channel].length>i) &&
(Math.abs(this.defectsDiff[channel][i])<this.correctionsParameters.pixelDefectsThreshold)) break;
int x=this.defectsXY[channel][i][0];
int y=this.defectsXY[channel][i][1];
int index=x+y*width;
int [] dirs=(((x^y)&1)==0)?dirsG:dirsRB;
// do not bother to correct border pixels
if ((x<2) || (y<2) || (x>(width-3)) || (y>height-3)) continue;
double s=0.0;
for (int dir=0;dir<dirs.length;dir++) s+=pixels[index+dirs[dir]];
pixels[index]=(float) (s/dirs.length);
numApplied++;
}
}
return numApplied;
}
public ImagePlus processChannelImage(
......@@ -852,6 +909,16 @@ public class EyesisCorrections {
// int channel= Integer.parseInt((String) imp_src.getProperty("channel"));
int channel= (Integer) imp_src.getProperty("channel");
String path= (String) imp_src.getProperty("path");
if (this.correctionsParameters.pixelDefects && (this.defectsXY!=null)&& (this.defectsXY[channel]!=null)){
// apply pixel correction
int numApplied= correctDefects(
imp_src,
channel,
debugLevel);
if ((debugLevel>0) && (numApplied>0)) { // reduce verbosity after verified defect correction works
System.out.println("Corrected "+numApplied+" pixels in "+path);
}
}
if (this.correctionsParameters.vignetting){
if ((this.channelVignettingCorrection==null) || (channel<0) || (channel>=this.channelVignettingCorrection.length) || (this.channelVignettingCorrection[channel]==null)){
System.out.println("No vignetting data for channel "+channel);
......
......@@ -177,7 +177,19 @@ public class PixelMapping {
height,
bayer);
}
public int [][] getDefectsXY(
int channel){
if ((this.sensors == null) || (channel<0) && (channel>=this.sensors.length))return null;
return this.sensors[channel].getDefectsXY();
}
public double[] getDefectsDiff(
int channel){
if ((this.sensors == null) || (channel<0) && (channel>=this.sensors.length))return null;
return this.sensors[channel].getDefectsDiff();
}
///SensorData
/*
public float [] getBayerFlatFieldFloat(
......@@ -15550,6 +15562,10 @@ public class PixelMapping {
public int debugLevel=1;
public DirectMap directMap=null;
public EquirectangularMap equirectangularMap=null;
public int [][] defectsXY=null; // pixel defects coordinates list (starting with worst)
public double [] defectsDiff=null; // pixel defects value (diff from average of neighbors), matching defectsXY
// TODO - add option to generate individual flat projections
public InterSensor interSensor=null; // multiple sensors may have the same instance of the interSensor
......@@ -15715,6 +15731,12 @@ public class PixelMapping {
}
return corrScale;
}
public int [][] getDefectsXY(){
return this.defectsXY;
}
public double [] getDefectsDiff(){
return this.defectsDiff;
}
public class DirectMap{
public int width;
......@@ -16048,6 +16070,23 @@ public class PixelMapping {
for (int n=0;n<pixels.length;n++) for (int i= 0;i<this.pixelCorrection[0].length;i++){
this.pixelCorrection[n][i]=pixels[n][i];
}
if (imp.getProperty("defects")!=null) {
String sDefects=(String) imp.getProperty("defects");
String [] asDefects=sDefects.trim().split(" ");
this.defectsXY=new int [asDefects.length][2];
this.defectsDiff=new double [asDefects.length];
for (int i=0;i<asDefects.length;i++) {
String [] stDefect=asDefects[i].split(":");
this.defectsXY[i][0]=Integer.parseInt(stDefect[0]);
this.defectsXY[i][1]=Integer.parseInt(stDefect[1]);
this.defectsDiff[i]=Double.parseDouble(stDefect[2]);
}
} else {
this.defectsXY=null;
this.defectsDiff=null;
}
// now mask
}
/**
......
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