1.均值過濾器
均值濾波器用於模糊圖像以消除噪聲。它涉及確定n x n核範圍內像素值的平均值。然後,將中心元素的像素強度替換為平均值。這樣可以消除圖像中的某些噪點並平滑圖像的邊。 Open-CV庫中的模糊函數可用於將均值濾鏡應用於圖像。
處理彩色圖像時,首先必須將RGB轉換為HSV,因為RGB的維度相互依賴,而HSV中的三個維度彼此獨立(這使我們可以將濾鏡分別應用於三個維度。)
以下是均值過濾器的python實現:
import numpy as np
import cv2
from matplotlib import pyplot as plt
from PIL import Image, ImageFilter
%matplotlib inline
image = cv2.imread('AM04NES.JPG') # reads the image
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # convert to HSV
figure_size = 9 # the dimension of the x and y axis of the kernal.
new_image = cv2.blur(image,(figure_size, figure_size))
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(cv2.cvtColor(image, cv2.COLOR_HSV2RGB)),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(cv2.cvtColor(new_image, cv2.COLOR_HSV2RGB)),plt.title('Mean filter')
plt.xticks([]), plt.yticks([])
plt.show()
圖2顯示,雖然減少了一些斑點噪聲,但是圖像中現在存在許多以前不存在的偽影像。我們可以檢查將均值濾鏡應用於灰度圖像時是否創建了偽像。
# The image will first be converted to grayscale
image2 = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)
image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)
figure_size = 9
new_image = cv2.blur(image2,(figure_size, figure_size))
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(image2, cmap='gray'),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(new_image, cmap='gray'),plt.title('Mean filter')
plt.xticks([]), plt.yticks([])
plt.show()
圖3顯示,均值濾波可以消除一些噪聲,並且不會在灰度圖像上產生偽影像。但是,一些細節已丟失。
2.高斯濾波器
高斯濾波器類似於均值濾波器,但是它涉及周圍像素的加權平均值,並具有參數sigma。核代表高斯分布的離散近似。盡管高斯濾鏡也會使圖像的邊模糊(如均值濾鏡),但與相似大小的均值濾鏡相比,它在保留邊方麵做得更好。 Open-CV軟件包中的“ GaussianBlur”功能可用於實現高斯濾波器。該函數允許您指定核的形狀。還可以分別指定x和y方向的標準偏差。如果僅指定一個西格瑪值(sigma, σ),則將其視為x和y方向共享的西格瑪值。
new_image = cv2.GaussianBlur(image, (figure_size, figure_size),0)
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(cv2.cvtColor(image, cv2.COLOR_HSV2RGB)),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(cv2.cvtColor(new_image, cv2.COLOR_HSV2RGB)),plt.title('Gaussian Filter')
plt.xticks([]), plt.yticks([])
plt.show()
圖4顯示,與均值濾波器相比,高斯濾波器在保留圖像邊方麵做得更好,但是在彩色圖像上也會產生偽像。現在我們可以檢查高斯濾波器是否在灰度圖像上產生偽像。
new_image_gauss = cv2.GaussianBlur(image2, (figure_size, figure_size),0)
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(image2, cmap='gray'),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(new_image_gauss, cmap='gray'),plt.title('Gaussian Filter')
plt.xticks([]), plt.yticks([])
plt.show()
圖5顯示了將9 x 9高斯濾波器應用於灰度圖像時不會產生偽像。該濾鏡比9 x 9的平均濾鏡可以保留更多細節,並可以消除一些噪音。
3.中值過濾器
中值過濾器計算n x n核內圍繞像素中心像素的像素強度的中值。然後,用該中位數替換中心像素的像素強度。中值濾波器比平均值濾波器和高斯濾波器在消除胡椒鹽噪聲方麵做得更好。中值濾鏡保留圖像的邊,但不處理斑點噪聲。 Open-CV庫中的“ medianBlur”功能可用於實現中值濾波器。
new_image = cv2.medianBlur(image, figure_size)
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(cv2.cvtColor(image, cv2.COLOR_HSV2RGB)),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(cv2.cvtColor(new_image, cv2.COLOR_HSV2RGB)),plt.title('Median Filter')
plt.xticks([]), plt.yticks([])
plt.show()
圖6顯示,中值濾波器能夠保留圖像的邊,同時消除胡椒鹽噪聲。與均值和高斯濾波器不同,中值濾波器不會在彩色圖像上產生偽像。接下來,中值濾鏡將應用於灰度圖像。
new_image = cv2.medianBlur(image2, figure_size)
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(image2, cmap='gray'),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(new_image, cmap='gray'),plt.title('Median Filter')
plt.xticks([]), plt.yticks([])
plt.show()
圖7顯示了一個9 x 9的中值濾鏡可以在保留圖像邊的同時消除一些胡椒鹽噪聲。
其他過濾器:
以下是另外一些可用於圖像預處理的過濾器:
保守過濾器/最值濾波器
保守過濾器用於去除胡椒鹽噪音。確定像素附近的最小強度和最大強度。如果中心像素的強度大於最大值,則將其替換為最大值。如果小於最小值,則將其替換為最小值。保守濾鏡可以保留邊,但不能消除斑點噪聲。
以下代碼可用於定義保守過濾器:
# first a conservative filter for grayscale images will be defined.
def conservative_smoothing_gray(data, filter_size):
temp = []
indexer = filter_size // 2
new_image = data.copy()
nrow, ncol = data.shape
for i in range(nrow):
for j in range(ncol):
for k in range(i-indexer, i+indexer+1):
for m in range(j-indexer, j+indexer+1):
if (k > -1) and (k < nrow): if (m > -1) and (m < ncol): temp.append(data[k,m]) temp.remove(data[i,j]) max_value = max(temp) min_value = min(temp) if data[i,j] > max_value:
new_image[i,j] = max_value
elif data[i,j] < min_value:
new_image[i,j] = min_value
temp =[]
return new_image.copy()
現在,可以將保守濾鏡應用於灰度圖像:
new_image = conservative_smoothing_gray(image2,5)
plt.figure(figsize=(11,6))
plt.subplot(121), plt.imshow(image2, cmap='gray'),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(new_image, cmap='gray'),plt.title('Conservative Smoothing')
plt.xticks([]), plt.yticks([])
plt.show()
圖9表明,保守平滑濾波器能夠消除一些胡椒鹽噪聲。但該濾波器無法像中值濾波器一樣消除更多胡椒鹽噪聲(盡管它確實保留了更多細節)。
拉普拉斯過濾器
圖像的拉普拉斯算子突出顯示強度快速變化的區域,因此可以用於邊檢測。如果我們讓I(x,y)表示圖像的強度,則圖像的拉普拉斯算子由以下公式給出:
拉普拉斯算子在特定像素處的離散近似值可以通過在像素的小鄰域中采用像素強度的加權平均值來確定。圖10顯示了兩個核,它們代表了逼近拉普拉斯算子的兩種不同方式。
由於拉普拉斯濾鏡檢測圖像的邊,因此可以將其與高斯濾鏡一起使用,以便首先去除斑點噪聲,然後突出顯示圖像的邊。此方法稱為拉普拉斯高斯濾波。 Open-CV庫中的“拉普拉斯算子”功能可用於查找圖像的拉普拉斯算子。
new_image = cv2.Laplacian(image2,cv2.CV_64F)
plt.figure(figsize=(11,6))
plt.subplot(131), plt.imshow(image2, cmap='gray'),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(new_image, cmap='gray'),plt.title('Laplacian')
plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(image2 + new_image, cmap='gray'),plt.title('Resulting image')
plt.xticks([]), plt.yticks([])
plt.show()
圖11顯示,雖然將圖像的拉普拉斯算子添加到原始圖像可能會增強邊,但也會增加一些噪點。
頻率濾波器
在將頻率濾波器應用於圖像時,重要的是首先將圖像轉換為圖像的頻域表示。傅裏葉變換(將一個函數分解成其正弦和餘弦分量)可以應用於圖像,以獲得其頻域表示。我們對圖像的頻域表示感興趣的原因是,在頻域中對圖像應用頻率濾波器要比在空間域中應用濾波器更方便。這是基於以下事實:頻域表示中的每個像素都對應於一個頻率而不是圖像的位置。
低通濾波器和高通濾波器都是頻率濾波器。低通濾波器保留最低頻率(低於閾值),這意味著它會模糊邊並從空間域中的圖像中去除斑點噪聲。高通濾波器可以保留高頻,這意味著可以保留邊。 “ dft”功能確定圖像的離散傅立葉變換。為一個N x N圖像做二維離散傅裏葉變換由下式給出:
其中,f是空間域中的圖像值,F是其頻域中的圖像值。以下是離散傅立葉逆變換的公式(它將圖像從頻域轉換到空間域):
一旦將頻率濾波器應用於圖像之後,就可以使用傅立葉逆變換將圖像轉換回空間域。現在將給出低通濾波器的python實現:
dft = cv2.dft(np.float32(image2),flags = cv2.DFT_COMPLEX_OUTPUT)
# shift the zero-frequncy component to the center of the spectrum
dft_shift = np.fft.fftshift(dft)
# save image of the image in the fourier domain.
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
# plot both images
plt.figure(figsize=(11,6))
plt.subplot(121),plt.imshow(image2, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
rows, cols = image2.shape
crow,ccol = rows//2 , cols//2
# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
# plot both images
plt.figure(figsize=(11,6))
plt.subplot(121),plt.imshow(image2, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Low Pass Filter'), plt.xticks([]), plt.yticks([])
plt.show()
圖13顯示丟失了很多細節,但是去除了一些斑點噪聲。
Crimmin去除斑點
Crimmins互補剔除算法用於去除斑點噪聲並平滑邊。它還可以降低胡椒鹽噪聲的強度。該算法將圖像中像素的強度與其8個相鄰像素的強度進行比較。該算法考慮4組鄰居(N-S,E-W,NW-SE,NE-SW)。假設a,b,c是三個連續像素(例如來自E-S)。那麽算法是:
- 對於每次迭代:
a)暗像素調整:針對四個方向中的每個方向
1)使用以下方法處理整個圖像:if a ≥ b+2 then b = b + 1
2)使用以下方法處理整個圖像:if a > b and b ≤ c then b = b + 1
3)使用以下方法處理整個圖像:if c > b and b ≤ a then b = b + 1
4)使用以下方法處理整個圖像:if c ≥ b+2 then b = b + 1
b)亮像素調整:針對四個方向的每個方向
1)使用以下方法處理整個圖像: if a ≤ b — 2 then b = b — 1
2)使用以下方法處理整個圖像:if a < b and b ≥ c then b = b — 1
3)使用以下方法處理整個圖像:if c < b and b ≥ a then b = b — 1
4)使用以下方法處理整個圖像:if c ≤ b — 2 then b = b — 1
可以在此處找到互補剔除算法的Python實現。
圖14顯示了將Crimmins斑點去除濾鏡應用於圖像的結果。去除了一些斑點噪聲,但是一些邊變得模糊。
銳化濾鏡
銳化濾鏡可用於增強圖像的邊。 PIL包中的ImageFilter.Unsharpmask函數將銳化濾鏡應用於圖像(注:首先需要將圖像轉換為PIL Image對象)。ImageFilter.Unsharpmask函數具有三個參數。 “radius”參數指定邊周圍有多少相鄰像素受到影響。 “percentage”參數指定邊變暗或變亮的程度。第三個參數“threshold”定義在濾波器執行任何操作之前相鄰色調值必須相距多遠。
image = Image.fromarray(image.astype('uint8'))
new_image = image.filter(ImageFilter.UnsharpMask(radius=2, percent=150))
plt.subplot(121),plt.imshow(image, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(new_image, cmap = 'gray')
plt.title('Unsharp Filter'), plt.xticks([]), plt.yticks([])
plt.show()
圖15顯示了Unsharp濾鏡的結果。在增強圖像邊的同時,也增強了一些噪點。
結論
在消除噪點和保留圖像邊之間始終需要權衡取舍。為了消除圖像中的斑點噪聲,需要應用模糊濾波器,該濾波器又使圖像的邊模糊。如果要保留圖像的邊,則唯一可以消除的噪聲是胡椒鹽噪聲。可以在此處找到Jupyter Notebook以及本文使用的所有代碼:https://github.com/m4nv1r/medium_articles/blob/master/Image_Filters_in_Python.ipynb