Skip to content

Commit

Permalink
Fixes For Otsu's Thresholding Augmentation issue 170
Browse files Browse the repository at this point in the history
  • Loading branch information
mike committed Mar 28, 2024
1 parent 99f5ed1 commit 2367dcf
Showing 1 changed file with 38 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@

import de.edux.augmentation.core.AbstractAugmentation;

import java.awt.*;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

/**
* Applies Otsu's thresholding method to the given image.
* Converts the image to grayscale, calculates the histogram, finds the optimal threshold,
* and applies the threshold to create a binary image.
*/
public class OtsuThresholdingAugmentation extends AbstractAugmentation {
private static final Integer HISTOGRAM_SIZE = 256;
private static final int RED_INTENSITY_SHIFT = 16;


/**
* Applies Otsu's thresholding method to the given image.
* @param image the original image to be thresholded
* @return a binary image where pixels with intensity greater than the threshold are white,
* and others are black
*/
@Override
public BufferedImage apply(BufferedImage image) {
BufferedImage grayImage = toGrayScale((image));
Expand All @@ -17,18 +29,14 @@ public BufferedImage apply(BufferedImage image) {
for (int i = 0; i < grayImage.getWidth(); i++) {
for (int j = 0; j < grayImage.getHeight(); j++) {
int pixel = grayImage.getRGB(i, j);
int intensity = (pixel >> 16) & 0xff;
int intensity = (pixel >> RED_INTENSITY_SHIFT) & 0xff;
thresholdedImage.setRGB(i, j, intensity > threshold ? 0xFFFFFF : 0x000000);
}
}
return thresholdedImage;
}


/**
* Convert it first to Grayscale*
*/
public BufferedImage toGrayScale(BufferedImage img) {
private BufferedImage toGrayScale(BufferedImage img) {
System.out.println(" Converting to GrayScale.");
BufferedImage grayImage = new BufferedImage(
img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Expand All @@ -38,8 +46,8 @@ public BufferedImage toGrayScale(BufferedImage img) {
return grayImage;
}

private static int[] calculateHistogram(BufferedImage image) {
int[] histogram = new int[256];
private int[] calculateHistogram(BufferedImage image) {
int[] histogram = new int[HISTOGRAM_SIZE];
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
int pixel = image.getRGB(i, j);
Expand All @@ -50,36 +58,47 @@ private static int[] calculateHistogram(BufferedImage image) {
return histogram;
}

private static int findOtsuThreshold(int[] histogram, int totalPixels) {
private int findOtsuThreshold(int[] histogram, int totalPixels) {
float totalPixelIntensity = 0;
for (int intensity = 0; intensity < 256; intensity++) {
for (int intensity = 0; intensity < HISTOGRAM_SIZE; intensity++) {
totalPixelIntensity += intensity * histogram[intensity];
}
float backgroundPixelIntensity = 0;
int backgroundWeight = 0;
int foregroundWeight = 0;
float maxVariance = 0;
int optimalThreshold = 0;
for (int threshold = 0; threshold < 256; threshold++) {
for (int threshold = 0; threshold < HISTOGRAM_SIZE; threshold++) {
backgroundWeight += histogram[threshold];

if (backgroundWeight == 0) continue;
foregroundWeight = totalPixels - backgroundWeight;
if (foregroundWeight == 0) break;

backgroundPixelIntensity += (float) (threshold * histogram[threshold]);

float meanBackgroundIntensity = backgroundPixelIntensity / backgroundWeight;
float meanForegroundIntensity = (totalPixelIntensity - backgroundPixelIntensity) / foregroundWeight;
// Calculate the between-class variance
float betweenClassVariance = (float) ((float) backgroundWeight
* (float) foregroundWeight
* Math.pow(meanBackgroundIntensity - meanForegroundIntensity, 2));
// Update the maximum variance and optimal
// threshold if the current between-class variance is greater
float betweenClassVariance = calculateBetweenClassVariance(backgroundWeight, foregroundWeight, meanBackgroundIntensity, meanForegroundIntensity);

if (betweenClassVariance > maxVariance) {
maxVariance = betweenClassVariance;
optimalThreshold = threshold;
}
}
return optimalThreshold;
}

private float calculateBetweenClassVariance(int backgroundWeight, int foregroundWeight, float meanBackgroundIntensity, float meanForegroundIntensity) {
return (float) ((float) backgroundWeight * (float) foregroundWeight * Math.pow(meanBackgroundIntensity - meanForegroundIntensity, 2));
}

}








0 comments on commit 2367dcf

Please sign in to comment.