我正在尝试用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);
}
}
......................................
答案 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;
}
}
<强>输出强>
修改强>
第二张图片包含与第一张图片相对的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;
我已使用相同的内容更改了上面的原始代码。
此处有更改输出。
要获得评论中图像中的边缘,您必须根据渐变的方向对边缘进行分组,并使用合适的阈值来忽略弱边缘。