2017-12-03 13 views
1

이미지에서 소벨 가장자리 감지를 수행해야하는 학교 지정을하고 있습니다. 우리는 sobel 코어와 convolution을 수행하고 각 픽셀에 대한 gradient magnitude를 계산해야합니다. 그런 다음 임계 값 방법에 따라 임계 값에 따라 픽셀에 255 (흰색) 또는 0 (검정) 값을 지정해야합니다. 가장자리 감지 의 출력 이미지는이되어야합니다. BufferedImage.TYPE_BYTE_BINARY이어야합니다. 나는 그레이 스케일 이미지를 입력으로 사용하지만 endresult는 매우 이상하게 보입니다. 확실히 가장자리를 감지하지 못합니다.출력으로 BufferedImage.TYPE_BYTE_BINARY를 사용한 소벨 가장자리 감지

Google 검색을 통해 작업 코드 (here, 표시된 정답을 참조)를 찾을 수 있지만 여기서 출력 이미지는 허용되지 않는 BufferedImage.TYPE_INT_RGB 유형입니다 ...이 질문에서 BufferedImage.TYPE.INT.RGB를 엣지 검출의 인풋으로서 사용한다.

이 문제를 해결하는 데 도움을 주셔서 감사합니다.

결과가 프로그램을 실행하면. 가장자리 감지 결과가 맨 오른쪽에 있습니다. 에지 검출 결과 어떻게 보일지 enter image description here

. enter image description here

내 코드 :

/** 
* turns an image to a grayscale version of the image 
*/ 
public void alterImageGrayScale() throws IOException { 
    imageGrayScale = new BufferedImage(imageOriginal.getWidth(), imageOriginal.getHeight(), BufferedImage.TYPE_BYTE_GRAY); 

    for(int i = 0; i < imageOriginal.getWidth(); i++) { 
     for(int j = 0; j < imageOriginal.getHeight(); j++) { 
      Color c = new Color(imageOriginal.getRGB(i, j)); 
      int red = c.getRed(); 
      int green = c.getGreen(); 
      int blue = c.getBlue(); 
      int gray = (int) (0.2126*red + 0.7152*green + 0.0722*blue); 
      imageGrayScale.setRGB(i, j, new Color(gray, gray, gray).getRGB()); 
     } 
    } 
} 

/** 
* edge detection 
* @throws IOException 
*/ 
public void alterEdgeDetection() throws IOException { 
    imageBlackAndWhite = new BufferedImage(imageGrayScale.getWidth(), imageGrayScale.getHeight(), BufferedImage.TYPE_INT_RGB); 
    int x = imageGrayScale.getWidth(); 
    int y = imageGrayScale.getHeight(); 
    int threshold = 250; 

    for (int i = 1; i < x - 1; i++) { 
     for (int j = 1; j < y - 1; j++) { 

      int val00 = imageGrayScale.getRGB(i - 1, j - 1); 
      int val01 = imageGrayScale.getRGB(i - 1, j); 
      int val02 = imageGrayScale.getRGB(i - 1, j + 1); 
      int val10 = imageGrayScale.getRGB(i, j - 1); 
      int val11 = imageGrayScale.getRGB(i, j); 
      int val12 = imageGrayScale.getRGB(i, j + 1); 
      int val20 = imageGrayScale.getRGB(i + 1, j - 1); 
      int val21 = imageGrayScale.getRGB(i + 1, j); 
      int val22 = imageGrayScale.getRGB(i + 1, j + 1); 

      int gradientX = ((-1 * val00) + (0 * val01) + (1 * val02)) + ((-2 * val10) + (0 * val11) + (2 * val12)) 
        + ((-1 * val20) + (0 * val21) + (1 * val22)); 
      int gradientY = ((-1 * val00) + (-2 * val01) + (-1 * val02)) + ((0 * val10) + (0 * val11) + (0 * val12)) 
        + ((1 * val20) + (2 * val21) + (1 * val22)); 
      int gradientValue = (int) Math.sqrt(Math.pow(gradientX, 2) + Math.pow(gradientY, 2)); 

      //???? feel like something should be done here, but dont know what 

      if(threshold > gradientValue) { 
       imageBlackAndWhite.setRGB(i, j, new Color(0, 0, 0).getRGB()); 
      } else { 
       imageBlackAndWhite.setRGB(i, j, new Color(255, 255, 255).getRGB()); 
      } 

     } 
    } 
} 
+0

그레이 스케일 이미지를 'TYPE_BYTE_BINARY'로 변환하는 것이 좋다고 생각합니까? 그런 다음 기존의 에지 감지 코드를 사용하여 그레이 스케일 이미지를 생성하고 전용 방법의 마지막 단계로 "그레이 스케일 - 바이너리"변환 만 수행하면됩니다. – Marco13

