【发布时间】:2018-05-17 01:19:16
【问题描述】:
我正在做一项学校作业,我们应该对图像进行 sobel 边缘检测。我们应该使用 sobel 核 och 进行卷积,然后计算每个像素的梯度幅度。之后,我们应该使用阈值方法给像素值 255(白色)或 0(黑色),具体取决于阈值。边缘检测的输出图像必须为 BufferedImage.TYPE_BYTE_BINARY 类型。我使用灰度图像作为输入,但最终结果看起来很奇怪..它绝对没有检测到边缘。
我四处搜索并设法找到工作代码(here,请参阅标记的正确答案),但是,这里的输出图像是 BufferedImage.TYPE_INT_RGB 类型,这是不允许的......在这个问题中,还使用 BufferedImage.TYPE.INT.RGB 作为边缘检测的输入。
非常感谢您帮助解决此问题!
我的代码:
/**
* 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());
}
}
}
}
【问题讨论】:
-
你认为只用
TYPE_BYTE_BINARY将灰度图像转换成一张就可以了吗?然后你可以只使用现有的边缘检测代码来生成灰度图像,并且只做一个“灰度到二进制”的转换作为专用方法的最后一步。 -
我认为没关系。我提供的另一个 stackoverflow 问题的代码可以完美运行,唯一的问题是最终结果是带有
TYPE_INT_RGB的图像。我不明白如何更改代码以使最终结果为TYPE_BYTE_BINARY。如果这会引起麻烦,我认为我不需要像我在问题中所写的那样将灰度作为输入。我认为灰度发生在边缘检测“之外”,我必须明确地为此编写代码@Marco13
标签: java image-processing edge-detection sobel