CDMS/src/CDMS/Partridge/FieldFlattening
diff -u -r1.2 -r1.3
--- BlankImageFinder.java 11 Oct 2010 00:25:43 -0000 1.2
+++ BlankImageFinder.java 9 Apr 2011 17:22:14 -0000 1.3
@@ -11,10 +11,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
/**
* Find blank images by identifying images with small standard deviations
@@ -28,69 +25,91 @@
// Define the inputs and outputs - eventually it would be good to package
// this application and invoke these parameters from the command line
- String fbase = "c:/CDMS/IZipG47_Side1_PKG/IZipG47_Side1_PKG-";
+ String fbase = "c:/CDMS/MaxScanTestL09/MaxScanTestL09-";
int ifirst = 1;
- int ilast = 8585;
- String suffix = ".png";
- String outfile = "c:/CDMS/IZipv4_side1_blanks.txt";
+ int ilast = 138;
+ int nfile = ilast - ifirst + 1;
+ String suffix = ".BMP";
+ String outfile = "c:/CDMS/MaxScanTestL09_blanks.txt";
double imin = 100.;
- int nblank = 100;
+ int nblank = 10;
- // Create maps to hold the mean and sd calculations
- Map<String, Double> imean = new HashMap<String, Double>();
- Map<String, Double> isd = new HashMap<String, Double>();
+ // Create arrays to hold the mean and sd calculations
+ double[][] imean = new double[nfile][4];
+ double[][] isd = new double[nfile][4];
// Loop over the image files
- for (int ifile=ifirst; ifile<=ilast; ifile++) {
+ for (int file=0; file<nfile; file++) {
// Show progress in processing the image files
- if (ifile > 0 && (ifile % 100) == 0) System.out.println("Processing file "+ifile);
+ int ifile = ifirst + file;
+ if (file % 10 == 9) System.out.println("Processing file "+ifile);
// Open the image file with arbitrary origin and pixel size
String fname = fbase + ifile + suffix;
GeImage image = new GeImage(fname, 0., 0., 1., 1.);
PixelArray pixarray = image.getPixelArray();
- // Loop over pixels and find the intensity mean and standard deviation
- double itot = 0.;
- double i2tot = 0.;
- for (int row=0; row<pixarray.getNRow(); row++) {
- for (int col=0; col<pixarray.getNCol(); col++) {
- double intensity = image.getIntensity(row, col);
- itot += intensity;
- i2tot += intensity*intensity;
+ // Loop over quadrants
+ for (int quad=0; quad<4; quad++) {
+
+ // Loop over pixels and find the intensity mean and standard deviation
+ int nrow = pixarray.getNRow() / 2;
+ int ncol = pixarray.getNCol() / 2;
+ double itot = 0.;
+ double i2tot = 0.;
+ for (int row=0; row<nrow; row++) {
+ for (int col=0; col<ncol; col++) {
+
+ int irow = ImageQuadrant.getIRow(row, nrow, quad);
+ int icol = ImageQuadrant.getICol(col, ncol, quad);
+ double intensity = image.getIntensity(irow, icol);
+ itot += intensity;
+ i2tot += intensity*intensity;
+ }
}
- }
- int npixel = pixarray.getNRow() * pixarray.getNCol();
- double mean = itot / npixel;
- double sd = Math.sqrt(i2tot/npixel - mean*mean);
-
- // Save the mean and st dev in maps for later access
- imean.put(fname, mean);
- isd.put(fname, sd);
+ int npixel = nrow * ncol;
+ double mean = itot / npixel;
+ double sd = Math.sqrt(i2tot/npixel - mean*mean);
+
+ // Save the mean and st dev in arrays for later access
+ imean[file][quad] = mean;
+ isd[file][quad] = sd;
+ }
}
- // Make a list of sd for blank candidates, excluding those that have
- // low mean intensity (typically images outside the detector boundary)
- List<Double> sdlist = new ArrayList<Double>();
- for (Entry<String, Double> ent : imean.entrySet()) {
- if (ent.getValue() > imin) sdlist.add(isd.get(ent.getKey()));
- }
+ // Open the output file
+ PrintWriter out = new PrintWriter(new FileWriter(outfile));
+
+ // Loop over quadrants and find the best blank candidates
+ for (int quad = 0; quad<4; quad++) {
- // Sort the list and find the cutoff sd for our list of blank images
- Collections.sort(sdlist);
- double sdmax = sdlist.get(nblank-1);
-
- // Open the output file
- PrintWriter out = new PrintWriter(new FileWriter(outfile));
-
- // Output the desired number of images choosing those with the smallest sd
- for (String fname : imean.keySet()) {
- double mean = imean.get(fname);
- double sd = isd.get(fname);
- if (sd > sdmax || mean <= imin) continue;
- System.out.println("File "+fname+" selected - mean: "+mean+" sd: "+sd);
- out.println(fname);
+ // Make a list of sd for blank candidates, excluding those that have
+ // low mean intensity (typically images outside the detector boundary)
+ List<Double> sdlist = new ArrayList<Double>();
+ for (int file=0; file<nfile; file++) {
+ if (imean[file][quad] > imin) sdlist.add(isd[file][quad]);
+ }
+
+ // Sort the list and find the cutoff sd for our list of blank images
+ Collections.sort(sdlist);
+ double sdmax = sdlist.get(nblank-1);
+
+ // Output the desired number of images choosing those with the smallest sd
+ for (int file=0; file<nfile; file++) {
+
+ // Check if this is among the image files with the smallest sd
+ double mean = imean[file][quad];
+ double sd = isd[file][quad];
+ if (sd > sdmax || mean <= imin) continue;
+
+ // Construct the file name and write it and the quadrant out
+ int ifile = ifirst + file;
+ String fname = fbase + ifile + suffix;
+ System.out.println("File "+fname+" quadrant "+quad+
+ " selected - mean: "+mean+" sd: "+sd);
+ out.println(fname+" "+quad);
+ }
}
// Close the output file
CDMS/src/CDMS/Partridge/FieldFlattening
diff -u -r1.2 -r1.3
--- FieldFlattener.java 11 Oct 2010 00:25:43 -0000 1.2
+++ FieldFlattener.java 9 Apr 2011 17:22:14 -0000 1.3
@@ -13,9 +13,9 @@
import java.util.List;
/**
- * Takes a set of uniform blank images and creates a 2D field flattening map that
- * eliminates variations in intensity among the different image pixels. These
- * variations may arise from non-uniform illumination and/or camera response.
+ * Takes a set of uniform blank image quadrants and creates a 2D field flattening
+ * map that eliminates variations in intensity among the different image pixels.
+ * These variations may arise from non-uniform illumination and/or camera response.
*
* The BlankImageFinder class can be used to identify blank images and create
* the blank image file used by this class.
@@ -30,7 +30,7 @@
*/
public class FieldFlattener {
- private List<String> _fnames;
+ private List<ImageQuadrant> _quads;
private int _nrow;
private int _ncol;
private double[][] _rcor;
@@ -46,66 +46,55 @@
*/
public FieldFlattener(String blankfile, double cut) {
- // Read in the list of blank images
+ // Read in the list of blank quadrants and create the corresponding ImageQuadrants
ReadBlankFile(blankfile);
// Initialize the arrays for the image data and pixel descriptors
- int nfiles = _fnames.size();
- if (nfiles == 0) throw new RuntimeException("No blank images found");
- GeImage[] _images = new GeImage[nfiles];
- PixelArray[] _pixarray = new PixelArray[nfiles];
-
- // Loop over files and retrieve the image data
- for (int ifile=0; ifile<nfiles; ifile++) {
-
- // Get the image data and pixel array descriptor for this file
- String fname = _fnames.get(ifile);
- _images[ifile] = new GeImage(fname, 0., 0., 1., 1.);
- _pixarray[ifile] = _images[ifile].getPixelArray();
-
- // If this is the first image, save the image size
- if (ifile == 0) {
- _nrow = _pixarray[0].getNRow();
- _ncol = _pixarray[0].getNCol();
- }
-
- // Check that all images are the same size
- if (_pixarray[ifile].getNRow() != _nrow ||
- _pixarray[ifile].getNCol() != _ncol)
- throw new RuntimeException("Blank image files have different sizes");
- }
+ if (_quads.isEmpty()) throw new RuntimeException("No blank image quadrants found");
// Create arrays for the average color intensities of each pixel
- double ared[][] = new double[_nrow][_ncol];
- double agreen[][] = new double[_nrow][_ncol];
- double ablue[][] = new double[_nrow][_ncol];
-
- // Loop over all pixels
- for (int row=0; row<_nrow; row++) {
- for (int col=0; col<_ncol; col++) {
-
- // Arrays for the color intensities from each blank image
- int[] red = new int[nfiles];
- int[] blue = new int[nfiles];
- int[] green = new int[nfiles];
-
- // Loop over the blank images
- for (int ifile=0; ifile<nfiles; ifile++) {
-
- // Save the color intensities found for this pixel
- GeImage image = _images[ifile];
- int rgb = image.getRGB(row, col);
- red[ifile] = image.getRed(rgb);
- blue[ifile] = image.getBlue(rgb);
- green[ifile] = image.getGreen(rgb);
+ double ared[][][] = new double[_nrow][_ncol][4];
+ double agreen[][][] = new double[_nrow][_ncol][4];
+ double ablue[][][] = new double[_nrow][_ncol][4];
+ int nquad[] = {0, 0, 0, 0};
+
+ // Count the number of images for each quadrant
+ for (ImageQuadrant iquad : _quads) {
+ int quad = iquad.getQuadrant();
+ nquad[quad] += 1;
+ }
+
+ // Loop over the quadrants
+ for (int quad=0; quad<4; quad++) {
+
+ // Loop over all pixels in a quadrant
+ for (int row=0; row<_nrow; row++) {
+ for (int col=0; col<_ncol; col++) {
+
+ // Lists for the color intensities
+ List<Integer> red = new ArrayList<Integer>();
+ List<Integer> green = new ArrayList<Integer>();
+ List<Integer> blue = new ArrayList<Integer>();
+
+ // Loop over the ImageQuadrants
+ for (ImageQuadrant iquad : _quads) {
+
+ // Check that this is the quadrant we are interested in
+ if (iquad.getQuadrant() != quad) continue;
+
+ // Save the color intensities found for this pixel
+ red.add(iquad.getRed(row, col));
+ green.add(iquad.getGreen(row, col));
+ blue.add(iquad.getBlue(row, col));
+ }
+
+ // Average the color intensities for this pixel using a
+ // truncated mean that discards outliers since our blank
+ // images may not be flawless
+ ared[row][col][quad] = TruncatedMean(red, cut);
+ ablue[row][col][quad] = TruncatedMean(blue, cut);
+ agreen[row][col][quad] = TruncatedMean(green, cut);
}
-
- // Average the color intensities for this pixel using a
- // truncated mean that discards outliers since our blank
- // images may not be flawless
- ared[row][col] = TruncatedMean(red, cut);
- ablue[row][col] = TruncatedMean(blue, cut);
- agreen[row][col] = TruncatedMean(green, cut);
}
}
@@ -116,25 +105,33 @@
double bave = 0.;
for (int row=0; row<_nrow; row++) {
for (int col=0; col<_ncol; col++) {
- rave += ared[row][col] / (_nrow * _ncol);
- gave += agreen[row][col] / (_nrow * _ncol);
- bave += ablue[row][col] / (_nrow * _ncol);
+ for (int quad=0; quad<4; quad++) {
+ rave += ared[row][col][quad] / (4 * _nrow * _ncol);
+ gave += agreen[row][col][quad] / (4 * _nrow * _ncol);
+ bave += ablue[row][col][quad] / (4 * _nrow * _ncol);
+ }
}
}
// Create the arrays to hold the field flattening map
- _rcor = new double[_nrow][_ncol];
- _gcor = new double[_nrow][_ncol];
- _bcor = new double[_nrow][_ncol];
+ _rcor = new double[2*_nrow][2*_ncol];
+ _gcor = new double[2*_nrow][2*_ncol];
+ _bcor = new double[2*_nrow][2*_ncol];
// Calculate the correction factors to be applied to the
// color intensities for each image pixel
for (int row=0; row<_nrow; row++) {
for (int col=0; col<_ncol; col++) {
+ for (int quad=0; quad<4; quad++) {
- _rcor[row][col] = rave / ared[row][col];
- _gcor[row][col] = gave / agreen[row][col];
- _bcor[row][col] = bave / ablue[row][col];
+ // Get the row/col for the full 4-quadrant image
+ int irow = ImageQuadrant.getIRow(row, _nrow, quad);
+ int icol = ImageQuadrant.getICol(col, _ncol, quad);
+
+ _rcor[irow][icol] = rave / ared[row][col][quad];
+ _gcor[irow][icol] = gave / agreen[row][col][quad];
+ _bcor[irow][icol] = bave / ablue[row][col][quad];
+ }
}
}
}
@@ -181,8 +178,8 @@
*
* @return
*/
- public List<String> getBlankFileNames() {
- return _fnames;
+ public List<ImageQuadrant> getBlankImageQuadrants() {
+ return _quads;
}
/**
@@ -200,12 +197,12 @@
// Check that the dimensions of the image to be flattened are the
// same as the blank images used to develop the flattening correction
- if (pixarray.getNRow() != _nrow || pixarray.getNCol() != _ncol)
+ if (pixarray.getNRow() != 2*_nrow || pixarray.getNCol() != 2*_ncol)
throw new RuntimeException("Image sizes don't match");
// Loop over the image pixels
- for (int row=0; row<_nrow; row++) {
- for (int col=0; col<_ncol; col++) {
+ for (int row=0; row<2*_nrow; row++) {
+ for (int col=0; col<2*_ncol; col++) {
// Get the packed rgb color intensities for this pixel
int rgb = image.getRGB(row, col);
@@ -230,8 +227,9 @@
*/
private void ReadBlankFile(String blankfile) {
- // Initialize the list of file names
- _fnames = new ArrayList<String>();
+ // Initialize the list of file names and initialization flag
+ _quads = new ArrayList<ImageQuadrant>();
+ boolean first = true;
// Open the file with the list of blank images
FileReader fr;
@@ -252,10 +250,30 @@
// Loop over the blank file entries
try {
while (tok.nextToken() != StreamTokenizer.TT_EOF) {
+
// Get the next file name
if (tok.ttype != StreamTokenizer.TT_WORD) ParseError();
String fname = tok.sval;
- _fnames.add(fname);
+
+ // Get the quadrant
+ if (tok.nextToken() != StreamTokenizer.TT_NUMBER) ParseError();
+ int quad = (int) Math.round(tok.nval);
+
+ // Create a new ImageQuadrant and add it to the list
+ ImageQuadrant iquad = new ImageQuadrant(fname, quad);
+ _quads.add(iquad);
+
+ // Initialize / check the image size
+ if (first) {
+ _nrow = iquad.getNRow();
+ _ncol = iquad.getNCol();
+ first = false;
+ } else {
+ if (iquad.getNRow() != _nrow || iquad.getNCol() != _ncol)
+ throw new RuntimeException("Blank image files have different sizes");
+ }
+
+ // Check for the end of line token
if (tok.nextToken() != StreamTokenizer.TT_EOL) ParseError();
}
} catch (Exception ex) {
@@ -284,17 +302,20 @@
* @param cut truncation cut in units of the standard deviation
* @return truncated mean
*/
- private double TruncatedMean(int[] values, double cut) {
+ private double TruncatedMean(List<Integer> valuelist, double cut) {
// Get the number of values to average
- int nval = values.length;
+ int nval = valuelist.size();
- // Create and initialize the array of values to be excluded
+ // Create and initialize the arrays of values and exclusion flags
+ int[] values = new int[nval];
boolean[] exclude = new boolean[nval];
for (int i=0; i<nval; i++) {
+ values[i] = valuelist.get(i);
exclude[i] = false;
}
+
// Calculate the initial mean and stddev using all values
double mean = CalcMean(values, exclude);
double sd = CalcStdDev(values, mean, exclude);
CDMS/src/CDMS/Partridge/FieldFlattening
diff -u -r1.3 -r1.4
--- FieldFlattenerTest.java 12 Nov 2010 21:26:54 -0000 1.3
+++ FieldFlattenerTest.java 9 Apr 2011 17:22:14 -0000 1.4
@@ -19,11 +19,12 @@
public static void main(String[] args) throws IOException {
- String blankindexfile = "c:/CDMS/IZipv4_side1_blanks.txt";
+ String blankindexfile = "c:/CDMS/MaxScanTestL09_blanks.txt";
FieldFlattener flat = new FieldFlattener(blankindexfile, 2.0);
int ifile = 0;
AIDA aida = AIDA.defaultInstance();
- for (String fname : flat.getBlankFileNames()) {
+ for (ImageQuadrant iquad : flat.getBlankImageQuadrants()) {
+ String fname = iquad.getFileName();
GeImage image = new GeImage(fname, 0., 0., 1., 1.);
PixelArray pixarray = image.getPixelArray();
GeImage flatimage = flat.FlattenImage(image);
@@ -31,14 +32,17 @@
double i2sum = 0.;
double ifsum = 0.;
double i2fsum = 0.;
- int nrow = pixarray.getNRow();
- int ncol = pixarray.getNCol();
+ int nrow = iquad.getNRow();
+ int ncol = iquad.getNCol();
+ int quad = iquad.getQuadrant();
for (int row=0; row<nrow; row++) {
for (int col=0; col<ncol; col++) {
- double fintensity = flatimage.getIntensity(row, col);
+ int irow = ImageQuadrant.getIRow(row, nrow, quad);
+ int icol = ImageQuadrant.getICol(col, ncol, quad);
+ double fintensity = flatimage.getIntensity(irow, icol);
ifsum += fintensity;
i2fsum += fintensity*fintensity;
- double intensity = image.getIntensity(row, col);
+ double intensity = image.getIntensity(irow, icol);
isum += intensity;
i2sum += intensity*intensity;
aida.histogram1D("Flattened intensity", 256, 0., 256.).fill(fintensity);