【问题标题】:Sobel Edge Detecting program in javajava中的Sobel边缘检测程序
【发布时间】:2017-01-11 09:40:25
【问题描述】:

我正在尝试用 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);
  }
  }

输入图像:

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

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

【问题讨论】:

  • 仅作记录:您不会来这里订购/要求“提供有效的解决方案”。你试着问一个好问题;然后我们看看我们做了什么。但这很少意味着有人会放弃一个可行的解决方案!从这个意义上说:简单地避免这样的陈述;他们可以过来一点...粗鲁...
  • 提示:您仍然可以编辑您的问题 ;-)
  • 收到消息,完成。

标签: java algorithm


【解决方案1】:

您的代码存在两个问题。首先是代码应该在计算中使用颜色分量(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&lt;&lt;16 | g&lt;&lt;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;
    }
}

输出

编辑

第二张图片包含一个与第一张相反的 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 设置为不透明。

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

我已经用相同的方式更改了上面的原始代码。

这是更改后的输出。

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 2020-04-06
  • 2016-11-07
相关资源
最近更新 更多