0

这个 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;
}

}

4

3 回答 3

0

图像以行优先格式存储。

So the outer loop should be iterating over rows (there should be height iterations), and the inner loop should be iterating over the pixels in each row (there should be width iterations). So basically you need to swap width and height everywhere except on the calls to getRGB/setRGB.

于 2012-07-27T12:21:30.400 回答
0

It is possible to get the good result using javacv which internally uses opencv

  IplImage iploriginal = IplImage.createFrom(originalBufferedImg);

  IplImage srcimg = IplImage.create(iploriginal.width(),iploriginal.height(), IPL_DEPTH_8U, 1);

  IplImage destimg = IplImage.create(iploriginal.width(),iploriginal.height(), IPL_DEPTH_8U, 1);

  cvCvtColor(iploriginal, srcimg, CV_BGR2GRAY);

  cvSmooth(srcimg, destimg, CV_BLUR,9, 9, 2, 2);

  cvSobel(srcimg, destimg,0,1,3);

  BufferedImage img=destimg.getBufferedImage();
于 2013-04-25T14:10:26.297 回答
0

You are using the slowest method in Java for manipulate the pixels. Try to use Catalano Framework. Contains several algorithm in parallel and run in Android with the same code.

FastBitmap fb = new FastBitmap(bufferedImage);
fb.toGrayscale();

SobelEdgeDetector sobel = new SobelEdgeDetector();
sobel.applyInPlace(fb);

You can see an example with Sobel in this article.

于 2014-02-05T17:38:27.670 回答