Java 中的均值和中值图像滤波
Mean and Median Image Filtering in Java
作为一个简短的序言,我想为提出这样一个非常愚蠢的问题而道歉。
现在,正确的问题 - 我们的任务是为我们的学习计划编写一个简单的 Mean/Median(两者)过滤器,稍后将作为更高级过滤器类型的介绍和基础。
我已经研究了内核 2D 矩阵如何工作并在图像数据矩阵上流动(至少,我希望我了解它应该如何工作),但我 运行 遇到了一个问题我的代码。我使用以下代码过滤的每个图像都显示为单一颜色,通常是从左上角开始的第一种颜色。我确定错误可能很小,但我似乎找不到它。
如果你们能看一看,我将不胜感激。
public void medianFilter(){
System.out.println("Initializing 2nd image.");
initializeAltImage(); // <-- Preps a blank image the same size as the original.
System.out.println("2nd image initialized.");
int kernelwidth = 3;
int kernelheight = 3;
int[] rMedian = new int [kernelwidth*kernelheight];
int[] gMedian = new int [kernelwidth*kernelheight];
int[] bMedian = new int [kernelwidth*kernelheight];
int kerneliter = 0;
// Walk the entire image but stop before you go out of bounds at the kernel boundraries.
for (int i = 0; i<this.x-kernelwidth; i++){
for (int j=0; j<this.y-kernelheight; j++){
// Walk the kernel itself.
for (int ki = i; ki<kernelwidth; ki++){
for(int kj = j; kj<kernelheight; kj++){
Color col = new Color(this.img.getRGB(ki, kj));
rMedian[kerneliter] = col.getRed();
gMedian[kerneliter] = col.getGreen();
bMedian[kerneliter] = col.getBlue();
kerneliter++;
}
}
kerneliter = 0;
Arrays.sort(rMedian);
Arrays.sort(gMedian);
Arrays.sort(bMedian);
Color colfinal = new Color(rMedian[4], gMedian[4], bMedian[4]);
this.altimg.setRGB(i+1, j+1, colfinal.getRGB());
}
}
}
编辑 #1:为帮助目的添加了完整的最小可编译代码。
编辑 #2:删除了上述代码。答案原来是简单的愚蠢循环限制。
当您从源图像 img.getRGB(ki, kj)
获取值时,您实际上是在 0 和 kernelwidth
/kernelheight
之间的坐标处获取一个像素。
为简单起见,假设 kernelwidth=kernelheight=3
。 i,j >=3
时不执行内循环,不更新中位数
for (int i = 0; i<x-3; i++)
for (int j=0; j<y-3; j++)
for (int ki = i; ki<3; ki++)
for(int kj = j; kj<3; kj++)
//ki, kj at most between 0 and 2
img.getRGB(ki, kj)
其实应该是:
for (int i=1; i<x-1; i++)
for (int j=1; j<y-1; j++) {
for (int ki = 0; ki<3; ki++)
for(int kj = 0; kj<3; kj++)
img.getRGB(i+ki-1, j+kj-1) {
...
请注意,我不是在处理边界。对于边界,您可能会使用缩小的内核,或者将图像外部像素的值作为常量(例如 white/black)或与边界具有相同的值。
作为一个简短的序言,我想为提出这样一个非常愚蠢的问题而道歉。
现在,正确的问题 - 我们的任务是为我们的学习计划编写一个简单的 Mean/Median(两者)过滤器,稍后将作为更高级过滤器类型的介绍和基础。
我已经研究了内核 2D 矩阵如何工作并在图像数据矩阵上流动(至少,我希望我了解它应该如何工作),但我 运行 遇到了一个问题我的代码。我使用以下代码过滤的每个图像都显示为单一颜色,通常是从左上角开始的第一种颜色。我确定错误可能很小,但我似乎找不到它。
如果你们能看一看,我将不胜感激。
public void medianFilter(){
System.out.println("Initializing 2nd image.");
initializeAltImage(); // <-- Preps a blank image the same size as the original.
System.out.println("2nd image initialized.");
int kernelwidth = 3;
int kernelheight = 3;
int[] rMedian = new int [kernelwidth*kernelheight];
int[] gMedian = new int [kernelwidth*kernelheight];
int[] bMedian = new int [kernelwidth*kernelheight];
int kerneliter = 0;
// Walk the entire image but stop before you go out of bounds at the kernel boundraries.
for (int i = 0; i<this.x-kernelwidth; i++){
for (int j=0; j<this.y-kernelheight; j++){
// Walk the kernel itself.
for (int ki = i; ki<kernelwidth; ki++){
for(int kj = j; kj<kernelheight; kj++){
Color col = new Color(this.img.getRGB(ki, kj));
rMedian[kerneliter] = col.getRed();
gMedian[kerneliter] = col.getGreen();
bMedian[kerneliter] = col.getBlue();
kerneliter++;
}
}
kerneliter = 0;
Arrays.sort(rMedian);
Arrays.sort(gMedian);
Arrays.sort(bMedian);
Color colfinal = new Color(rMedian[4], gMedian[4], bMedian[4]);
this.altimg.setRGB(i+1, j+1, colfinal.getRGB());
}
}
}
编辑 #1:为帮助目的添加了完整的最小可编译代码。
编辑 #2:删除了上述代码。答案原来是简单的愚蠢循环限制。
当您从源图像 img.getRGB(ki, kj)
获取值时,您实际上是在 0 和 kernelwidth
/kernelheight
之间的坐标处获取一个像素。
为简单起见,假设 kernelwidth=kernelheight=3
。 i,j >=3
时不执行内循环,不更新中位数
for (int i = 0; i<x-3; i++)
for (int j=0; j<y-3; j++)
for (int ki = i; ki<3; ki++)
for(int kj = j; kj<3; kj++)
//ki, kj at most between 0 and 2
img.getRGB(ki, kj)
其实应该是:
for (int i=1; i<x-1; i++)
for (int j=1; j<y-1; j++) {
for (int ki = 0; ki<3; ki++)
for(int kj = 0; kj<3; kj++)
img.getRGB(i+ki-1, j+kj-1) {
...
请注意,我不是在处理边界。对于边界,您可能会使用缩小的内核,或者将图像外部像素的值作为常量(例如 white/black)或与边界具有相同的值。