Search code examples
javaconvolutionsobel

Sobel filter - How to correctly display convolution result?


I'm currently trying to implement my own version of the Sobel-Filter/Operator. I tried to pull as much information as possible from Wikipedia(https://en.wikipedia.org/wiki/Sobel_operator) and numerous explanations on YouTube, but i can't find a solution to my problem.

So after gray-scaling my image:

    public BufferedImage grayscale(String path) {
        BufferedImage img = readImage(path);
        for (int x = 0; x < img.getWidth(); x++) {
            for (int y = 0; y < img.getHeight(); y++) {
                Color oldColor = new Color(img.getRGB(x, y));
                int red = oldColor.getRed();
                int green = oldColor.getGreen();
                int blue = oldColor.getBlue();
                int grayValue = (int) (0.244 * red + 0.587 * green + 0.114 * blue);
                Color newColor = new Color(grayValue, grayValue, grayValue);
                img.setRGB(x, y, newColor.getRGB());
            }
        }
        return img;
    }

I tried to extract the part of the image that should be convolved with the Sobel-Operator Sx. Since i gray-scaled the entire image, i figured it should be fine to use the red-portion since all values should be the same:

    public void sobel(BufferedImage grayScaledImg) {
        for (int x = 1; x < grayScaledImg.getWidth() - 1; x++) {
            for (int y = 1; y < grayScaledImg.getHeight() - 1; y++) {
                int field1 = new Color(grayScaledImg.getRGB(x - 1, y - 1)).getRed();
                int field2 = new Color(grayScaledImg.getRGB(x, y - 1)).getRed();
                int field3 = new Color(grayScaledImg.getRGB(x + 1, y - 1)).getRed();
                int field4 = new Color(grayScaledImg.getRGB(x - 1, y)).getRed();
                int field5 = new Color(grayScaledImg.getRGB(x, y)).getRed();
                int field6 = new Color(grayScaledImg.getRGB(x + 1, y)).getRed();
                int field7 = new Color(grayScaledImg.getRGB(x - 1, y + 1)).getRed();
                int field8 = new Color(grayScaledImg.getRGB(x, y + 1)).getRed();
                int field9 = new Color(grayScaledImg.getRGB(x + 1, y + 1)).getRed();
                int[] currentPartOfImage = {field1, field2, field3, field4, field5, field6, field7, field8, field9};

And i'm pretty sure that in the following piece of code i did something wrong but i cant figure out what..

                int newGrayScale = sobelX(currentPartOfImage);
                grayScaledImg.setRGB(x, y, new Color(newGrayScale, newGrayScale, newGrayScale).getRGB());
            }
        }
    }

The sobelX-Function looks like this:

    public int sobelX(int[] image) {
        return Math.abs(image[2] + (2 * image[5]) + image[8] - image[0] - (2 * image[3]) - image[6]);
    }

Problem
Some of the values i get while doing the convolution are larger than 255, which means they aren't valid RGB-values. So i'm currently not sure how to properly use those values?

Thanks in advance for the help! :)


Solution

  • Some of the values i get while doing the convolution are larger than 255

    This is often solved by using a "clamp" function. It is a function that checks if the argument is in the allowed range, and if not, returns the closest allowed value.

    int clamp(int value) {
        if (value > 255) return 255;
        if (value < 0) return 0;
        return value;
    }
    

    And this is how you use it:

    int newGrayScale = clamp(sobelX(currentPartOfImage));