2012-07-27 33 views
0

該sobel算子的思想是首先將每個像素的值放入數組中,然後將這些值分爲三個數組,每個RGB組分一個。包含RGB分量值的數組每次都要進行變換,然後組合成最終數組以生成輸出圖像。Sobel Operator只適用於小圖像

但是,它似乎只適用於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; 
} 

}

+0

你是什麼意思不起作用? OutOfMemoryException異常? – 2012-07-27 12:10:26

回答

0

圖像存儲在列優先格式。因此,外層循環應該迭代行(應該有height迭代),並且內層循環應該遍歷每行中的像素(迭代應該有width)。所以基本上你需要交換widthheight,除了撥打電話getRGB/setRGB

+0

哇!我已經改變了循環和數組的高度和寬度,它工作。非常感謝! – ivandj 2012-07-30 09:32:43

+0

嘿,我只是想知道如果你嘗試了這個sobel算子,你對這個結果有什麼看法? – ivandj 2012-07-30 09:34:04

+0

@ivandj:我沒有嘗試,我只是快速查看了代碼。進一步的問題請注意:你應該描述什麼不起作用(「*代碼正確執行,但輸出看起來很奇怪*」;如果可能,將輸出圖像與問題一起發佈),並且您應該嘗試過更多圖像,以便您可以更準確地描述什麼不起作用:實際問題來自縱橫比,而不是圖像的絕對大小。 – 2012-07-30 09:39:14

0

有可能使用javacv它在內部使用了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(); 
0

您使用的是最慢的方法在Java中用於操縱像素,以獲得良好的效果。嘗試使用Catalano Framework。包含多個並行算法,並使用相同的代碼在Android中運行。

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

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

您可以在此article中看到Sobel的示例。