double rodbard(double x) { // y = c*((a-x/(x-d))^(1/b) // a=3.9, b=.88, c=712, d=44 double ex; if (x == 0.0) ex = 5.0; else ex = Math.exp(Math.log(x / 700.0) * 0.88); double y = 3.9 - 44.0; y = y / (1.0 + ex); return y + 44.0; }
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(); }
void Phansalkar(ImagePlus imp, int radius, double par1, double par2, boolean doIwhite) { // This is a modification of Sauvola's thresholding method to deal with low contrast images. // Phansalskar N. et al. Adaptive local thresholding for detection of nuclei in diversity // stained // cytology images.International Conference on Communications and Signal Processing (ICCSP), // 2011, // 218 - 220. // In this method, the threshold t = mean*(1+p*exp(-q*mean)+k*((stdev/r)-1)) // Phansalkar recommends k = 0.25, r = 0.5, p = 2 and q = 10. In this plugin, k and r are the // parameters 1 and 2 respectively, but the values of p and q are fixed. // // Implemented from Phansalkar's paper description by G. Landini // This version uses a circular local window, instead of a rectagular one ImagePlus Meanimp, Varimp, Orimp; ImageProcessor ip = imp.getProcessor(), ipMean, ipVar, ipOri; double k_value = 0.25; double r_value = 0.5; double p_value = 2.0; double q_value = 10.0; byte object; byte backg; if (par1 != 0) { IJ.log("Phansalkar: changed k_value from :" + k_value + " to:" + par1); k_value = par1; } if (par2 != 0) { IJ.log("Phansalkar: changed r_value from :" + r_value + " to:" + par2); r_value = par2; } if (doIwhite) { object = (byte) 0xff; backg = (byte) 0; } else { object = (byte) 0; backg = (byte) 0xff; } Meanimp = duplicateImage(ip); ContrastEnhancer ce = new ContrastEnhancer(); ce.stretchHistogram(Meanimp, 0.0); ImageConverter ic = new ImageConverter(Meanimp); ic.convertToGray32(); ipMean = Meanimp.getProcessor(); ipMean.multiply(1.0 / 255); Orimp = duplicateImage(ip); ce.stretchHistogram(Orimp, 0.0); ic = new ImageConverter(Orimp); ic.convertToGray32(); ipOri = Orimp.getProcessor(); ipOri.multiply(1.0 / 255); // original to compare // Orimp.show(); RankFilters rf = new RankFilters(); rf.rank(ipMean, radius, rf.MEAN); // Mean // Meanimp.show(); Varimp = duplicateImage(ip); ce.stretchHistogram(Varimp, 0.0); ic = new ImageConverter(Varimp); ic.convertToGray32(); ipVar = Varimp.getProcessor(); ipVar.multiply(1.0 / 255); rf.rank(ipVar, radius, rf.VARIANCE); // Variance ipVar.sqr(); // SD // Varimp.show(); byte[] pixels = (byte[]) ip.getPixels(); float[] ori = (float[]) ipOri.getPixels(); float[] mean = (float[]) ipMean.getPixels(); float[] sd = (float[]) ipVar.getPixels(); for (int i = 0; i < pixels.length; i++) pixels[i] = ((ori[i]) > (mean[i] * (1.0 + p_value * Math.exp(-q_value * mean[i]) + k_value * ((sd[i] / r_value) - 1.0)))) ? object : backg; // imp.updateAndDraw(); return; }