The idea for this sobel operator is to first place value of each pixel into the array and then to separate these values into three arrays, one for each RGB component. The arrays containing the values of RGB components are each then transformed and then combined into final array for generating the output image.
However, it appears that it works well only for smaller images about the size of 350×350 px and I don’t know why.
I think that the problem is in the scansize parameter for getRGB() and setRGB(), since it works when I hardcore the value of the image height for scansize instead of the image width.
public class Sobel {
private BufferedImage image;
public Sobel(BufferedImage image)
{
this.image = image;
}
public BufferedImage process()
{
double A[][], B[][], Ar[][], Br[][], Ag[][], Bg[][], Ab[][], Bb[][], G[][], Gr[][], Gg[][], Gb[][];
BufferedImage inImg = image;
int width = inImg.getWidth();
int height = inImg.getHeight();
int[] pixels = new int[width * height];
// RGB channels of the image
int[][] red = new int[width][height];
int[][] green = new int[width][height];
int[][] blue = new int[width][height];
try {
image.getRGB(0, 0, width, height, pixels, 0, width);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int counter = 0;
for(int i = 0 ; i < width ; i++ )
{
for(int j = 0 ; j < height ; j++ )
{
// get color of each pixel and separate it in the RGB components
Color c = new Color(pixels[counter]);
red[i][j] = c.getRed();
green[i][j] = c.getGreen();
blue[i][j] = c.getBlue();
counter = counter + 1;
}
}
// Arrays for RGB values (Ar, Br, Ag, Bg, Ab, Bb) which are than combined into final array for generating processed image
A = new double[width][height];
B = new double[width][height];
Ar = new double[width][height];
Br = new double[width][height];
Ag = new double[width][height];
Bg = new double[width][height];
Ab = new double[width][height];
Bb = new double[width][height];
G = new double[width][height];
Gr = new double[width][height];
Gg = new double[width][height];
Gb = new double[width][height];
/**
* Transform pixel p of each RGB channel
* p = sqrt(A^2 + B^2),
* where A = (p3 + 2*p4 + p5) - (p1 + 2*p8 + p7)
* and B = (p1 + 2*p2 + p3) - (p7 + 2*p6 + p5)
*
* Pixel p
*
* p1 p2 p3
* p8 p p4
* p7 p6 p5
*/
for (int i=0; i<width; i++) {
for (int j=0; j<height; j++) {
if (i==0 || i==width-1 || j==0 || j==height-1)
A[i][j] = B[i][j] = G[i][j] = Ar[i][j] = Br[i][j] = Gr[i][j] = Ag[i][j] = Bg[i][j] = Gg[i][j] = Ab[i][j] = Bb[i][j] = Gb[i][j] = 0; // Image boundary cleared
else
{
// RED CHANNEL
Ar[i][j] = red[i-1][j+1] + 2*red[i][j+1] + red[i+1][j+1] - red[i-1][j-1] - 2*red[i][j-1] - red[i+1][j-1];
Br[i][j] = red[i-1][j-1] + 2*red[i-1][j] + red[i-1][j+1] - red[i+1][j-1] - 2*red[i+1][j] - red[i+1][j+1];
Gr[i][j] = Math.sqrt(Ar[i][j]*Ar[i][j] + Br[i][j]*Br[i][j]);
// GREEN CHANNEL
Ag[i][j] = green[i-1][j+1] + 2*green[i][j+1] + green[i+1][j+1] - green[i-1][j-1] - 2*green[i][j-1] - green[i+1][j-1];
Bg[i][j] = green[i-1][j-1] + 2*green[i-1][j] + green[i-1][j+1] - green[i+1][j-1] - 2*green[i+1][j] - green[i+1][j+1];
Gg[i][j] = Math.sqrt(Ag[i][j]*Ag[i][j] + Bg[i][j]*Bg[i][j]);
// BLUE CHANNEL
Ab[i][j] = blue[i-1][j+1] + 2*blue[i][j+1] + blue[i+1][j+1] - blue[i-1][j-1] - 2*blue[i][j-1] - blue[i+1][j-1];
Bb[i][j] = blue[i-1][j-1] + 2*blue[i-1][j] + blue[i-1][j+1] - blue[i+1][j-1] - 2*blue[i+1][j] - blue[i+1][j+1];
//System.out.println(output[i][j]);
Gb[i][j] = Math.sqrt(Ab[i][j]*Ab[i][j] + Bb[i][j]*Bb[i][j]);
//if((int)Gg[i][j] > 255) System.out.println("GREEN : " + Gg[i][j] + " ~ " + (int)Gg[i][j] + "\n" + green[i-1][j+1] + " " + green[i][j+1] + " " + green[i+1][j+1] + " " + green[i-1][j-1] + " " + green[i][j-1] + " " + green[i+1][j-1] + " " + green[i-1][j-1] + " " + green[i-1][j] + " " + green[i-1][j+1] + " " + green[i+1][j] + " " + green[i+1][j] + " " + green[i+1][j+1]);
if((int)Gg[i][j] > 255) {Gg[i][j] = 255; }
if((int)Gb[i][j] > 255) {Gb[i][j] = 255; }
if((int)Gr[i][j] > 255) {Gr[i][j] = 255; }
G[i][j] = new Color((int)Gr[i][j], (int)Gg[i][j], (int)Gb[i][j]).getRGB();
}
}
}
counter = 0;
for(int ii = 0 ; ii < width ; ii++ )
{
for(int jj = 0 ; jj < height ; jj++ )
{
pixels[counter] = (int)G[ii][jj];
counter = counter + 1;
}
}
BufferedImage outImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
System.out.println("pixels.length = " + pixels.length + "; Image size: " + outImg.getHeight() + "x" + outImg.getWidth());
//outImg.getRaster().setPixels(0,0,width,height,pixels);
outImg.setRGB(0, 0, width, height, pixels, 0, width);
return outImg;
}
}
Images are stored in row-major format.
So the outer loop should be iterating over rows (there should be
heightiterations), and the inner loop should be iterating over the pixels in each row (there should bewidthiterations). So basically you need to swapwidthandheighteverywhere except on the calls togetRGB/setRGB.