2012-07-27 6 views
0

이 sobel 연산자에 대한 아이디어는 먼저 각 픽셀의 값을 배열에 배치 한 다음이 값을 RGB 구성 요소마다 하나씩 3 개의 배열로 분리하는 것입니다. RGB 컴퍼넌트의 값을 포함한 배열은 각각 변환되어 출력 이미지를 생성하기위한 최종 배열로 결합됩니다.Sobel 연산자는 작은 이미지에만 적용됩니다

그러나 350x350 픽셀 크기의 작은 이미지에 대해서만 잘 작동하는 것으로 보입니다. 그 이유는 모르겠습니다.

이미지의 너비 대신 이미지 크기의 값을 하드 코어 할 때 문제가 있기 때문에 getRGB() 및 setRGB()에 대한 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? –

답변

0

이미지는 행 주요 형식으로 저장된다.

따라서 외부 루프는 행을 반복해야하며 (height 개의 반복이 있어야 함) 내부 루프는 각 행의 픽셀을 반복해야합니다 (반복은 width 회이어야 함). 따라서 기본적으로 widthheight을 교환해야합니다 (getRGB/setRGB).

+0

와우! for 루프와 배열에서 높이와 너비를 변경했으며 효과가있었습니다. 정말 고맙습니다! – ivandj

+0

이봐 요, 당신이 그것을 시도한다면이 소블 오퍼레이터의 결과에 대해 어떻게 생각합니까? – ivandj

+0

@ivandj : 나는 그것을 시도하지 않았고 코드를 빨리 보았습니다. 추가 질문에 대한 참고 사항 : 작동하지 않는 내용 ("코드가 제대로 실행되지만 출력이 이상하게 보입니다 *", 가능한 경우 질문과 함께 출력 이미지 게시)을 설명해야합니다. 더 많은 이미지를 사용하면 효과가없는 것을보다 정확하게 설명 할 수 있습니다. 실제 문제는 이미지의 절대 크기가 아니라 종횡비로 인한 것입니다. –

0

은 내부적으로 당신은 픽셀을 조작 자바에서 가장 느린 방법을 사용 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

를 사용 javacv를 사용하여 좋은 결과를 얻을 수 있습니다. Catalano Framework을 사용해보십시오. 여러 알고리즘이 병렬로 포함되어 있으며 Android에서 동일한 코드로 실행됩니다.

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

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

article에서 Sobel의 예를 볼 수 있습니다.