Search code examples
javaimage-processingedge-detectionsobel

My Sobel Edge Detection Operator Output is weird


My output of Sobel edge detection operator is weird. Here's my code :

    BufferedImage temp = img;
    float kernelx[][] = {{-1, 0, 1},{-2, 0, 2},{-1, 0, 1}};
    float kernely[][] = {{-1, -2, -1},{0,  0,  0},{1,  2,  1}};
    float valx = 0;
    float valy = 0;
    float val = 0;
        for(int i=1;i<width-2;i++) {
           for(int j=1;j<height-2;j++) {
               valx = (kernelx[0][0]*new Color(img.getRGB(i-1, j-1)).getRed()) + (kernelx[0][2]*new Color(img.getRGB(i+1, j-1)).getRed()) +
                     (kernelx[1][0]*new Color(img.getRGB(i-1, j)).getRed()) + (kernelx[1][2]*new Color(img.getRGB(i+1, j)).getRed()) +
                     (kernelx[2][0]*new Color(img.getRGB(i-1, j+1)).getRed()) + (kernelx[2][2]*new Color(img.getRGB(i+1, j+1)).getRed());

               valy = (kernely[0][0]*new Color(img.getRGB(i-1, j-1)).getRed()) + (kernely[0][1]*new Color(img.getRGB(i, j-1)).getRed()) + (kernely[0][2]*new Color(img.getRGB(i+1, j-1)).getRed()) +
                       (kernely[2][0]*new Color(img.getRGB(i-1, j+1)).getRed()) + (kernely[2][1]*new Color(img.getRGB(i, j+1)).getRed()) + (kernely[2][2]*new Color(img.getRGB(i+1, j+1)).getRed());

               val = (float)sqrt(valx*valx+valy*valy);

               val = val/1443*255;
               if(val <= 127) {
                   val = 0;
               } else {
                   val = 255;
               }
               temp.setRGB(i, j, new Color((int)val,(int)val,(int)val).getRGB());
           }
           File outputfile = new File("src/image/edge.png");
           ImageIO.write(temp, "png", outputfile);
        }

Anything wrong about my code? Please help me. And this is the picture of the result.

Original Image:

Original Image

Result Image:

Resulted Image


Solution

  • There are different issues in your code:

    • When using a kernel of dimensions 3x3, you go from [1,1] to ]width-1,height-1[, not ]width-2, height-2[.
    • In java, use image.getRaster().getSample(x, y, channel), instead of 'new Color(img.getRGB(i-1, j-1)).getRed())'. It's going to be much faster and easier to understand. Same thing when writing image.getRaster().setSample(x, y, channel, value)
    • When computing a Sobel gradient on an image encoded on [0,max], each direction (X and Y) is going to give you values on [-4*max, 4*max]. So it's aggressive to cut the exceeded values. You may want to perform a histogram stretching instead, then you will keep much more information.
    • The normalization val = val/1443*255; is up to you, but not necessary.
    • And finally the main problem into your code. The resulting (or temp in your case) image and the original image MUST be different. Else you modify the image at the same time you process it. That explain why your have all this huge white area.