OpenCV-Python教程(5、初級濾波內容)

本篇文章介紹如何用OpenCV-Python來實現初級濾波功能。

本文來自https://blog.csdn.net/sunny2038/article/details/9155893

簡介
過濾是信號和圖像處理中基本的任務。其目的是根據應用環境的不同,選擇性的提取圖像中某些認爲是重要的信息。過濾可以移除圖像中的噪音、提取感興趣的可視特徵、允許圖像重採樣,等等。其源自於一般的信號和系統理論,這裏將不介紹該理論的細節。但本章會介紹關於過濾的基本概念,以及如何在圖像處理程序中使用濾波器。首先,簡要介紹下頻率域分析的概念。

當我們觀察一張圖片時,我們觀察的是圖像中有多少灰度級(或顏色)及其分佈。根據灰度分佈的不同來區分不同的圖像。但還有其他方面可以對圖像進行分析。我們可以觀察圖像中灰度的變化。某些圖像中包含大量的強度不變的區域(如藍天),而在其他圖像中的灰度變化可能會非常快(如包含許多小物體的擁擠的圖像)。因此,觀察圖像中這些變化的頻率就構成了另一條分類圖像的方法。這個觀點稱爲頻域。而通過觀察圖像灰度分佈來分類圖像稱爲空間域。

頻域分析將圖像分成從低頻到高頻的不同部分。低頻對應圖像強度變化小的區域,而高頻是圖像強度變化非常大的區域。目前已存在若干轉換方法,如傅立葉變換或餘弦變換,可以用來清晰的顯示圖像的頻率內容。注意,由於圖像是一個二維實體,所以其由水平頻率(水平方向的變化)和豎直頻率(豎直方向的變化)共同組成。

在頻率分析領域的框架中,濾波器是一個用來增強圖像中某個波段或頻率並阻塞(或降低)其他頻率波段的操作。低通濾波器是消除圖像中高頻部分,但保留低頻部分。高通濾波器消除低頻部分

本篇文章介紹在OpenCV-Python中實現的初級的濾波操作,下一篇文章介紹更加複雜的濾波原理及其實現。

本篇文章使用傳統的lena作爲實驗圖像。

用低通濾波來平滑圖像

低通濾波器的目標是降低圖像的變化率。如將每個像素替換爲該像素周圍像素的均值。這樣就可以平滑並替代那些強度變化明顯的區域。在OpenCV中,可以通過blur函數做到這一點:

dst = cv2.blur(image,(5,5)); 

其中dst是blur處理後返回的圖像,參數一是輸入的待處理圖像,參數2是低通濾波器的大小。其後含有幾個可選參數,用來設置濾波器的細節,具體可查閱參考資料2。不過這裏,這樣就夠了。下面是一個簡單的示例代碼:

import cv2

img = cv2.imread(r'C:\contentpic\2018\09\17\20180917150947_5310158069_580328.jpg',0)
result = cv2.blur(img,(5,5))
print(result)
cv2.imshow("Origin", img)
cv2.imshow("Blur", result)

cv2.waitKey(0)
cv2.destroyAllWindows()

結果如下,左邊是平滑過的圖像,右邊是原圖像:

這種濾波器又稱爲boxfilter(注,這與化學上的箱式過濾器是兩碼事,所以這裏就不翻譯了)。所以也可通過OpenCV的cv2.bofxfilter(...)函數來完成相同的工作。如下:

result = cv2.boxFilter(img, -1, (5, 5))

這行代碼與上面使用blur函數的效果完全相同。其中第二個參數的-1表示輸出圖像使用的深度與輸入圖像相同。後面還有幾個可選參數,具體可查閱OpenCV文檔。

高斯模糊

在某些情況下,需要對一個像素的周圍的像素給予更多的重視。因此,可通過分配權重來重新計算這些周圍點的值。這可通過高斯函數(鐘形函數,即喇叭形數)的權重方案來解決。cv::GaussianBlur函數可作爲濾波器用下面的方法調用:

gaussianResult = cv2.GaussianBlur(img,(5,5),1.5)

數返回處理結果,第一個參數是待處理圖像,第二個參數是孔徑的尺寸,一個大於1的奇數。比如這裏是5,中值濾波器就會使用5×5的範圍來計算。即對像素的中心值及其5×5鄰域組成了一個數值集,對其進行處理計算,當前像素被其中值替換掉。

區別

低通濾波與高斯濾波的不同之處在於:低通濾波中,濾波器中每個像素的權重是相同的,即濾波器是線性的。而高斯濾波器中像素的權重與其距中心像素的距離成比例。關於高斯模糊的詳細內容,抽空將寫一篇獨立的文章介紹。

使用中值濾波消除噪點

前面介紹的是線性過濾器,這裏介紹非線性過濾器——中值濾波器。由於中值濾波器對消除椒鹽現象特別有用。所以我們使用第二篇教程中椒鹽函數先對圖像進行處理,將處理結果作爲示例圖片。

調用中值濾波器的方法與調用其他濾波器的方法類似,如下:

result = cv2.medianBlur(image,5)

函數返回處理結果,第一個參數是待處理圖像,第二個參數是孔徑的尺寸,一個大於1的奇數。比如這裏是5,中值濾波器就會使用5×5的範圍來計算。即對像素的中心值及其5×5鄰域組成了一個數值集,對其進行處理計算,當前像素被其中值替換掉。

如果在某個像素周圍有白色或黑色的像素,這些白色或黑色的像素不會選擇作爲中值(最大或最小值不用),而是被替換爲鄰域值。代碼如下:

import cv2
import numpy as np


def salt(img, n):
	for k in range(n):
		i = int(np.random.random() * img.shape[1]);
		j = int(np.random.random() * img.shape[0]);
		if img.ndim == 2:
			img[j, i] = 255
		elif img.ndim == 3:
			img[j, i, 0] = 255
			img[j, i, 1] = 255
			img[j, i, 2] = 255
	return img


img = cv2.imread(r"C:\contentpic\2018\09\17\20180917150947_5310158069_580328.jpg", 0)
result = salt(img, 500)
median = cv2.medianBlur(result, 5)

cv2.imshow("Salt", result)
cv2.imshow("Median", median)

cv2.waitKey(0)

結果如下圖所示

由於中值濾波不會處理最大和最小值,所以就不會受到噪聲的影響。相反,如果直接採用blur進行均值濾波,則不會區分這些噪聲點,濾波後的圖像會受到噪聲的影響。

中值濾波器在處理邊緣也有優勢。但中值濾波器會清除掉某些區域的紋理(如背景中的樹)。

其他
由於方向濾波器與這裏的原理有較大的出入,所以將用獨立的一篇文章中介紹其原理以及實現。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章