/* * see http://rsb.info.nih.gov/ij/developer/source/ij/process/AutoThresholder.java.html * The method is present in: Implements Li's Minimum Cross Entropy thresholding method * This implementation is based on the iterative version (Ref. 2nd reference below) of the algorithm. * 1) Li, CH & Lee, CK (1993), "Minimum Cross Entropy Thresholding", Pattern Recognition 26(4): 61 625 * 2) Li, CH & Tam, PKS (1998), "An Iterative Algorithm for Minimum Cross Entropy Thresholding", * Pattern Recognition Letters 18(8): 771-776 * 3) Sezgin, M & Sankur, B (2004), "Survey over Image Thresholding Techniques and Quantitative Performance * Evaluation",Journal of Electronic Imaging 13(1): 146-165 * @param histogram - the histogram of the image * @param total - the number of pixels in the image * @returns {number} - the threshold */ /** * Return a threshold for a histogram using Li algorithm. * @param histogram - Image histogram. * @param total - Number of pixels in the image. * @returns The threshold. */ export default function li(histogram: Uint32Array, total: number): number { let threshold; let sumBack; /* sum of the background pixels at a given threshold */ let sumObj; /* sum of the object pixels at a given threshold */ let numBack; /* number of background pixels at a given threshold */ let numObj; /* number of object pixels at a given threshold */ let oldThresh; let newThresh; let meanBack; /* mean of the background pixels at a given threshold */ let meanObj; /* mean of the object pixels at a given threshold */ let mean; /* mean gray-level in the image */ const tolerance = 0.5; /* threshold tolerance */ let temp; /* Calculate the mean gray-level */ mean = 0; for (let ih = 0; ih < histogram.length; ih++) { mean += ih * histogram[ih]; } mean /= total; /* Initial estimate */ newThresh = mean; do { oldThresh = newThresh; threshold = (oldThresh + 0.5) | 0; /* range */ /* Calculate the means of background and object pixels */ /* Background */ sumBack = 0; numBack = 0; for (let ih = 0; ih <= threshold; ih++) { sumBack += ih * histogram[ih]; numBack += histogram[ih]; } meanBack = numBack === 0 ? 0 : sumBack / numBack; /* Object */ sumObj = 0; numObj = 0; for (let ih = threshold + 1; ih < histogram.length; ih++) { sumObj += ih * histogram[ih]; numObj += histogram[ih]; } meanObj = numObj === 0 ? 0 : sumObj / numObj; temp = (meanBack - meanObj) / (Math.log(meanBack) - Math.log(meanObj)); if (temp < -Number.EPSILON) { newThresh = (temp - 0.5) | 0; } else { newThresh = (temp + 0.5) | 0; } /* Stop the iterations when the difference between the new and old threshold values is less than the tolerance */ } while (Math.abs(newThresh - oldThresh) > tolerance); return threshold; }