public static Func<byte, byte, byte, Pixel> Otsu(PNM image) { double[] histogram = image.GetHistogramLuminosity(); object compareLock = new object(); double[] variances = new double[256]; Parallel.For(0, 256, i => { double[] background = histogram.Take(i).ToArray(); double[] foreground = histogram.Skip(i).ToArray(); double backgroundWeight = background.Sum(); double foregroundWeight = 1 - backgroundWeight; double backgroundMean = background.Length == 0 ? 0 : background.Select((d, idx) => d * idx).Average(); double foregroundMean = foreground.Select((d, idx) => d * idx).Average(); double variance = backgroundWeight * foregroundWeight * Math.Pow(foregroundMean - backgroundMean, 2); variances[i] = variance; }); byte threshold = 0; double maxVariance = Double.NegativeInfinity; for(int i =0; i< 256;i++) { if (variances[i] > maxVariance) { maxVariance = variances[i]; threshold = (byte)i; } } return (r, g, b) => Plain(r, g, b, threshold); }
public static Func <byte, byte, byte, Pixel> Otsu(PNM image) { double[] histogram = image.GetHistogramLuminosity(); object compareLock = new object(); double[] variances = new double[256]; Parallel.For(0, 256, i => { double[] background = histogram.Take(i).ToArray(); double[] foreground = histogram.Skip(i).ToArray(); double backgroundWeight = background.Sum(); double foregroundWeight = 1 - backgroundWeight; double backgroundMean = background.Length == 0 ? 0 : background.Select((d, idx) => d * idx).Average(); double foregroundMean = foreground.Select((d, idx) => d * idx).Average(); double variance = backgroundWeight * foregroundWeight * Math.Pow(foregroundMean - backgroundMean, 2); variances[i] = variance; }); byte threshold = 0; double maxVariance = Double.NegativeInfinity; for (int i = 0; i < 256; i++) { if (variances[i] > maxVariance) { maxVariance = variances[i]; threshold = (byte)i; } } return((r, g, b) => Plain(r, g, b, threshold)); }
public static Func <byte, byte, byte, Pixel> Triangle(PNM image) { double[] histogram = image.GetHistogramLuminosity(); int minx = 0, maxx = 0; double minValue = Double.PositiveInfinity, maxValue = Double.NegativeInfinity; // find min max for (int i = 0; i < 256; i++) { if (histogram[i] >= maxValue) { maxValue = histogram[i]; maxx = i; } if (histogram[i] < minValue) { minValue = histogram[i]; minx = i; } } // find line double a = -(maxValue - minValue) / (maxx - minx); double b = 1; double c = (minx * (maxValue - minValue) / (maxx - minx)) - minValue; // find the furthest point double distance, maxDistance = Double.NegativeInfinity; byte threshold = 0; int from, to; if (minx < maxx) { from = minx + 1; to = maxx; } else { to = minx + 1; from = maxx; } for (int i = from; i < to; i++) { distance = PointToLineDistance(a, b, c, i, histogram[i]); if (distance >= maxDistance) { maxDistance = distance; threshold = (byte)i; } } return((pr, pg, pb) => Plain(pr, pg, pb, threshold)); }
public static Func<byte, byte, byte, Pixel> Triangle(PNM image) { double[] histogram = image.GetHistogramLuminosity(); int minx=0, maxx=0; double minValue = Double.PositiveInfinity, maxValue = Double.NegativeInfinity; // find min max for (int i = 0; i < 256; i++) { if (histogram[i] >= maxValue) { maxValue = histogram[i]; maxx = i; } if (histogram[i] < minValue) { minValue = histogram[i]; minx = i; } } // find line double a = -(maxValue - minValue) / (maxx - minx); double b = 1; double c = (minx * (maxValue - minValue) / (maxx - minx)) - minValue; // find the furthest point double distance, maxDistance = Double.NegativeInfinity; byte threshold = 0; int from, to; if (minx < maxx) { from = minx + 1; to = maxx; } else { to = minx + 1; from = maxx; } for(int i = from; i< to; i++) { distance = PointToLineDistance(a,b,c,i,histogram[i]); if (distance >= maxDistance) { maxDistance = distance; threshold = (byte)i; } } return (pr, pg, pb) => Plain(pr, pg, pb, threshold); }
// Kapur's method public static Func <byte, byte, byte, Pixel> Entropy(PNM image) { double[] histogram = image.GetHistogramLuminosity(); double entropySum = Double.NegativeInfinity; int threshold = 0; for (int i = 0; i < 256; i++) { double[] background = histogram.Take(i + 1).ToArray(); double[] foreground = histogram.Skip(i + 1).ToArray(); double sumB = background.Sum(); double sumF = foreground.Sum(); double entropyB = -background.Select(p => { if (p == 0) { return(0); } return((p / sumB) * Math.Log(p / sumB, 2)); }) .Sum(); double entropyF = -foreground.Select(p => { if (p == 0) { return(0); } return((p / (1 - sumB)) * Math.Log(p / (1 - sumB), 2)); }) .Sum(); double sum = entropyB + entropyF; if (sum > entropySum) { entropySum = sum; threshold = i; } } return((r, g, b) => Plain(r, g, b, (byte)threshold)); }
// Kapur's method public static Func<byte, byte, byte, Pixel> Entropy(PNM image) { double[] histogram = image.GetHistogramLuminosity(); double entropySum = Double.NegativeInfinity; int threshold = 0; for (int i = 0; i < 256; i++) { double[] background = histogram.Take(i + 1).ToArray(); double[] foreground = histogram.Skip(i + 1).ToArray(); double sumB = background.Sum(); double sumF = foreground.Sum(); double entropyB = -background.Select(p => { if(p == 0) return 0; return (p / sumB) * Math.Log(p / sumB, 2); }) .Sum(); double entropyF = -foreground.Select(p => { if(p == 0) return 0; return (p / (1 - sumB)) * Math.Log(p / (1 - sumB), 2); }) .Sum(); double sum = entropyB + entropyF; if (sum > entropySum) { entropySum = sum; threshold = i; } } return (r, g, b) => Plain(r, g, b, (byte)threshold); }