我正在做一个关于中值滤波器的程序。所有我想要完成的是获取一个像素值,找到它的相邻像素,并将它们存储在一个数组中,对该数组进行排序,并取中间值(对于大小为9的数组,中间值为索引位置4)。并将该值替换为与所考虑的像素完全相同的坐标。
如果我删除其内容并只打印i,j,x,y
的值,则循环可以正常工作。我添加语句的那一刻,我neighborhoodVal.add(imageRaster.getSample(x, y, 0));
我收到java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
错误。
根据我的观察,当j
的值变为1
时,我发现i
的值变为264
,这很奇怪,因为我只循环所有像素在图像中,外部的两个循环(i和j)循环遍历除了图像边缘处的像素之外的所有像素。内圈(x
& y
)遍历[i][j]
像素的所有8个邻居。
我正在使用的图片有width = 265
和height=269
。
代码如下:
public class MedianFilter {
public static void main(String[] args) throws IOException {
int i, j, x, y;
ArrayList<Integer> neighborhoodVal = new ArrayList<Integer>();
;
String imagePath = "images/assignment10/noisyShapes.jpg";
BufferedImage inputImage = convertToGrayScale(ImageIO.read(new File(
imagePath)));
WritableRaster imageRaster = inputImage.getRaster();
BufferedImage filteredImage = new BufferedImage(inputImage.getWidth(),
inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
WritableRaster newWRaster = filteredImage.getRaster();
for (i = 1; i < imageRaster.getHeight()-1; i++) {
for (j = 1; j < imageRaster.getWidth()-1; j++) {
for (x = Math.max(0, i - 1); x <= Math.min(i + 1,imageRaster.getWidth()); x++) {
for (y = Math.max(0, j - 1); y <= Math.min(j + 1,imageRaster.getHeight()); y++) {
System.out.println(i+","+j+"------->"+x+","+y);
neighborhoodVal.add(imageRaster.getSample(x, y, 0));
Collections.sort(neighborhoodVal);
}
}
newWRaster.setSample(i, j, 0, (neighborhoodVal
.get((neighborhoodVal.size() / 2) + 1)));
neighborhoodVal.clear();
}
}
File f = new File("images/assignment10/medianFilterOutput.jpg");
ImageIO.write(filteredImage, "JPG", f);
}
public static BufferedImage convertToGrayScale(BufferedImage givenImage)
throws IOException {
// TODO Auto-generated method stub
BufferedImage image = new BufferedImage(givenImage.getWidth(),
givenImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
Graphics grp = image.getGraphics();
grp.drawImage(givenImage, 0, 0, null);
return image;
}
}
我正在使用这张图片:
j
如何成为1?我在哪里错了?
答案 0 :(得分:1)
在外部循环中,您使用带有.getHeight()的“i”,但在内部循环中,“x”与.getWidth()一起使用。因此看起来需要交换i和j的边界。这可能是疲倦的错字;我可能会在下面的示例代码中自己完成。
此外,由于外环已经忽略了边界像素,内部循环可能只是“for(x = i - 1; i&lt; = i + 1; i ++”和“for(y = j - 1; y) &lt; = j + 1; j ++)“并保证在界限范围内。
如果我可以提出建议:在图像处理中,通常在最外层循环中逐行扫描(即“y”),然后扫描x,并使用(x,y)作为像素坐标和(i,j)偏移量。例如:
int r = 1; //radius, in case you want to use median over a larger kernel
for(int y = r; y < height - r; y++)
{
for (int x = r; x < width - r; x++)
{
for(int j = y - r; j <= y + r; j++)
{
for(i = x - r; i <= x + r; i++)
{
//get all neighborhood values
}
}
//find median
}
}
那就是说,一旦你使用了一个约定,坚持下去。意外地交换getWidth()和getHeight()边界很容易,但是如果你总是以y,x,j,i的相同顺序嵌套你的循环,那你就更有可能在不考虑它的情况下键入正确的边界