首页 文章

使用BufferedImage.TYPE_BYTE_BINARY作为输出进行Sobel边缘检测

提问于
浏览
1

我正在做一个学校作业,我们应该对图像进行索贝尔边缘检测 . 我们应该用sobel核心进行卷积,然后计算每个像素的梯度幅度 . 之后,我们应该使用阈值方法为像素提供值255(白色)或0(黑色),具体取决于阈值 . 边缘检测 must 的输出图像属于 BufferedImage.TYPE_BYTE_BINARY 类型 . 我使用灰度图像作为输入,但结果看起来非常奇怪..它绝对不会检测到边缘 .

我google了一下,设法找到工作代码(here,看到标记的正确答案),但是,这里的输出图像是BufferedImage.TYPE_INT_RGB类型,这是不允许的...在这个问题中,也使用BufferedImage . TYPE.INT.RGB作为边缘检测的输入 .

非常感谢帮助解决这个问题!

Result when I execute the program. The edge detection result is on the far right.
enter image description here

What the edge detection result should look like.
enter image description here

My code:

/**
 * 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());
            }

        }
    }
}

1 回答

  • 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;
        }        
    
    }
    

相关问题