首页 > 解决方案 > 用双数组在java上模糊图片表示像素集

问题描述

编写一个名为“smooth”的函数,将图片模糊化——一个双精度数组表示图片的像素组。为参数 n 平滑图片,将图片中的所有像素作为 n n 个邻居的平均值。意思是看一个以当前像素为中心的正方形,并用邻居的平均值替换该像素。


我的尝试: 所以我写了以下内容:

public void smooth(int n) {
    int N = (n-1)/2;
    for (int x = N; x<frame.length-N;x++){
        for (int y=N;y<frame[x].length-N;y++){
            frame[x][y]=average(x,y,N,this.frame);
        }
    }
    //for edges:
    for (int x = 0; x<frame.length;x++) {
        for (int y = 0; y < frame[0].length; y++) {
            if (FilterOutOfBounds(x,y,this.frame,N)!=-1) frame[x][y] = FilterOutOfBounds(x, y, this.frame, N);
        }
    }

}
public static int average(int x, int y, int N,int[][] frame){
    int sum = 0, cnt=0;
    for (int i = x-N;i<x+N;i++){
        for (int j = y-N;j<y+N;j++){
            sum+=frame[i][j]; cnt++;
        }
    }
    return sum/cnt;
}

public static int FilterOutOfBounds(int x, int y, int[][] frame, int N){
    int cnt = 0,sum=0;
    if (frame[0].length-1-y<N && x!=frame.length-1){
        for (int j = y;j>=y-1;j--){
            for (int i = x;i<=x+1;i++){
                cnt++;
                sum+=frame[i][j];
            }
        }
    }
    else if (y<N && x!=frame.length-1 ){
        for (int j = y;j<=y+1;j++){
            for (int i = x;i<=x+1;i++){
                cnt++;
                sum+=frame[i][j];
            }
        }
    }

    else if(frame.length-x<N && y!=0){
        for (int i = x;i>=x-1;i--){
            for (int j = y;j>=y-1;j--){
                cnt++;
                sum+=frame[i][j];
            }
        }

    }

    else if (x<N && y!=frame.length-1){
        for (int i = x;i<=x+1;i++){
            for (int j = y;j<=y+1;j++){
                cnt++;
                sum+=frame[i][j];
            }
        }
    }
    if (cnt==0) return -1;
    return sum/cnt;
}

但是,由于某种原因,它不会模糊边缘,我想不出为什么。因此,我会很高兴得到一些帮助。谢谢!

标签: javagaussianblur

解决方案


我认为您的代码存在一些问题。首先,您正在直接更新frame变量,这将为您的计算累积平均值。我相信这也是一个不需要的副作用。另一件事是,该FilterOutOfBounds方法使用frame.length反对y,这应该是frame[0].length,因为这指的y是一个矩形。这些内部计算也无法处理N,因此 for 循环中的x+1andy+1可能是误解,它们应该是x+Nandy+N或类似的东西。

我为您的问题创建了一个更简单的解决方案。基本上我已经修改了该avarage方法,以便能够处理边缘情况并让smoothfor 循环遍历frame. 为我工作:

public void smooth( int n ) {
    int N = (n - 1) / 2;
    int[][] blurred = new int[frame.length][frame[0].length];
    for ( int x = 0; x < frame.length; x++ ) {
        for ( int y = 0; y < frame[x].length; y++ ) {
            blurred[x][y] = average(x, y, N, frame);
        }
    }
    frame = blurred;
}

public static int average( int x, int y, int N, int[][] frame ) {
    int sum = 0, cnt = 0;
    for ( int i = Math.max(x - N, 0); i <= Math.min(x + N, frame.length - 1); i++ ) {
        for ( int j = Math.max(y - N, 0); j <= Math.min(y + N, frame[i].length - 1); j++ ) {
            sum += frame[i][j];
            cnt++;
        }
    }
    return sum / cnt;
}

推荐阅读