package edu.berkeley.cs.nlp.ocular.preprocessing; import edu.berkeley.cs.nlp.ocular.image.ImageUtils; /** * @author Taylor Berg-Kirkpatrick (tberg@eecs.berkeley.edu) */ public class Binarizer { public static boolean isBinary(double[][] levels) { int[] histogram = new int[(int) ImageUtils.MAX_LEVEL+1]; for (int i=0; i<levels.length; i++) { for (int j=0; j<levels[i].length; j++) { histogram[(int) levels[i][j]]++; } } int nonZeroEntries = 0; for (int count : histogram) { if (count > 0) nonZeroEntries++; } return nonZeroEntries <= 2; } public static void binarizeAlreadyBinary(double[][] levels) { double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (double[] vals : levels) { for (double val : vals) { min = Math.min(val, min); max = Math.max(val, max); } } double threshold = (max + min) / 2.0; for (int i = 0; i < levels.length; i++) { for (int j = 0; j < levels[i].length; j++) { if (levels[i][j] <= threshold) { levels[i][j] = 0; } else { levels[i][j] = ImageUtils.MAX_LEVEL; } } } } public static void binarizeGlobal(double blackPercential, double[][] levels) { if (isBinary(levels)) { binarizeAlreadyBinary(levels); return; } int[] histogram = new int[(int) ImageUtils.MAX_LEVEL+1]; int total = 0; for (int i=0; i<levels.length; i++) { for (int j=0; j<levels[i].length; j++) { histogram[(int) levels[i][j]]++; total++; } } int rank = (int) (Math.ceil(total * blackPercential)); int curRank = 0; double threshold = 0.0; for (int v=0; v<histogram.length; ++v) { curRank += histogram[v]; if (curRank >= rank) { threshold = v; break; } } for (int i = 0; i < levels.length; i++) { for (int j = 0; j < levels[i].length; j++) { if (levels[i][j] <= threshold) { levels[i][j] = 0; } else { levels[i][j] = ImageUtils.MAX_LEVEL; } } } } public static void binarizeLocal(double blackPercential, double radiusFactor, double[][] levels) { if (isBinary(levels)) { binarizeAlreadyBinary(levels); return; } int radius = (int) (levels.length * radiusFactor); int dWidth = (int) Math.ceil((double) levels.length / radius); int dHeight = (int) Math.ceil((double) levels[0].length / radius); double[][] thresholds = new double[dWidth][dHeight]; for (int di=0; di<dWidth; ++di) { for (int dj=0; dj<dHeight; ++dj) { int i = di*radius + radius / 2; int j = dj*radius + radius / 2; if (i < levels.length && j < levels[0].length) { int[] histogram = new int[(int) ImageUtils.MAX_LEVEL+1]; int total = 0; for (int i0 = Math.max(0,i-radius); i0 < Math.min(levels.length,i+radius); i0++) { for (int j0 = Math.max(0,j-radius); j0 < Math.min(levels[i].length,j+radius); j0++) { histogram[(int) levels[i0][j0]]++; total++; } } int rank = (int) (Math.ceil(total * blackPercential)); int curRank = 0; double threshold = 0.0; for (int v=0; v<histogram.length; ++v) { curRank += histogram[v]; if (curRank >= rank) { threshold = v; break; } } thresholds[di][dj] = threshold; } } } for (int i = 0; i < levels.length; i++) { for (int j = 0; j < levels[i].length; j++) { if (levels[i][j] <= thresholds[i/radius][j/radius]) { levels[i][j] = 0; } else { levels[i][j] = ImageUtils.MAX_LEVEL; } } } } }