/** * Calculate the Rand index between some 2D original labels and the corresponding proposed labels. * Both image are binarized. We follow the definition of Rand index as described by William M. * Rand \cite{Rand71}. * * <p>BibTeX: * * <pre> * @article{Rand71, * author = {William M. Rand}, * title = {Objective criteria for the evaluation of clustering methods}, * journal = {Journal of the American Statistical Association}, * year = {1971}, * volume = {66}, * number = {336}, * pages = {846--850}, * doi = {10.2307/2284239) * } * </pre> * * @param label 2D image with the original labels * @param proposal 2D image with the proposed labels * @param binaryThreshold threshold value to binarize the input images * @return rand index value and derived statistics */ public ClassificationStatistics randIndexStats( ImageProcessor label, ImageProcessor proposal, double binaryThreshold) { // Binarize inputs ByteProcessor binaryLabel = new ByteProcessor(label.getWidth(), label.getHeight()); ByteProcessor binaryProposal = new ByteProcessor(label.getWidth(), label.getHeight()); for (int x = 0; x < label.getWidth(); x++) for (int y = 0; y < label.getHeight(); y++) { binaryLabel.set(x, y, label.getPixelValue(x, y) > binaryThreshold ? 255 : 0); binaryProposal.set(x, y, proposal.getPixelValue(x, y) > binaryThreshold ? 255 : 0); } // Find components ShortProcessor components1 = (ShortProcessor) Utils.connectedComponents(new ImagePlus("binary labels", binaryLabel), 4) .allRegions .getProcessor(); ShortProcessor components2 = (ShortProcessor) Utils.connectedComponents(new ImagePlus("proposal labels", binaryProposal), 4) .allRegions .getProcessor(); return getRandIndexStats(components1, components2); }
public void run(String arg) { int[] wList = WindowManager.getIDList(); if (wList == null) { IJ.error("No images are open."); return; } double thalf = 0.5; boolean keep; GenericDialog gd = new GenericDialog("Bleach correction"); gd.addNumericField("t½:", thalf, 1); gd.addCheckbox("Keep source stack:", true); gd.showDialog(); if (gd.wasCanceled()) return; long start = System.currentTimeMillis(); thalf = gd.getNextNumber(); keep = gd.getNextBoolean(); if (keep) IJ.run("Duplicate...", "title='Bleach corrected' duplicate"); ImagePlus imp1 = WindowManager.getCurrentImage(); int d1 = imp1.getStackSize(); double v1, v2; int width = imp1.getWidth(); int height = imp1.getHeight(); ImageProcessor ip1, ip2, ip3; int slices = imp1.getStackSize(); ImageStack stack1 = imp1.getStack(); ImageStack stack2 = imp1.getStack(); int currentSlice = imp1.getCurrentSlice(); for (int n = 1; n <= slices; n++) { ip1 = stack1.getProcessor(n); ip3 = stack1.getProcessor(1); ip2 = stack2.getProcessor(n); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { v1 = ip1.getPixelValue(x, y); v2 = ip3.getPixelValue(x, y); // =B8/(EXP(-C$7*A8)) v1 = (v1 / Math.exp(-n * thalf)); ip2.putPixelValue(x, y, v1); } } IJ.showProgress((double) n / slices); IJ.showStatus(n + "/" + slices); } // stack2.show(); imp1.updateAndDraw(); }
// get a pixel value; returns Float.NaN if outside the field. private float getPixel(int x, int y) { if (x < 0 || x >= width || y < 0 || y >= height) return Float.NaN; if (bpixels != null) return bpixels[y * width + x] & 0xff; else if (spixels != null) return spixels[y * width + x] & 0xffff; else if (fpixels != null) return fpixels[y * width + x]; else if (exactPixelValue) // RGB for exact match return cpixels[y * width + x] & 0xffffff; // don't care for upper byte else // gray value of RGB return ip.getPixelValue(x, y); }
void avg_col(ImageProcessor ip) { float sum; // sum of pixel values column float avg; // average pixel value of a column float[] sliceavgs = new float[width]; // means across columns of one slice int sliceNumber = ip.getSliceNumber() - 1; // slice number for (int x = 0; x < width; x += 1) { sum = 0; // reset with each column avg = 0; // reset with each column for (int y = 0; y < height; y += 1) { sum = sum + ip.getPixelValue(x, y); } avg = sum / height; sliceavgs[x] = avg; // building array of means } this.slicecols[sliceNumber] = sliceavgs; // add this slice's means to array }
public OpenCLVolumeRenderer(ImagePlus image) { super( new byte[image.getWidth() * image.getHeight() * image.getStackSize() / image.getNFrames()], image.getWidth(), image.getHeight(), image.getStackSize() / image.getNFrames(), false); transferFunc = new float[] { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; minmax = ImageUtil.minAndMaxOfImageProcessor(image); minmax[1] *= 1.05; if (image.getNFrames() == 1) multiFrameMode = false; else multiFrameMode = true; nFrames = image.getNFrames(); // Create the image array clImages = new ArrayList<CLImage3d<IntBuffer>>(image.getNFrames()); // rewrite imagePlus container into nFrames single byte volumes volumes = new byte[image.getNFrames()][volumeSize[2] * volumeSize[1] * volumeSize[0]]; for (int n = 0; n < image.getNFrames(); n++) { for (int k = 0; k < volumeSize[2]; k++) { ImageProcessor img = image.getStack().getProcessor((n * volumeSize[2]) + k + 1); for (int i = 0; i < image.getWidth(); i++) { for (int j = 0; j < image.getHeight(); j++) { setVoxel(volumes[n], i, j, k, img.getPixelValue(i, j)); } } } } initialized = false; // System.out.println("init"); frame.setTitle("Volume: " + image.getTitle()); }
/** * Returns image in units of adjusted count-rate (Klimpki et al., 2016), i.e. compensated for * laser power and dwell time. If requested, non-linearities in laser-power compensation are * considered. * * @param img Input image * @param dwell_time Pixel dwell time, unit will match rate (i.e. us --> MHz) * @param laser_power Percentage laser power, * @param laser_exponent Exponent of laser-power compensation non-linearity, referred to 10% * percentage laser power. Equals 0.0 for perfect linearity * @return */ public static ImagePlus getAdjustedCountrateImage( ImagePlus img, double dwell_time, double laser_power, double laser_exponent) { boolean silent = (IJ.getInstance() == null); int nX = img.getWidth(); int nY = img.getHeight(); int nSlices = img.getNSlices(); int nFrames = img.getNFrames(); int nChannels = img.getNChannels(); ImageStack resIms = new ImageStack(nX, nY); FloatProcessor fp; ImageProcessor ip1; int total = nSlices * nFrames * nChannels; double prog = 0; if (silent) { System.out.println("DWELL-TIME/LASER-POWER COMPENSATION"); } else { IJ.showStatus("DWELL-TIME/LASER-POWER COMPENSATION"); } for (int i = 0; i < nChannels; i++) { for (int j = 0; j < nFrames; j++) { for (int k = 0; k < nSlices; k++) { if (silent) { FNTDprogress.updateProgress(prog / total); } else { IJ.showProgress(prog / total); } prog++; img.setPosition(i + 1, k + 1, j + 1); ip1 = img.getProcessor(); fp = new FloatProcessor(nX, nY); double laser_factor = Math.pow(laser_power / 0.10, laser_exponent); for (int m = 0; m < nX; m++) { for (int n = 0; n < nY; n++) { fp.putPixelValue( m, n, ip1.getPixelValue(m, n) * laser_factor / (laser_power * dwell_time)); } } resIms.addSlice(fp); } } } FNTDprogress.updateProgress(1); System.out.println(""); ImagePlus resImp = new ImagePlus(img.getTitle() + " (adj. count-rate)", resIms); if (resIms.getSize() > 1) { resImp = HyperStackConverter.toHyperStack( resImp, nChannels, nSlices, nFrames, "xyztc", "grayscale"); } return (resImp); }
/** * Returns saturation corrected version of the input image. A simple, one-parametric * exponential-saturation function with characteristic saturation rate is used (see Greilich et * al., 2013; Klimpki et al., 2016) * * @param img Input image * @param dwell_time Pixel dwell time, unit has to match saturation_rate * @param saturation_rate Characteristic saturation rate, unit has to match dwell_time * @return */ public static ImagePlus saturationCorrection( ImagePlus img, double dwell_time, double saturation_rate) { boolean silent = (IJ.getInstance() == null); int nX = img.getWidth(); int nY = img.getHeight(); int nSlices = img.getNSlices(); int nFrames = img.getNFrames(); int nChannels = img.getNChannels(); ImageStack resIms = new ImageStack(nX, nY); FloatProcessor fp; ImageProcessor ip1; int total = nSlices * nFrames * nChannels; double prog = 0; if (silent) { System.out.println("SATURATION CORRECTION"); } else { IJ.showStatus("SATURATION CORRECTION"); } for (int i = 0; i < nChannels; i++) { for (int j = 0; j < nFrames; j++) { for (int k = 0; k < nSlices; k++) { if (silent) { FNTDprogress.updateProgress(prog / total); } else { IJ.showProgress(prog / total); } prog++; img.setPosition(i + 1, k + 1, j + 1); ip1 = img.getProcessor(); fp = new FloatProcessor(nX, nY); double count_rate; for (int m = 0; m < nX; m++) { for (int n = 0; n < nY; n++) { count_rate = ip1.getPixelValue(m, n); count_rate = 1.0 - count_rate / (dwell_time * saturation_rate); count_rate = -1.0 * saturation_rate * dwell_time * log(count_rate); fp.putPixelValue(m, n, count_rate); } } resIms.addSlice(fp); } } } FNTDprogress.updateProgress(1); System.out.println(""); ImagePlus resImp = new ImagePlus(img.getTitle() + " (sat. corrected)", resIms); if (resIms.getSize() > 1) { resImp = HyperStackConverter.toHyperStack( resImp, nChannels, nSlices, nFrames, "xyztc", "grayscale"); } return (resImp); }
public static ImagePlus subtract(ImagePlus a, ImagePlus b) { boolean silent = (IJ.getInstance() == null); int nX = a.getWidth(); int nY = a.getHeight(); int nSlices = a.getNSlices(); int nFrames = a.getNFrames(); int nChannels = a.getNChannels(); if ((nX != b.getWidth()) || (nY != b.getHeight()) || (nSlices != b.getNSlices()) || (nFrames != b.getNFrames()) || (nChannels != b.getNChannels())) { if (silent) { System.out.println("Subtract: image dimensions do not match, return nothing."); } else { IJ.showMessage("Subtract: image dimensions do not match, return nothing."); } } ImageStack resIms = new ImageStack(nX, nY); FloatProcessor fp; ImageProcessor ip1, ip2; int total = nSlices * nFrames * nChannels; double prog = 0; if (silent) { System.out.println("SUBSTRACTING BACKGROUND"); } else { IJ.showStatus("SUBSTRACTING BACKGROUND"); } for (int i = 0; i < nChannels; i++) { for (int j = 0; j < nFrames; j++) { for (int k = 0; k < nSlices; k++) { if (silent) { FNTDprogress.updateProgress(prog / total); } else { IJ.showProgress(prog / total); } prog++; a.setPosition(i + 1, k + 1, j + 1); b.setPosition(i + 1, k + 1, j + 1); ip1 = a.getProcessor(); ip2 = b.getProcessor(); fp = new FloatProcessor(nX, nY); for (int m = 0; m < nX; m++) { for (int n = 0; n < nY; n++) { fp.putPixelValue(m, n, ip1.getPixelValue(m, n) - ip2.getPixelValue(m, n)); } } resIms.addSlice(fp); } } } FNTDprogress.updateProgress(1); System.out.println(""); ImagePlus resImp = new ImagePlus("Result of" + a.getTitle() + "-" + b.getTitle(), resIms); if (resIms.getSize() > 1) { resImp = HyperStackConverter.toHyperStack( resImp, nChannels, nSlices, nFrames, "xyztc", "grayscale"); } return (resImp); }
public void run(String arg) { int[] wList = WindowManager.getIDList(); if (wList==null) { IJ.error("No images are open."); return; } double kernel=3; double kernelsum = 0; double kernelvarsum =0; double kernalvar = 0; double sigmawidth = 2; int kernelindex, minpixnumber; String[] kernelsize = { "3�,"5�, "7�, "9�}; GenericDialog gd = new GenericDialog("Sigma Filter"); gd.addChoice("Kernel size", kernelsize, kernelsize[0]); gd.addNumericField("Sigma width",sigmawidth , 2); gd.addNumericField("Minimum number of pixels", 1, 0); gd.addCheckbox("Keep source:",true); gd.addCheckbox("Do all stack:",true); gd.addCheckbox("Modified Lee's FIlter:",true); gd.showDialog(); if (gd.wasCanceled()) return ; kernelindex = gd.getNextChoiceIndex(); sigmawidth = gd.getNextNumber(); minpixnumber = ((int)gd.getNextNumber()); boolean keep = gd.getNextBoolean(); boolean doallstack = gd.getNextBoolean(); boolean modified = gd.getNextBoolean(); if (kernelindex==0) kernel = 3; if (kernelindex==1) kernel = 5; if (kernelindex==2) kernel = 7; if (kernelindex==3) kernel = 9; long start = System.currentTimeMillis(); if (minpixnumber> (kernel*kernel)){ IJ.showMessage("Sigma filter", "There must be more pixels in the kernel than+\n" + "the minimum number to be included"); return; } double v, midintensity; int x, y, ix, iy; double sum = 0; double backupsum =0; int count = 0; int n = 0; if (keep) {IJ.run("Select All"); IJ.run("Duplicate...", "title='Sigma filtered' duplicate");} int radius = (int)(kernel-1)/2; ImagePlus imp = WindowManager.getCurrentImage(); ImageStack stack1 = imp.getStack(); int width = imp.getWidth(); int height = imp.getHeight(); int nslices = stack1.getSize(); int cslice = imp.getCurrentSlice(); double status = width*height*nslices; ImageProcessor ip = imp.getProcessor(); int sstart = 1; if (!doallstack) {sstart = cslice; nslices=sstart;status = status/nslices;}; for (int i=sstart; i<=nslices; i++) { imp.setSlice(i); for (x=radius;x<width+radius;x++) { for (y=radius;y<height+radius;y++) { midintensity = ip.getPixelValue(x,y); count = 0; sum = 0; kernelsum =0; kernalvar =0; kernelvarsum =0; backupsum = 0; //calculate mean of kernel value for (ix=0;ix<kernel;ix++) { for (iy=0;iy<kernel;iy++) { v = ip.getPixelValue(x+ix-radius,y+iy-radius); kernelsum = kernelsum+v; } } double sigmacalcmean = (kernelsum/(kernel*kernel)); //calculate variance of kernel for (ix=0;ix<kernel;ix++) { for (iy=0;iy<kernel;iy++) { v = ip.getPixelValue(x+ix-radius,y+iy-radius); kernalvar = (v-sigmacalcmean)*(v-sigmacalcmean); kernelvarsum = kernelvarsum + kernalvar; } } //double variance = kernelvarsum/kernel; double sigmacalcvar = kernelvarsum/((kernel*kernel)-1); //calcuate sigma range = sqrt(variance/(mean^2)) � sigmawidth double sigmarange = sigmawidth*(Math.sqrt((sigmacalcvar) /(sigmacalcmean*sigmacalcmean))); //calulate sigma top value and bottom value double sigmatop = midintensity*(1+sigmarange); double sigmabottom = midintensity*(1-sigmarange); //calculate mean of values that differ are in sigma range. for (ix=0;ix<kernel;ix++) { for (iy=0;iy<kernel;iy++) { v = ip.getPixelValue(x+ix-radius,y+iy-radius); if ((v>=sigmabottom)&&(v<=sigmatop)){ sum = sum+v; count = count+1; } backupsum = v+ backupsum; } } //if there are too few pixels in the kernal that are within sigma range, the //mean of the entire kernal is taken. My modification of Lee's filter is to exclude the central value //from the calculation of the mean as I assume it to be spuriously high or low if (!(count>(minpixnumber))) {sum = (backupsum-midintensity); count = (int)((kernel*kernel)-1); if (!modified) {sum = (backupsum); count = (int)(kernel*kernel);} } double val = (sum/count); ip.putPixelValue(x,y, val); n = n+1; double percentage = (((double)n/status)*100); IJ.showStatus(IJ.d2s(percentage,0) +"% done"); } // IJ.showProgress(i, status); }} imp.updateAndDraw(); IJ.showStatus(IJ.d2s((System.currentTimeMillis()-start)/1000.0, 2)+" seconds"); }
/** * Performs particle analysis on the specified ImagePlus and ImageProcessor. Returns false if * there is an error. */ public boolean analyze(ImagePlus imp, ImageProcessor ip) { if (this.imp == null) this.imp = imp; showResults = (options & SHOW_RESULTS) != 0; excludeEdgeParticles = (options & EXCLUDE_EDGE_PARTICLES) != 0; resetCounter = (options & CLEAR_WORKSHEET) != 0; showProgress = (options & SHOW_PROGRESS) != 0; floodFill = (options & INCLUDE_HOLES) == 0; recordStarts = (options & RECORD_STARTS) != 0; addToManager = (options & ADD_TO_MANAGER) != 0; displaySummary = (options & DISPLAY_SUMMARY) != 0; inSituShow = (options & IN_SITU_SHOW) != 0; outputImage = null; ip.snapshot(); ip.setProgressBar(null); if (Analyzer.isRedirectImage()) { redirectImp = Analyzer.getRedirectImage(imp); if (redirectImp == null) return false; int depth = redirectImp.getStackSize(); if (depth > 1 && depth == imp.getStackSize()) { ImageStack redirectStack = redirectImp.getStack(); redirectIP = redirectStack.getProcessor(imp.getCurrentSlice()); } else redirectIP = redirectImp.getProcessor(); } else if (imp.getType() == ImagePlus.COLOR_RGB) { ImagePlus original = (ImagePlus) imp.getProperty("OriginalImage"); if (original != null && original.getWidth() == imp.getWidth() && original.getHeight() == imp.getHeight()) { redirectImp = original; redirectIP = original.getProcessor(); } } if (!setThresholdLevels(imp, ip)) return false; width = ip.getWidth(); height = ip.getHeight(); if (!(showChoice == NOTHING || showChoice == OVERLAY_OUTLINES || showChoice == OVERLAY_MASKS)) { blackBackground = Prefs.blackBackground && inSituShow; if (slice == 1) outlines = new ImageStack(width, height); if (showChoice == ROI_MASKS) drawIP = new ShortProcessor(width, height); else drawIP = new ByteProcessor(width, height); drawIP.setLineWidth(lineWidth); if (showChoice == ROI_MASKS) { } // Place holder for now... else if (showChoice == MASKS && !blackBackground) drawIP.invertLut(); else if (showChoice == OUTLINES) { if (!inSituShow) { if (customLut == null) makeCustomLut(); drawIP.setColorModel(customLut); } drawIP.setFont(new Font("SansSerif", Font.PLAIN, fontSize)); if (fontSize > 12 && inSituShow) drawIP.setAntialiasedText(true); } outlines.addSlice(null, drawIP); if (showChoice == ROI_MASKS || blackBackground) { drawIP.setColor(Color.black); drawIP.fill(); drawIP.setColor(Color.white); } else { drawIP.setColor(Color.white); drawIP.fill(); drawIP.setColor(Color.black); } } calibration = redirectImp != null ? redirectImp.getCalibration() : imp.getCalibration(); if (rt == null) { rt = Analyzer.getResultsTable(); analyzer = new Analyzer(imp); } else analyzer = new Analyzer(imp, measurements, rt); if (resetCounter && slice == 1) { if (!Analyzer.resetCounter()) return false; } beginningCount = Analyzer.getCounter(); byte[] pixels = null; if (ip instanceof ByteProcessor) pixels = (byte[]) ip.getPixels(); if (r == null) { r = ip.getRoi(); mask = ip.getMask(); if (displaySummary) { if (mask != null) totalArea = ImageStatistics.getStatistics(ip, AREA, calibration).area; else totalArea = r.width * calibration.pixelWidth * r.height * calibration.pixelHeight; } } minX = r.x; maxX = r.x + r.width; minY = r.y; maxY = r.y + r.height; if (r.width < width || r.height < height || mask != null) { if (!eraseOutsideRoi(ip, r, mask)) return false; } int offset; double value; int inc = Math.max(r.height / 25, 1); int mi = 0; ImageWindow win = imp.getWindow(); if (win != null) win.running = true; if (measurements == 0) measurements = Analyzer.getMeasurements(); if (showChoice == ELLIPSES) measurements |= ELLIPSE; measurements &= ~LIMIT; // ignore "Limit to Threshold" roiNeedsImage = (measurements & PERIMETER) != 0 || (measurements & SHAPE_DESCRIPTORS) != 0 || (measurements & FERET) != 0; particleCount = 0; wand = new Wand(ip); pf = new PolygonFiller(); if (floodFill) { ImageProcessor ipf = ip.duplicate(); ipf.setValue(fillColor); ff = new FloodFiller(ipf); } roiType = Wand.allPoints() ? Roi.FREEROI : Roi.TRACED_ROI; for (int y = r.y; y < (r.y + r.height); y++) { offset = y * width; for (int x = r.x; x < (r.x + r.width); x++) { if (pixels != null) value = pixels[offset + x] & 255; else if (imageType == SHORT) value = ip.getPixel(x, y); else value = ip.getPixelValue(x, y); if (value >= level1 && value <= level2) analyzeParticle(x, y, imp, ip); } if (showProgress && ((y % inc) == 0)) IJ.showProgress((double) (y - r.y) / r.height); if (win != null) canceled = !win.running; if (canceled) { Macro.abort(); break; } } if (showProgress) IJ.showProgress(1.0); if (showResults) rt.updateResults(); imp.killRoi(); ip.resetRoi(); ip.reset(); if (displaySummary && IJ.getInstance() != null) updateSliceSummary(); if (addToManager && roiManager != null) roiManager.setEditMode(imp, true); maxParticleCount = (particleCount > maxParticleCount) ? particleCount : maxParticleCount; totalCount += particleCount; if (!canceled) showResults(); return true; }