// Conversion Options void conversions() { double[] weights = ColorProcessor.getWeightingFactors(); boolean weighted = !(weights[0] == 1d / 3d && weights[1] == 1d / 3d && weights[2] == 1d / 3d); // boolean weighted = !(Math.abs(weights[0]-1d/3d)<0.0001 && Math.abs(weights[1]-1d/3d)<0.0001 // && Math.abs(weights[2]-1d/3d)<0.0001); GenericDialog gd = new GenericDialog("Conversion Options"); gd.addCheckbox("Scale when converting", ImageConverter.getDoScaling()); String prompt = "Weighted RGB conversions"; if (weighted) prompt += " (" + IJ.d2s(weights[0]) + "," + IJ.d2s(weights[1]) + "," + IJ.d2s(weights[2]) + ")"; gd.addCheckbox(prompt, weighted); gd.showDialog(); if (gd.wasCanceled()) return; ImageConverter.setDoScaling(gd.getNextBoolean()); Prefs.weightedColor = gd.getNextBoolean(); if (!Prefs.weightedColor) ColorProcessor.setWeightingFactors(1d / 3d, 1d / 3d, 1d / 3d); else if (Prefs.weightedColor && !weighted) ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114); return; }
void Mean(ImagePlus imp, int radius, double par1, double par2, boolean doIwhite) { // See: Image Processing Learning Resourches HIPR2 // http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm ImagePlus Meanimp; ImageProcessor ip = imp.getProcessor(), ipMean; int c_value = 0; byte object; byte backg; if (par1 != 0) { IJ.log("Mean: changed c_value from :" + c_value + " to:" + par1); c_value = (int) par1; } if (doIwhite) { object = (byte) 0xff; backg = (byte) 0; } else { object = (byte) 0; backg = (byte) 0xff; } Meanimp = duplicateImage(ip); ImageConverter ic = new ImageConverter(Meanimp); ic.convertToGray32(); ipMean = Meanimp.getProcessor(); RankFilters rf = new RankFilters(); rf.rank(ipMean, radius, rf.MEAN); // Mean // Meanimp.show(); byte[] pixels = (byte[]) ip.getPixels(); float[] mean = (float[]) ipMean.getPixels(); for (int i = 0; i < pixels.length; i++) pixels[i] = ((int) (pixels[i] & 0xff) > (int) (mean[i] - c_value)) ? object : backg; // imp.updateAndDraw(); return; }
void Sauvola(ImagePlus imp, int radius, double par1, double par2, boolean doIwhite) { // Sauvola recommends K_VALUE = 0.5 and R_VALUE = 128. // This is a modification of Niblack's thresholding method. // Sauvola J. and Pietaksinen M. (2000) "Adaptive Document Image Binarization" // Pattern Recognition, 33(2): 225-236 // http://www.ee.oulu.fi/mvg/publications/show_pdf.php?ID=24 // Ported to ImageJ plugin from E Celebi's fourier_0.8 routines // This version uses a circular local window, instead of a rectagular one ImagePlus Meanimp, Varimp; ImageProcessor ip = imp.getProcessor(), ipMean, ipVar; double k_value = 0.5; double r_value = 128; byte object; byte backg; if (par1 != 0) { IJ.log("Sauvola: changed k_value from :" + k_value + " to:" + par1); k_value = par1; } if (par2 != 0) { IJ.log("Sauvola: 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); ImageConverter ic = new ImageConverter(Meanimp); ic.convertToGray32(); ipMean = Meanimp.getProcessor(); RankFilters rf = new RankFilters(); rf.rank(ipMean, radius, rf.MEAN); // Mean // Meanimp.show(); Varimp = duplicateImage(ip); ic = new ImageConverter(Varimp); ic.convertToGray32(); ipVar = Varimp.getProcessor(); rf.rank(ipVar, radius, rf.VARIANCE); // Variance // Varimp.show(); byte[] pixels = (byte[]) ip.getPixels(); float[] mean = (float[]) ipMean.getPixels(); float[] var = (float[]) ipVar.getPixels(); for (int i = 0; i < pixels.length; i++) pixels[i] = ((int) (pixels[i] & 0xff) > (int) (mean[i] * (1.0 + k_value * ((Math.sqrt(var[i]) / r_value) - 1.0)))) ? object : backg; // imp.updateAndDraw(); return; }
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; }
void Niblack(ImagePlus imp, int radius, double par1, double par2, boolean doIwhite) { // Niblack recommends K_VALUE = -0.2 for images with black foreground // objects, and K_VALUE = +0.2 for images with white foreground objects. // Niblack W. (1986) "An introduction to Digital Image Processing" Prentice-Hall. // Ported to ImageJ plugin from E Celebi's fourier_0.8 routines // This version uses a circular local window, instead of a rectagular one ImagePlus Meanimp, Varimp; ImageProcessor ip = imp.getProcessor(), ipMean, ipVar; double k_value; int c_value = 0; byte object; byte backg; if (doIwhite) { k_value = 0.2; object = (byte) 0xff; backg = (byte) 0; } else { k_value = -0.2; object = (byte) 0; backg = (byte) 0xff; } if (par1 != 0) { IJ.log("Niblack: changed k_value from :" + k_value + " to:" + par1); k_value = par1; } if (par2 != 0) { IJ.log( "Niblack: changed c_value from :" + c_value + " to:" + par2); // requested feature, not in original c_value = (int) par2; } Meanimp = duplicateImage(ip); ImageConverter ic = new ImageConverter(Meanimp); ic.convertToGray32(); ipMean = Meanimp.getProcessor(); RankFilters rf = new RankFilters(); rf.rank(ipMean, radius, rf.MEAN); // Mean // Meanimp.show(); Varimp = duplicateImage(ip); ic = new ImageConverter(Varimp); ic.convertToGray32(); ipVar = Varimp.getProcessor(); rf.rank(ipVar, radius, rf.VARIANCE); // Variance // Varimp.show(); byte[] pixels = (byte[]) ip.getPixels(); float[] mean = (float[]) ipMean.getPixels(); float[] var = (float[]) ipVar.getPixels(); for (int i = 0; i < pixels.length; i++) pixels[i] = ((int) (pixels[i] & 0xff) > (int) (mean[i] + k_value * Math.sqrt(var[i]) - c_value)) ? object : backg; // imp.updateAndDraw(); return; }