我的 Sobel 边缘检测运算符输出很奇怪
My Sobel Edge Detection Operator Output is weird
我的 Sobel 边缘检测算子输出很奇怪。
这是我的代码:
BufferedImage temp = img;
float kernelx[][] = {{-1, 0, 1},{-2, 0, 2},{-1, 0, 1}};
float kernely[][] = {{-1, -2, -1},{0, 0, 0},{1, 2, 1}};
float valx = 0;
float valy = 0;
float val = 0;
for(int i=1;i<width-2;i++) {
for(int j=1;j<height-2;j++) {
valx = (kernelx[0][0]*new Color(img.getRGB(i-1, j-1)).getRed()) + (kernelx[0][2]*new Color(img.getRGB(i+1, j-1)).getRed()) +
(kernelx[1][0]*new Color(img.getRGB(i-1, j)).getRed()) + (kernelx[1][2]*new Color(img.getRGB(i+1, j)).getRed()) +
(kernelx[2][0]*new Color(img.getRGB(i-1, j+1)).getRed()) + (kernelx[2][2]*new Color(img.getRGB(i+1, j+1)).getRed());
valy = (kernely[0][0]*new Color(img.getRGB(i-1, j-1)).getRed()) + (kernely[0][1]*new Color(img.getRGB(i, j-1)).getRed()) + (kernely[0][2]*new Color(img.getRGB(i+1, j-1)).getRed()) +
(kernely[2][0]*new Color(img.getRGB(i-1, j+1)).getRed()) + (kernely[2][1]*new Color(img.getRGB(i, j+1)).getRed()) + (kernely[2][2]*new Color(img.getRGB(i+1, j+1)).getRed());
val = (float)sqrt(valx*valx+valy*valy);
val = val/1443*255;
if(val <= 127) {
val = 0;
} else {
val = 255;
}
temp.setRGB(i, j, new Color((int)val,(int)val,(int)val).getRGB());
}
File outputfile = new File("src/image/edge.png");
ImageIO.write(temp, "png", outputfile);
}
我的代码有什么问题吗?请帮我。
这是结果的图片。
原图:
结果图片:
您的代码中存在不同的问题:
- 当使用尺寸为 3x3 的内核时,您从 [1,1] 变为 ]width-1,height-1[,而不是 ]width-2,height-2[.
- 在java中,使用image.getRaster().getSample(x, y, channel),而不是'new Color(img.getRGB(i-1, j-1)).getRed())'。它将变得更快、更容易理解。写
image.getRaster().setSample(x, y, channel, value)
时也是一样
- 当在 [0,max] 上编码的图像上计算 Sobel 梯度时,每个方向(X 和 Y)都会为您提供 [-4*max, 4*max] 上的值。因此,削减超出的值是积极的。您可能想要执行直方图拉伸,这样您将保留更多信息。
- 规范化
val = val/1443*255;
由您决定,但不是必需的。
- 最后 主要问题 进入您的代码。结果(或在您的情况下为临时)图像和原始图像必须不同。否则您在处理图像的同时修改图像。这就解释了为什么你有这么大的白色区域。
我的 Sobel 边缘检测算子输出很奇怪。 这是我的代码:
BufferedImage temp = img;
float kernelx[][] = {{-1, 0, 1},{-2, 0, 2},{-1, 0, 1}};
float kernely[][] = {{-1, -2, -1},{0, 0, 0},{1, 2, 1}};
float valx = 0;
float valy = 0;
float val = 0;
for(int i=1;i<width-2;i++) {
for(int j=1;j<height-2;j++) {
valx = (kernelx[0][0]*new Color(img.getRGB(i-1, j-1)).getRed()) + (kernelx[0][2]*new Color(img.getRGB(i+1, j-1)).getRed()) +
(kernelx[1][0]*new Color(img.getRGB(i-1, j)).getRed()) + (kernelx[1][2]*new Color(img.getRGB(i+1, j)).getRed()) +
(kernelx[2][0]*new Color(img.getRGB(i-1, j+1)).getRed()) + (kernelx[2][2]*new Color(img.getRGB(i+1, j+1)).getRed());
valy = (kernely[0][0]*new Color(img.getRGB(i-1, j-1)).getRed()) + (kernely[0][1]*new Color(img.getRGB(i, j-1)).getRed()) + (kernely[0][2]*new Color(img.getRGB(i+1, j-1)).getRed()) +
(kernely[2][0]*new Color(img.getRGB(i-1, j+1)).getRed()) + (kernely[2][1]*new Color(img.getRGB(i, j+1)).getRed()) + (kernely[2][2]*new Color(img.getRGB(i+1, j+1)).getRed());
val = (float)sqrt(valx*valx+valy*valy);
val = val/1443*255;
if(val <= 127) {
val = 0;
} else {
val = 255;
}
temp.setRGB(i, j, new Color((int)val,(int)val,(int)val).getRGB());
}
File outputfile = new File("src/image/edge.png");
ImageIO.write(temp, "png", outputfile);
}
我的代码有什么问题吗?请帮我。 这是结果的图片。
原图:
结果图片:
您的代码中存在不同的问题:
- 当使用尺寸为 3x3 的内核时,您从 [1,1] 变为 ]width-1,height-1[,而不是 ]width-2,height-2[.
- 在java中,使用image.getRaster().getSample(x, y, channel),而不是'new Color(img.getRGB(i-1, j-1)).getRed())'。它将变得更快、更容易理解。写
image.getRaster().setSample(x, y, channel, value)
时也是一样
- 当在 [0,max] 上编码的图像上计算 Sobel 梯度时,每个方向(X 和 Y)都会为您提供 [-4*max, 4*max] 上的值。因此,削减超出的值是积极的。您可能想要执行直方图拉伸,这样您将保留更多信息。
- 规范化
val = val/1443*255;
由您决定,但不是必需的。 - 最后 主要问题 进入您的代码。结果(或在您的情况下为临时)图像和原始图像必须不同。否则您在处理图像的同时修改图像。这就解释了为什么你有这么大的白色区域。