+0

나는 그것이 좋을 것이라고 생각한다. 내가 제공 한 다른 stackoverflow 질문에는 완벽하게 작동하는 코드가 있으며, 유일한 결과는 최종 결과가 'TYPE_INT_RGB'이미지입니다. 최종 결과가 TYPE_BYTE_BINARY가되도록 코드를 변경하는 방법을 모르겠다. 질문에 글을 쓰면서 회색 음영을 입력으로해야한다고 생각하지 않습니다. 문제가 발생하는 경우. 나는 그레이 스케일링이 에지 검출의 "외부"에서 일어난다 고 생각했고, 그것을 명시 적으로 @ Marco13을위한 코드로 작성해야만한다고 생각했습니다. – Isus

답변

1

주석의 반응에 따르면, 형 TYPE_BYTE_BINARY의 화상에 엣지 검출 수단에 의해 계산 된 그레이 스케일 이미지로 변환하기에 충분해야한다.

다음은 질문에 링크 된 회색 음영 이미지 (가장자리 감지 결과 포함)를로드하고 이진 이미지로 변환하는 MCVE입니다.

이진 이미지로 변환 할 때 화면 하단의 슬라이더로 수정할 수있는 임계 값이 있습니다. 회색조 값이 각각 BLACK 또는 WHITE 픽셀로 변환 될 것인지 결정합니다.

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.GridLayout; 
import java.awt.image.BufferedImage; 
import java.net.URL; 

import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.SwingUtilities; 

public class ImageToBinary 
{ 
    public static void main(String[] args) throws Exception 
    { 
     BufferedImage input = 
      ImageIO.read(new URL("https://i.stack.imgur.com/jvOan.png"));   

     BufferedImage output = convertToBinary(input, 10); 

     SwingUtilities.invokeLater(() -> createAndShowGui(input, output)); 
    } 

    private static void createAndShowGui(
     BufferedImage input, BufferedImage output) 
    { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel p = new JPanel(new GridLayout(1,2)); 
     JLabel outputLabel = new JLabel(new ImageIcon(output)); 
     p.add(new JLabel(new ImageIcon(input)));  
     p.add(outputLabel); 
     f.getContentPane().setLayout(new BorderLayout()); 
     f.getContentPane().add(p, BorderLayout.NORTH); 

     JSlider slider = new JSlider(0, 256, 10); 
     slider.addChangeListener(e -> 
     { 
      int threshold = slider.getValue(); 
      BufferedImage newOutput = convertToBinary(input, threshold); 
      outputLabel.setIcon(new ImageIcon(newOutput)); 
     }); 

     f.getContentPane().add(slider, BorderLayout.SOUTH); 
     f.pack(); 

     f.setLocationRelativeTo(null); 
     f.setVisible(true); 

    } 

    private static BufferedImage convertToBinary(
     BufferedImage input, int threshold) 
    { 
     int w = input.getWidth(); 
     int h = input.getHeight(); 
     BufferedImage output = new BufferedImage(
      w, h, BufferedImage.TYPE_BYTE_BINARY); 

     int blackRgb = Color.BLACK.getRGB(); 
     int whiteRgb = Color.WHITE.getRGB(); 

     for (int y = 0; y < h; y++) 
     { 
      for (int x = 0; x < w; x++) 
      { 

       int rgb = input.getRGB(x, y); 
       int r = (rgb >> 16) & 0xFF; 
       int g = (rgb >> 8) & 0xFF; 
       int b = (rgb) & 0xFF; 
       int gray = (int) (0.2126 * r + 0.7152 * g + 0.0722 * b); 
       if (gray >= threshold) 
       { 
        output.setRGB(x, y, whiteRgb); 
       } 
       else 
       { 
        output.setRGB(x, y, blackRgb); 
       } 
      } 
     } 
     return output; 
    }   

} 
+0

코드가 잘 작동합니다! 나는 지금 개종 사업을 할 수 있었다. 나는 당신이 슬라이더와 함께 제공 한 예제를 좋아하는데, 도움을 주셔서 감사합니다. 왜 우리는'rgb >> 16) & 0xFF'를하고 있습니까? 이 코드는 @ Marco13 전에 본 적이 없습니다. – Isus

+0

자세한 내용은 [이 답변] (https://stackoverflow.com/a/2615537/3182664)을 참조하십시오. 참고 : 이미 허용 된 대답은'Color' 개체와 함께 이미 수행 한 것입니다.하지만 'Color'객체로 이미지/픽셀 조작을하는 것은 비효율적 인 경향이 있습니다. 가능한 경우 RGB'int '값으로 작업해야합니다. – Marco13

+0

추가 조언과 링크를 제공해 주셔서 감사합니다. @ Marco13 – Isus