这个 sobel 算子的想法是首先将每个像素的值放入数组中,然后将这些值分成三个数组,一个用于每个 RGB 分量。然后将包含 RGB 分量值的数组分别转换,然后组合成最终数组以生成输出图像。
但是,它似乎只适用于大约 350x350 像素大小的较小图像,我不知道为什么。
我认为问题出在 getRGB() 和 setRGB() 的 scansize 参数中,因为当我硬核化 scansize 的图像高度值而不是图像宽度时,它会起作用。
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;
}
}