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=3i,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)或与边界具有相同的值。