Sobel filter not working correctly

I wrote a class for the Sobel operator to detect borders, but when I use the sample image, my edges are disabled. Really appreciate this if someone can help me with this.

import java.awt.image.BufferedImage; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import java.awt.image.Raster; import java.util.Arrays; class SobelFilter { private static final float[] sobel1 = { 1.0f, 0.0f, -1.0f}; private static final float[] sobel2 = { 1.0f, 2.0f, 1.0f}; private static final boolean[] sobelBoolean = {true, false}; private SobelFilter() {} private static ConvolveOp getSobelX(boolean fs) { Kernel kernel = null; if (fs) { kernel = new Kernel(1, 3, sobel1); } else { kernel = new Kernel(3, 1, sobel2); } return new ConvolveOp(kernel, ConvolveOp.EDGE_ZERO_FILL, null); } private static ConvolveOp getSobelY(boolean fs) { Kernel kernel = null; if (fs) { kernel = new Kernel(1, 3, sobel2); } else { kernel = new Kernel(3, 1, sobel1); } return new ConvolveOp(kernel, ConvolveOp.EDGE_ZERO_FILL, null); } public static BufferedImage getSobelFilter(BufferedImage img) { int width = img.getWidth(); int height = img.getHeight(); int size = width * height; int[] x = new int[size]; int[] y = new int[size]; int[] pixelM = new int[size]; //double[] pixelD = new double[size]; BufferedImage sobelX = null; BufferedImage sobelY = null; for(boolean i : sobelBoolean) { sobelX = getSobelX(i).filter(img, null); sobelY = getSobelY(i).filter(img, null); } sobelX.getRaster().getPixels(0, 0, width, height, x); sobelY.getRaster().getPixels(0, 0, width, height, y); for(int i = 0; i < size; i++) { pixelM[i] = (int) Math.hypot(x[i], y[i]); //pixelD[i] = Math.atan2((double) y[i], (double) x[i]); } BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); result.getRaster().setPixels(0, 0, width, height, pixelM); return result; } } 

As an example, I used the valve image from Wikipedia.

Source test image

original

Expected Result

expected

Actual result

Actual Result

+5
source share
1 answer

What you built is the Y component of the gradient. Consider this:

 g2.drawImage(sobelX, null, 0, 0); g2.drawImage(sobelY, null, 0, 0); 

sobelX hiding behind sobelY , so you only see the last.

What you want is the norm of the gradient . You will need to scan both images and calculate z = sqrt(x*x + y*y) for each pixel x sobelX and its corresponding y sobelY .

pseudo code:

 norm = image of the same size of sobelX and sobelY; for (int x = 0; x < horizontal dimension of the image; ++x) { for (int y = 0; y < vertical dimension of the image; ++y) { xPixel = sobelX.pixelAt(x,y); yPixel = sobelY.pixelAt(x,y); norm.pixelAt(x,y) = Math.hypot(xPixel, yPixel); } } return norm; 
+2
source

Source: https://habr.com/ru/post/1209161/


All Articles