基於Java實現空間濾波完整代碼

空間濾波的定義

濾波的本義是指信號有各種頻率的成分,濾掉不想要的成分,即為濾掉常說的噪聲,留下想要的成分,這即是濾波的過程,也是目的。空間濾波是一種采用濾波處理的影像增強方法。其理論基礎是空間卷積和空間相關。目的是改善影像質量,包括去除高頻噪聲與幹擾,及影像邊緣增強、線性增強以及去模糊等。分為低通濾波(平滑化)、高通濾波(銳化)和帶通濾波。

圖像需要增強的原因

各類圖像處理系統在圖像的采集、獲取、傳送和轉換(如成像、復制掃描、傳輸以及顯示等)過程中,均處在復雜的環境中,光照、電磁多變,所有的圖像均不同程度地被可見或不可見的噪聲幹擾。噪聲源包括電子噪聲、光子噪聲、斑點噪聲和量化噪聲。如果信噪比低於一定的水平,噪聲逐漸變成可見的顆粒形狀,導致圖像質量的下降。除瞭視覺上質量下降,噪聲同樣可能掩蓋重要的圖像細節,在對采集到的原始圖像做進一步的分割處理時,我們發現有一些分佈不規律的椒鹽噪聲,為此采取相應的對策就是對圖像進行必要的濾波降噪處理。

(1) 中值濾波

PART/01

是將每個像元在以其為中心的M×N鄰域內取中間亮度值來代替該像元值,以達到去尖銳“噪聲”和平滑圖像的目的。具體計算方法與模板卷積方法類似,仍采用活動窗口的掃描方法。取值時,將M×N窗口內所有像元按亮度值的大小排列,取中間值作為中間像元的值。所以M×N取奇數為好。一般來說,圖像亮度為階梯狀變化時,取均值平滑比取中值濾波要明顯得多,而對於突出亮點的“噪聲”幹擾,從去“噪聲”後對原圖的保留程度看取中值要優於取均值。

代碼實現:

比如我們要對下面矩陣進行中值濾波運算,

4 4 3 7 6 8 8

4 4 3 7 6 8 8

2 2 15 8 9 9 9

5 5 8 9 13 10 10

7 7 9 12 15 11 11

8 8 11 10 14 13 13

8 8 11 10 14 13 13

輸出結果如下圖所示:

package NB;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Scanner;

public class zzlb {

public static void main(String[] args) {

    Scanner s=new Scanner(System.in);

    System.out.println("請輸入矩陣的行數:");

    int x=s.nextInt();//獲取鍵盤輸入的數字

    System.out.println("請輸入矩陣的列數:");

    int y=s.nextInt();//獲取鍵盤輸入的數字

    int[][]b=new int[x][y];//創建一個二維數組

    int[]p=new int[9];//創建一個可以存放9個元素的一維數組來獲取#3*3窗口的像元值

    System.out.println("請輸入"+x+"*"+y+"的矩陣:");

    for (int i = 0; i <y; i++) {

        for (int j = 0; j < x; j++) {

            b[i][j]=s.nextInt();//將鍵盤輸入的矩陣存放到二維數組裡面

        }

    }

    System.out.print("運算結果如下:\n");

    for (int i = 1; i <y-1; i++) {

        for (int j = 1; j < x-1; j++) {  //鎖定到中心像元的位置,從(1,1)開始

            int g=0;

            for (int k =i-1; k <=i+1 ; k++) {

                for (int l =j-1; l <=j+1 ; l++) {

                    p[g++]=b[k][l]; //將3*3矩陣窗口存儲到一維數組中

                }

            }

            for (int k = 0; k <p.length-1; k++) {

                for (int l = 0; l < p.length-1-k; l++) {

                    if(p[l]>p[l+1]) {

                        int temp = p[l];

                        p[l]=p[l+1];

                        p[l+1]=temp;//本次采用冒泡排序法對3*3窗口內的像元從小到大排序

                    }

                }

            }

            System.out.print(p[4]+" ");//輸出每個3*3模板的中心值,下標都是4

        }

        System.out.println("\n");//輸出完一行就換行

    }

}
}

有小夥伴看到就會說:我求的是55的矩陣,為什麼輸入的是77的矩陣?原因在於我們運用的33矩陣窗口放在矩陣4個角的像元時,需要額外添加鄰近的像元來構成33的窗口,對於這個添加的臨時像元值一般和最近的像元值保持一致。

(2)羅伯特銳化

PART/02

圖像銳化是為瞭突出圖像上地物的邊緣、輪廓,或某些線性目標要素的特征。這種濾波方法提高瞭地物邊緣與周圍像元之間的反差,因此也被稱為邊緣增強。銳化的方法很多,在此隻介紹羅伯特梯度。梯度反映瞭相鄰像元的亮度變化率,也就是說,圖像中如果存在邊緣,如湖泊、河流的邊界,山脈和道路等,則邊緣處有較大的梯度值。對於亮度值較平滑的部分,亮度梯度值較小。因此,找到梯度較大的位置,也就找到邊緣,然後再用不同的梯度計算值代替邊緣處像元的值,也就突出瞭邊緣,實現瞭圖像的銳化。

不過在講解之前小編先給大傢引入一個新的概念——圖像卷積運算, 卷積運算:可看作是加權求和的過程,使圖像區域中的每個像素分別與卷積核(權矩陣)的每個元素對應相乘,所有乘積之和作為區域中心像素的新值。它是在空間域上對圖像作局部檢測的運算,以實現平滑和銳化的目的。具體作法是選定一個卷積函數,又稱為“模板”,實際上是一個M×N圖像。二維的卷積運算是在圖像中使用模板來實現運算的。運算方法從圖像左上角開始,選定與模板同樣大小的矩陣元素窗口,圖像窗口與模板像元對應的亮度值相乘後再相加,最後一般將計算結果放在窗口中心位置(當M和N都是奇數時),代替原來的像元灰度值。然後活動窗口向右移動一個像元再以同樣的方法進行卷積運算,逐行掃描,直到全幅影像都掃描一遍,最後生成新圖像。羅伯特銳化方法使用的兩個模板如下:

F=|aidxi|+|aidyi|,其中a是矩陣中的2*2個元素,i是第i個元素,i<=4,計算結果放在左上角像元,代替之前的灰度值,但是右下角的像元模板范圍內沒有其他像元瞭,無法進行計算,為此使用羅伯特銳化方法都要在原始矩陣的最下邊和最右邊添加一行和一列,值都和最臨近的像元灰度值一樣。為瞭直白瞭斷,小編直接上例子吧,比如有某個矩陣,如下圖(1)所示,我要用上面兩個模板進行羅伯特銳化,首先得在右邊和下邊分別添加一行和一列,如下圖(2)所示:

接下來對左上角像元進行運算:|2*(-1)+30+40+51|+|20+3*(-1)+41+50|=4,

接下來對右上角像元進行運算:|3*(-1)+30+50+51|+|30+3*(-1)+51+50|=4,

接下來對左下角像元進行運算:|4*(-1)+50+40+51|+|40+5*(-1)+41+50|=2,

接下來對右下角像元進行運算:|5*(-1)+50+50+51|+|50+5*(-1)+51+50|=0,最終輸出矩陣如下所示:

這種算法的意義在於用交叉的方法檢測出像與其領域在上下之間或左右之間或斜方向之間的差異,最終產生一個梯度影像,達到提取邊緣信息的目的。

代碼實現:

比如我們要對下面矩陣進行中值濾波運算,

2 2 10 10 10 10

2 2 10 10 10 10

2 2 10 10 10 10

2 2 2 2 2 2

2 2 2 2 2 2

2 2 2 2 2 2

輸出結果如下圖所示:

package NB;

import java.util.Scanner;

public class robet {
public static void main(String[] args) {

    Scanner s1 = new Scanner(System.in);

    System.out.println("請輸入矩陣的行數:");

    int x = s1.nextInt();//獲取鍵盤輸入的數字

    System.out.println("請輸入矩陣的列數:");

    int y = s1.nextInt();//獲取鍵盤輸入的數字

    int[][] b = new int[x][y];//創建一個二維數組

    System.out.println("請輸入" + x + "*" + y + "的矩陣:");

    for (int i = 0; i < y; i++) {

        for (int j = 0; j < x; j++) {

            b[i][j] = s1.nextInt();

        }///將鍵盤輸入的矩陣存放到二維數組裡面

    }

    for (int i =0; i <y-1; i++) {

        for (int j = 0; j <x-1; j++) {

            b[i][j]=Math.abs(b[i][j]-b[i+1][j+1])+Math.abs(b[i+1][j]-b[i][j+1]);

            System.out.print(b[i][j]+" ");

        }//對兩個模板進行圖像卷積運算後取絕對值相加,並且把結果放到2*2窗口的左上方

        System.out.println("\n");//輸出完一行就換行

    }

}
}

到此這篇關於基於Java的空間濾波代碼實現的文章就介紹到這瞭,更多相關Java空間濾波內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: