java中的Sobel Edge检测程序

时间:2017-01-04 16:25:02

标签: java algorithm

我正在尝试用java编写一个sobel边缘检测程序。但我得到的是输出。救命。这是我的计划。

import java.io.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Scanner;
import java.lang.Math;

public class sobeltest
{
  public static void main(String args[]) throws IOException{

    System.out.println("Enter the file name :");
    Scanner ne1=new Scanner(System.in);
    String filename=ne1.nextLine();


   File file= new File(filename);
   BufferedImage image = ImageIO.read(file);

   int x=image.getWidth();
   int y=image.getHeight();

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

     int val00=image.getRGB(i-1,j-1);
     int val01=image.getRGB(i-1,j);
     int val02=image.getRGB(i-1,j+1);

     int val10=image.getRGB(i,j-1);
     int val11=image.getRGB(i,j);
     int val12=image.getRGB(i,j+1);

     int val20=image.getRGB(i+1,j-1);
     int val21=image.getRGB(i+1,j);
     int val22=image.getRGB(i+1,j+1);

     int gx=(((-1*val00)+(0*val01)+(1*val02))+((-2*val10)+(0*val11)+(2*val12))+((-1*val20)+(0*val21)+(1*val22)));
     int gy=(((-1*val00)+(-2*val01)+(-1*val02))+((0*val10)+(0*val11)+(0*val12))+((1*val20)+(2*val21)+(1*val22)));

     double gval=Math.sqrt((gx*gx)+(gy*gy));
     int g=(int)gval;

     image.setRGB(i,j,g);

      }
      }
    File outputfile = new File("sobel.png");
    ImageIO.write(image, "png", outputfile);
  }
  }

输入图像: This is input image i given

这是我运行代码时得到的输出。 OUTPUT IMAGE

......................................

1 个答案:

答案 0 :(得分:3)

您的代码存在两个问题。首先,代码应该在计算中使用颜色分量(R,G,B)而不是颜色整数本身。

int val00=image.getRGB(i-1,j-1);
//Should be
int val00 = getGrayScale(image.getRGB(i - 1, j - 1));

Where getGrayScale() gives the luminance of the color in gray scale, otherwise you can use all three components individually.

第二个问题是您直接将gcal or g渐变值设置为颜色。这应该只是一个组件,应该使用g<<16 | g<<8 | g转换为颜色。

但g不一定在0-255范围内,因此我们必须通过查找最大g然后使用255/max(g)对所有渐变进行标准化来处理这个问题。

以下是工作代码。

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class SobelTest {
    public static void main(String args[]) throws IOException {

        System.out.println("Started");
        /*System.out.println("Enter the file name :");
        Scanner ne1 = new Scanner(System.in);
        String filename = ne1.nextLine();*/

        String filename = "engine.png";

        File file = new File(filename);
        BufferedImage image = ImageIO.read(file);

        int x = image.getWidth();
        int y = image.getHeight();

        int maxGval = 0;
        int[][] edgeColors = new int[x][y];
        int maxGradient = -1;

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

                int val00 = getGrayScale(image.getRGB(i - 1, j - 1));
                int val01 = getGrayScale(image.getRGB(i - 1, j));
                int val02 = getGrayScale(image.getRGB(i - 1, j + 1));

                int val10 = getGrayScale(image.getRGB(i, j - 1));
                int val11 = getGrayScale(image.getRGB(i, j));
                int val12 = getGrayScale(image.getRGB(i, j + 1));

                int val20 = getGrayScale(image.getRGB(i + 1, j - 1));
                int val21 = getGrayScale(image.getRGB(i + 1, j));
                int val22 = getGrayScale(image.getRGB(i + 1, j + 1));

                int gx =  ((-1 * val00) + (0 * val01) + (1 * val02)) 
                        + ((-2 * val10) + (0 * val11) + (2 * val12))
                        + ((-1 * val20) + (0 * val21) + (1 * val22));

                int gy =  ((-1 * val00) + (-2 * val01) + (-1 * val02))
                        + ((0 * val10) + (0 * val11) + (0 * val12))
                        + ((1 * val20) + (2 * val21) + (1 * val22));

                double gval = Math.sqrt((gx * gx) + (gy * gy));
                int g = (int) gval;

                if(maxGradient < g) {
                    maxGradient = g;
                }

                edgeColors[i][j] = g;
            }
        }

        double scale = 255.0 / maxGradient;

        for (int i = 1; i < x - 1; i++) {
            for (int j = 1; j < y - 1; j++) {
                int edgeColor = edgeColors[i][j];
                edgeColor = (int)(edgeColor * scale);
                edgeColor = 0xff000000 | (edgeColor << 16) | (edgeColor << 8) | edgeColor;

                image.setRGB(i, j, edgeColor);
            }
        }

        File outputfile = new File("sobel.png");
        ImageIO.write(image, "png", outputfile);

        System.out.println("max : " + maxGradient);
        System.out.println("Finished");
    }

    public static int  getGrayScale(int rgb) {
        int r = (rgb >> 16) & 0xff;
        int g = (rgb >> 8) & 0xff;
        int b = (rgb) & 0xff;

        //from https://en.wikipedia.org/wiki/Grayscale, calculating luminance
        int gray = (int)(0.2126 * r + 0.7152 * g + 0.0722 * b);
        //int gray = (r + g + b) / 3;

        return gray;
    }
}

<强>输出

enter image description here

修改

第二张图片包含与第一张图片相对的Alpha通道,请参阅下面的详细信息。

#Engine
type = 5 ColorModel: #pixelBits = 24 numComponents = 3 has alpha = false
#Type 5 is BufferedImage.TYPE_3BYTE_BGR
#Girl
type = 6 ColorModel: #pixelBits = 32 numComponents = 4 has alpha = true
#type 6 is BufferedImagef.TYPE_4BYTE_ABGR

由于第二张图片包含alpha分量而我们没有设置alpha,因此它变得完全透明。

以下部分代码需要更改为将alpha设置为opaque。

edgeColor = (edgeColor << 16) | (edgeColor << 8) | edgeColor;
//Should be
edgeColor = 0xff000000 | (edgeColor << 16) | (edgeColor << 8) | edgeColor;

我已使用相同的内容更改了上面的原始代码。

此处有更改输出。

enter image description here

要获得评论中图像中的边缘,您必须根据渐变的方向对边缘进行分组,并使用合适的阈值来忽略弱边缘。