package ini.trakem2.imaging.filters;
import ij.process.ColorProcessor;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import java.util.Map;
public class Normalize implements IFilter
{
protected double targetMean = 0;
protected double targetStdDev = 0;
public Normalize() {}
public Normalize(double targetMean, double targetStdDev) {
this.targetMean = targetMean;
this.targetStdDev = targetStdDev;
}
public Normalize(Map<String,String> params) {
try {
this.targetMean = Double.parseDouble(params.get("mean"));
this.targetStdDev = Integer.parseInt(params.get("stddev"));
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("Cannot create RankFilter!", nfe);
}
}
@Override
public ImageProcessor process(ImageProcessor ip) {
if (ip instanceof ColorProcessor) {
FloatProcessor r = normalize(ip.toFloat(0, null)),
g = normalize(ip.toFloat(1, null)),
b = normalize(ip.toFloat(2, null));
int[] p = new int[ip.getWidth() * ip.getHeight()];
ColorProcessor cp = new ColorProcessor(ip.getWidth(), ip.getHeight(), p);
final float[] rp = (float[]) r.getPixels(),
gp = (float[]) g.getPixels(),
bp = (float[]) b.getPixels();
for (int i=0; i<p.length; ++i) {
p[i] = ((int)rp[i] << 16) | ((int)gp[i] << 8) | (int)bp[i];
}
return cp;
}
final FloatProcessor fp = normalize((FloatProcessor)ip.convertToFloat());
if (ip instanceof FloatProcessor) {
return fp;
}
final int len = ip.getWidth() * ip.getHeight();
for (int i=0; i<len; ++i) {
ip.setf(i, fp.get(i));
}
return ip;
}
private FloatProcessor normalize(FloatProcessor fp) {
double s = 0;
final int len = fp.getWidth() * fp.getHeight();
final float[] p = (float[]) fp.getPixels();
// Compute mean
for (int i=0; i<len; ++i) s += p[i];
final double mean = s / len;
// Compute stdDev
s = 0;
for (int i=0; i<len; ++i) s += Math.pow(p[i] - mean, 2);
//final double stdDev = Math.sqrt(s / (len - 1));
//final double K = targetStdDev / stdDev;
final double K = targetStdDev / Math.sqrt(s / (len - 1)); // save one register
for (int i=0; i<len; ++i) {
//p[i] = (float)((((p[i] - mean) / stdDev) * targetStdDev) + targetMean);
p[i] = (float)(((p[i] - mean) * K) + targetMean); // save one division
}
return fp;
}
@Override
public String toXML(String indent) {
return new StringBuilder(indent)
.append("<t2_filter class=\"").append(getClass().getName())
.append("\" mean=\"").append(targetMean)
.append("\" stddev=\"").append(targetStdDev)
.append("\" />\n").toString();
}
@Override
public boolean equals(final Object o) {
if (null == o) return false;
if (o.getClass() == getClass()) {
final Normalize nr = (Normalize)o;
return targetMean == nr.targetMean && targetStdDev == nr.targetStdDev;
}
return false;
}
}