这是在上课时老师留的第一个大作业,不愧是我,总是赶到ddl。
中值滤波
中值滤波的原理很简单,就是滑动窗在原图上滑动,然后将滑动窗的内容的中值,作为新图中该坐标的像素值,比较适用于 椒盐噪声。从原理来说,如果没有对原图进行拓展的话,滤波后的新图的大小与原图是不一样的,原图的边缘部分是没有参与运算的。所以下面是利用了padding的技巧,确保原图的边缘部分也可以滤波。
代码如下:
import numpy as np
import cv2
import glob
from matplotlib import pyplot as plt
img = cv2.imread(r'F:\something_useful\Image_processing\homework01\Circuit_noise.jpg',0)
img_copy = img.copy()
width = img.shape[0] #宽
length = img.shape[1] #高
kernel = 5 #卷积核大小 / 滑动窗大小
mid = (kernel-1)//2
padding = (kernel - 1)//2 #扩展操作,为了对原图所有的点都操作
img_new = np.zeros([width + 2*padding,length + 2*padding],dtype = np.uint8) #扩展原图,补零
#将原图 铺在 新图上
for i in range(width):
for j in range(length):
img_new[padding + i,padding + j] = img[i,j]
slide_window = [] #滑动窗的内容
for i in range(width):
for j in range(length):
for m in range(kernel):
for n in range(kernel):
slide_window.append(img_new[i+m,j+n])
slide_window.sort()
img_copy[i ,j] = slide_window[(len(slide_window)+1)//2] #取中值
del slide_window[:]
print('okok---------')
cv2.imshow('img_after_Circuit_noise',img_copy)
print(img_copy.shape)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图如下:
均值滤波
与中值滤波相似,其实只是将取中值的操作换成取均值即可。均值滤波是用于去除高斯噪声,那种“米花类型”的噪音。代码如下:
import numpy as np
import cv2
import glob
from matplotlib import pyplot as plt
img = cv2.imread(r'F:\something_useful\Image_processing\homework01\california_22_13.bmp',0)
cv2.imshow('img',img)
img_copy = img.copy()
width = img.shape[0] #宽
length = img.shape[1] #高
kernel = 5 #卷积核大小 / 滑动窗大小
padding = (kernel - 1)//2 #扩展操作,为了对原图所有的点都操作
img_new = np.zeros([width + 2*padding,length + 2*padding],dtype = np.uint8) #扩展原图,补零
#将原图 铺在 新图上
for i in range(width):
for j in range(length):
img_new[padding + i,padding + j] = img[i,j]
slide_window = [] #滑动窗的内容
for i in range(width):
for j in range(length):
window_sum = 0 #滑动窗的和
for m in range(kernel):
for n in range(kernel):
slide_window.append(img_new[i+m,j+n])
window_sum += img_new[i+m,j+n]
window_average = window_sum / len(slide_window)
img_copy[i ,j] = window_average #取均值
del slide_window[:]
print('okok---------')
cv2.imshow('img_after',img_copy)
print(img_copy.shape)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图如下:可以就看出 均值滤波去除高斯噪声,还是很容易把边缘给模糊了的
FFT_陷波器
这里首先看一下给的带噪音的原图。
发现噪音很明显是带有特定频率的,这里把它称为正弦噪音,所以考虑在频域进行处理。首先试了频域下的低通滤波器,发现通过控制滤波的半径,可以去除正弦噪音,但是一些更加高频的细节并不能够被保留下来,效果如下:
所以考虑使用 陷波器,即去除特定频率的噪音,而不是去破坏图像的其他细节。代码如下:
def boy_noisy_process():
#读图片,噪音类型只要是正弦,利用fft变换,从频谱去除噪音
img_boy_noisy = Image.open(r'.\boy_noisy.gif')
img_boy_noisy = np.array(img_boy_noisy)
cv2.imshow('img_boy_noisy',img_boy_noisy)
#FFT
f = np.fft.fft2(img_boy_noisy)
#中心化
fshift = np.fft.fftshift(f)
fft_show = np.array(np.log(np.abs(fshift)),dtype = np.uint8)
plt.subplot(1,2,1),plt.imshow(fft_show,'gray'),plt.title('img fft')
#构建滤波器(陷波器)
kernel = np.ones(fshift.shape,dtype = np.uint8)
width_center = fshift.shape[0] // 2
length_center = fshift.shape[1] // 2
radius = 32 #滤波器半径
for i in range(width_center - radius,width_center + radius):
kernel[i,length_center - radius] = 0
kernel[i,length_center + radius] = 0
for j in range(length_center - radius,length_center + radius):
kernel[width_center - radius,j] = 0
kernel[width_center -+ radius,j] = 0
#频域滤波
fshift_new = fshift * kernel
fft_show_new = np.array(np.log(np.abs(fshift_new)),dtype = np.uint8)
plt.subplot(1,2,2),plt.imshow(fft_show_new,'gray'),plt.title('img fft new')
# 逆变换
f1shift = np.fft.ifftshift(fshift_new)
img_after_boy_noisy = np.fft.ifft2(f1shift)
#出来的是复数,无法显示
img_after_boy_noisy = np.array(np.abs(img_after_boy_noisy),dtype = np.uint8)
cv2.imshow('img_after_boy_noisy',img_after_boy_noisy)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果是比较满意的,高频的细节也可以保留下来。最终效果如下: