首頁 新聞中心 技術博客

基于Java的空間濾波代碼實現

發布時間:2021-10-25 23:02:53   瀏覽量:2764   作者:GIS前沿

空間濾波的定義

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

圖像需要增強的原因

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

(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");//輸出完一行就換行    }}

}

來源:https://blog.csdn.net/qq_43173805/article/details/119868866
18黄无遮挡免费视频