Hey, this is a continuation of my image editing program, I am trying to perform intensity thresholding with an intelligent threshold. My code thus far:

private void thresholdMenuItemActionPerformed(java.awt.event.ActionEvent evt) {                                                  
        BufferedImage inputImage = getImage();
        setUndoImage(inputImage);
        BufferedImage thresholdImage = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), inputImage.getType());
        int threshold = 0;
        int tnew = 128;
        int count = 0;
        double m1, m2;

        for (int x = 0; x < inputImage.getWidth(); x++) {
            for (int y = 0; y < inputImage.getHeight(); y++) {
                int red = (inputImage.getRGB(x,y) & 0x00ff0000) >> 16;
                int green = (inputImage.getRGB(x,y) & 0x0000ff00) >> 8;
                int blue = (inputImage.getRGB(x,y) & 0x000000ff);
                int grey = (int) ((0.30 * red) + (0.59 * green) + (0.11 * blue));
                thresholdImage.setRGB(x,y, 0xff000000 | grey << 16 | grey << 8 | grey);
            }
        }

        int[] hist = new int[256];

        for (int h = 0; h < 255; h++) {
        hist[h] = 0;
        }

        for (int x = 0; x < thresholdImage.getWidth(); x++) {
            for(int y = 0; y < thresholdImage.getHeight(); y++) {
                int i = (thresholdImage.getRGB(x, y) & 0x000000ff);
                hist[i]++;
            }
        }

        do {
            threshold = tnew;
            m1 = m2 = 0.0;
            for (int i = 0; i < threshold; i++){
                m1 += hist[i];
                count++;
            }

            m1 /= count;

            for (int i = threshold; i < 255; i++){
                m2 += hist[i];
                count++;
            }

            m2 /= count;

            tnew = (int)((m1 + m2) / 2.0);
        } while (tnew != threshold);

        for (int x = 0; x < thresholdImage.getWidth(); x++) {
            for (int y = 0; y < thresholdImage.getHeight(); y++) {
                int bin = (thresholdImage.getRGB(x, y) & 0x000000ff);
                if (bin > tnew) {
                    bin = 255;
                } else {
                    bin = 0;
                }
                thresholdImage.setRGB(x,y, 0xff000000 | bin << 16 | bin << 8 | bin);
            }
        }

        imageCanvas.setIcon(new ImageIcon(thresholdImage));
        System.out.println("Intensity thresholding succeeded.");
        setImage(thresholdImage);
}

First I convert the image to a greyscale image. Then I get the blue value (because it's greyscale red green and blue values should be equal) and make a histogram of the grey levels. Then I set an initial threshold of 128, and find the mean of all the values below and above this threshold, and then use them to find an overall mean, set my new threshold to that and try again, until it stabilises. Then I check if the grey value is over or under the threshold value, and set it white or black accordingly. My issue is that my threshold is being set unreasonably high, so that my image is either nearly all white, or it simply crashes with an "ArrayIndexOutOfBoundsException".

Edited 6 Years Ago by cherryduck: n/a

Which line generates the array index exception?

ps: line 22 should read <= 255
(althought new int arrays are initialised to all zeros anyway)

pps Shouldn't you re-initialise count around line 42?

Edited 6 Years Ago by JamesCherrill: ps, pps

I've removed the initialisation of the array values to 0 and that still works, thanks, might as well prune out unnecessary code. My array index exception is occuring at line 37. Oh, and re-initialising count just makes it crash for EVERY image instead of just some.

Edited 6 Years Ago by cherryduck: n/a

Suggests threashold has got > 255 - tho I can't see how (especially with the wrong value of count being used to divide m2). Try printing it to confirm?

The values in hist can get arbitrarily large, based on the size of the image, so m1 and m2 can get arbitrarily large, so tnew and thus threashold ditto, thus array index error when threashold is upper bound of loop.

Suggests threashold has got > 255 - tho I can't see how (especially with the wrong value of count being used to divide m2). Try printing it to confirm?

My threshold is 264 on one of my test images, and 734 on another, and I have no idea how or why this is happening.

My threshold is 264 on one of my test images, and 734 on another, and I have no idea how or why this is happening.

See my last post - the calculation of the means is wrong.

The values in hist can get arbitrarily large, based on the size of the image, so m1 and m2 can get arbitrarily large, so tnew and thus threashold ditto, thus array index error when threashold is upper bound of loop.

Pants, any idea how to overcome this?

I don't understand what you are really doing with the calculation of two means then averaging them in that convergent loop, so I'm not in a good position to re-design your code. But... at a guess...
if a contains the number of pixels with value i, then the weighted average value of i is something like
sum(a * i) / sum(a)
at least this should give an answer in the range 0-255

Edited 6 Years Ago by JamesCherrill: n/a

Thanks, I understand what you're saying there, I just have to figure out how to implement that in my current code...and I'm not very good at coding...this will be fun! Haha, cheers for your help.

Thank you VERY much for your help, it was a case of changing my mean code to

for (int i = 0; i < threshold; i++){
m1 += hist[i]*i;
count += hist[i];
}

And of course re-initialising my count. Once you told me the logic, I sat down with a good old pen and paper and figured out what I was trying to do. Thanks!

This question has already been answered. Start a new discussion instead.