use of ij.process.ImageProcessor in project GDSC-SMLM by aherbert.
the class PSFCreator method getFWHM.
private double getFWHM(ImageStack psf, int maxz) {
// Extract the line profile through the stack
int size = psf.getWidth();
int cx = size / 2;
// Even PSFs have the middle in the centre of two pixels
int cx2 = (size % 2 == 0) ? cx - 1 : cx;
double[] p0 = new double[size];
double[] p1 = new double[size];
double[] p2 = new double[size];
double[] p3 = new double[size];
double[] p4 = new double[size];
ImageProcessor ip = psf.getProcessor(maxz);
for (int i = 0, j = size - 1; i < size; i++, j--) {
p0[i] = i;
p1[i] = (ip.getf(i, cx) + ip.getf(i, cx2)) / 2.0;
p2[i] = (ip.getf(cx, i) + ip.getf(cx2, i)) / 2.0;
p3[i] = ip.getf(i, i);
p4[i] = ip.getf(i, j);
}
// Diagonals need to be scaled to the appropriate distance.
return (getFWHM(p0, p1) + getFWHM(p0, p2) + Math.sqrt(2) * getFWHM(p0, p3) + Math.sqrt(2) * getFWHM(p0, p4)) / 4.0;
}
use of ij.process.ImageProcessor in project GDSC-SMLM by aherbert.
the class ResultsImageSampler method getSample.
/**
* Gets the sample image. The image is a stack of the samples with an overlay of the localisation positions. The
* info property is set with details of the localisations and the image is calibrated.
*
* @param nNo
* the number of samples with no localisations
* @param nLow
* the number of samples with low localisations
* @param nHigh
* the number of samples with high localisations
* @return the sample image (could be null if no samples were made)
*/
public ImagePlus getSample(int nNo, int nLow, int nHigh) {
ImageStack out = new ImageStack(size, size);
if (!isValid())
return null;
list.clearf();
// empty
for (int i : Random.sample(nNo, no.length, r)) list.add(ResultsSample.createEmpty(no[i]));
// low
for (int i : Random.sample(nLow, lower, r)) list.add(data[i]);
// high
for (int i : Random.sample(nHigh, upper, r)) list.add(data[i + lower]);
if (list.isEmpty())
return null;
double nmPerPixel = 1;
if (results.getCalibration() != null) {
Calibration calibration = results.getCalibration();
if (calibration.hasNmPerPixel()) {
nmPerPixel = calibration.getNmPerPixel();
}
}
// Sort descending by number in the frame
ResultsSample[] sample = list.toArray(new ResultsSample[list.size()]);
Arrays.sort(sample, rcc);
int[] xyz = new int[3];
Rectangle stackBounds = new Rectangle(stack.getWidth(), stack.getHeight());
Overlay overlay = new Overlay();
float[] ox = new float[10], oy = new float[10];
StringBuilder sb = new StringBuilder();
if (nmPerPixel == 1)
sb.append("Sample X Y Z Signal\n");
else
sb.append("Sample X(nm) Y(nm) Z(nm) Signal\n");
for (ResultsSample s : sample) {
getXYZ(s.index, xyz);
// Construct the region to extract
Rectangle target = new Rectangle(xyz[0], xyz[1], size, size);
target = target.intersection(stackBounds);
if (target.width == 0 || target.height == 0)
continue;
// Extract the frame
int slice = xyz[2];
ImageProcessor ip = stack.getProcessor(slice);
// Cut out the desired pixels (some may be blank if the block overruns the source image)
ImageProcessor ip2 = ip.createProcessor(size, size);
for (int y = 0; y < target.height; y++) for (int x = 0, i = y * size, index = (y + target.y) * ip.getWidth() + target.x; x < target.width; x++, i++, index++) {
ip2.setf(i, ip.getf(index));
}
int size = s.size();
if (size > 0) {
int position = out.getSize() + 1;
// Create an ROI with the localisations
for (int i = 0; i < size; i++) {
PeakResult p = s.list.get(i);
ox[i] = p.getXPosition() - xyz[0];
oy[i] = p.getYPosition() - xyz[1];
sb.append(position).append(' ');
sb.append(Utils.rounded(ox[i] * nmPerPixel)).append(' ');
sb.append(Utils.rounded(oy[i] * nmPerPixel)).append(' ');
// Z can be stored in the error field
sb.append(Utils.rounded(p.error * nmPerPixel)).append(' ');
sb.append(Utils.rounded(p.getSignal())).append('\n');
}
PointRoi roi = new PointRoi(ox, oy, size);
roi.setPosition(position);
overlay.add(roi);
}
out.addSlice(String.format("Frame=%d @ %d,%d px (n=%d)", slice, xyz[0], xyz[1], size), ip2.getPixels());
}
if (out.getSize() == 0)
return null;
ImagePlus imp = new ImagePlus("Sample", out);
imp.setOverlay(overlay);
// Note: Only the info property can be saved to a TIFF file
imp.setProperty("Info", sb.toString());
if (nmPerPixel != 1) {
ij.measure.Calibration cal = new ij.measure.Calibration();
cal.setUnit("nm");
cal.pixelHeight = cal.pixelWidth = nmPerPixel;
imp.setCalibration(cal);
}
return imp;
}
use of ij.process.ImageProcessor in project GDSC-SMLM by aherbert.
the class ImageConverter method getDoubleData.
/**
* Get the data from the image as a double array (include cropping to the ROI). Data is duplicated if the
* input already a double array.
* <p>
* Allows reuse of an existing buffer if provided. This will not be truncated if it is larger than the
* ImageProcessor ROI bounds. If smaller then a new buffer will be created.
*
* @param oPixels
* @param width
* @param height
* @param bounds
* @param buffer
* @return The double array data
*/
public static double[] getDoubleData(final Object oPixels, final int width, final int height, final Rectangle bounds, double[] buffer) {
if (oPixels == null)
return null;
if (oPixels instanceof float[]) {
float[] pixels = (float[]) oPixels;
if (bounds != null && (bounds.x != 0 || bounds.y != 0 || bounds.width != width || bounds.height != height)) {
double[] pixels2 = allocate(buffer, bounds.width * bounds.height);
for (int ys = bounds.y; ys < bounds.y + bounds.height; ys++) {
int offset1 = (ys - bounds.y) * bounds.width;
int offset2 = ys * width + bounds.x;
for (int xs = 0; xs < bounds.width; xs++) pixels2[offset1++] = pixels[offset2++];
}
return pixels2;
} else {
double[] pixels2 = allocate(buffer, pixels.length);
for (int i = 0; i < pixels.length; i++) pixels2[i] = pixels[i];
return pixels2;
}
} else if (oPixels instanceof short[]) {
short[] pixels = (short[]) oPixels;
if (bounds != null && (bounds.x != 0 || bounds.y != 0 || bounds.width != width || bounds.height != height)) {
double[] pixels2 = allocate(buffer, bounds.width * bounds.height);
for (int ys = bounds.y; ys < bounds.y + bounds.height; ys++) {
int offset1 = (ys - bounds.y) * bounds.width;
int offset2 = ys * width + bounds.x;
for (int xs = 0; xs < bounds.width; xs++) pixels2[offset1++] = pixels[offset2++] & 0xffff;
}
return pixels2;
} else {
double[] pixels2 = allocate(buffer, pixels.length);
for (int i = 0; i < pixels.length; i++) pixels2[i] = pixels[i] & 0xffff;
return pixels2;
}
} else if (oPixels instanceof byte[]) {
byte[] pixels = (byte[]) oPixels;
if (bounds != null && (bounds.x != 0 || bounds.y != 0 || bounds.width != width || bounds.height != height)) {
double[] pixels2 = allocate(buffer, bounds.width * bounds.height);
for (int ys = bounds.y; ys < bounds.y + bounds.height; ys++) {
int offset1 = (ys - bounds.y) * bounds.width;
int offset2 = ys * width + bounds.x;
for (int xs = 0; xs < bounds.width; xs++) pixels2[offset1++] = pixels[offset2++] & 0xff;
}
return pixels2;
} else {
double[] pixels2 = allocate(buffer, pixels.length);
for (int i = 0; i < pixels.length; i++) pixels2[i] = pixels[i] & 0xff;
return pixels2;
}
} else if (oPixels instanceof int[]) {
// The default processing
ImageProcessor ip = new ColorProcessor(width, height, (int[]) oPixels);
ip.setRoi(bounds);
FloatProcessor fp = ip.crop().toFloat(0, null);
return (double[]) fp.getPixels();
}
return null;
}
use of ij.process.ImageProcessor in project GDSC-SMLM by aherbert.
the class FIRE method createImages.
/**
* Creates the images to use for the FIRE calculation. This must be called after
* {@link #initialise(MemoryPeakResults, MemoryPeakResults)}.
*
* @param fourierImageScale
* the fourier image scale (set to zero to auto compute)
* @param imageSize
* the image size
* @param useSignal
* Use the localisation signal to weight the intensity. The default uses a value of 1 per localisation.
* @return the fire images
*/
public FireImages createImages(double fourierImageScale, int imageSize, boolean useSignal) {
if (results == null)
return null;
final SignalProvider signalProvider = (useSignal && (results.getHead().getSignal() > 0)) ? new PeakSignalProvider() : new FixedSignalProvider();
// Draw images using the existing IJ routines.
Rectangle bounds = new Rectangle(0, 0, (int) Math.ceil(dataBounds.getWidth()), (int) Math.ceil(dataBounds.getHeight()));
boolean weighted = true;
boolean equalised = false;
double imageScale;
if (fourierImageScale <= 0) {
double size = FastMath.max(bounds.width, bounds.height);
if (size <= 0)
size = 1;
imageScale = imageSize / size;
} else
imageScale = fourierImageScale;
IJImagePeakResults image1 = ImagePeakResultsFactory.createPeakResultsImage(ResultsImage.NONE, weighted, equalised, "IP1", bounds, 1, 1, imageScale, 0, ResultsMode.ADD);
image1.setDisplayImage(false);
image1.begin();
IJImagePeakResults image2 = ImagePeakResultsFactory.createPeakResultsImage(ResultsImage.NONE, weighted, equalised, "IP2", bounds, 1, 1, imageScale, 0, ResultsMode.ADD);
image2.setDisplayImage(false);
image2.begin();
float minx = (float) dataBounds.getX();
float miny = (float) dataBounds.getY();
if (this.results2 != null) {
// Two image comparison
for (PeakResult p : results) {
float x = p.getXPosition() - minx;
float y = p.getYPosition() - miny;
image1.add(x, y, signalProvider.getSignal(p));
}
for (PeakResult p : results2) {
float x = p.getXPosition() - minx;
float y = p.getYPosition() - miny;
image2.add(x, y, signalProvider.getSignal(p));
}
} else {
// Block sampling.
// Ensure we have at least 2 even sized blocks.
int blockSize = Math.min(results.size() / 2, Math.max(1, FIRE.blockSize));
int nBlocks = (int) Math.ceil((double) results.size() / blockSize);
while (nBlocks <= 1 && blockSize > 1) {
blockSize /= 2;
nBlocks = (int) Math.ceil((double) results.size() / blockSize);
}
if (nBlocks <= 1)
// This should not happen since the results should contain at least 2 localisations
return null;
if (blockSize != FIRE.blockSize)
IJ.log(TITLE + " Warning: Changed block size to " + blockSize);
int i = 0;
int block = 0;
PeakResult[][] blocks = new PeakResult[nBlocks][blockSize];
for (PeakResult p : results) {
if (i == blockSize) {
block++;
i = 0;
}
blocks[block][i++] = p;
}
// Truncate last block
blocks[block] = Arrays.copyOf(blocks[block], i);
final int[] indices = Utils.newArray(nBlocks, 0, 1);
if (randomSplit)
MathArrays.shuffle(indices);
for (int index : indices) {
// Split alternating so just rotate
IJImagePeakResults image = image1;
image1 = image2;
image2 = image;
for (PeakResult p : blocks[index]) {
float x = p.getXPosition() - minx;
float y = p.getYPosition() - miny;
image.add(x, y, signalProvider.getSignal(p));
}
}
}
image1.end();
ImageProcessor ip1 = image1.getImagePlus().getProcessor();
image2.end();
ImageProcessor ip2 = image2.getImagePlus().getProcessor();
if (maxPerBin > 0 && signalProvider instanceof FixedSignalProvider) {
// We can eliminate over-sampled pixels
for (int i = ip1.getPixelCount(); i-- > 0; ) {
if (ip1.getf(i) > maxPerBin)
ip1.setf(i, maxPerBin);
if (ip2.getf(i) > maxPerBin)
ip2.setf(i, maxPerBin);
}
}
return new FireImages(ip1, ip2, nmPerPixel / imageScale);
}
use of ij.process.ImageProcessor in project GDSC-SMLM by aherbert.
the class ImageBackground method applyBlur.
private ImageProcessor applyBlur(ImageProcessor median) {
ImageProcessor blur = median;
if (sigma > 0) {
blur = median.duplicate();
GaussianBlur gb = new GaussianBlur();
gb.blurGaussian(blur, sigma, sigma, 0.0002);
}
return blur;
}
Aggregations