图像处理---逆滤波和维纳滤波


前言

本文主要介绍退化图像复原的两种方法:逆滤波和维纳滤波。


一、逆滤波

图像退化的表达式:
g ( x , y ) = h ( x , y ) ⊙ f ( x , y ) + η ( x , y ) \begin{aligned} g(x,y)=h(x,y)\odot f(x,y)+\eta(x,y) \end{aligned} g(x,y)=h(x,y)f(x,y)+η(x,y)
f ( x , y ) : f(x,y): f(x,y):输入图像
h ( x , y ) : h(x,y): h(x,y):退化函数
η ( x , y ) : \eta(x,y): η(x,y):噪声项
g : g: g: 退化图像

由卷积定理转换到频域中:
G ( u , v ) = H ( u , v ) ∗ F ( u , v ) + N ( u , v ) \begin{aligned} G(u,v)=H(u,v)*F(u,v)+N(u,v) \end{aligned} G(u,v)=H(u,v)F(u,v)+N(u,v)

逆滤波运算就是将退化函数去除:
F ^ = G ( u , v ) H ( u , v ) = F ( u , v ) + N ( u , v ) H ( u , v ) \begin{aligned} \hat{F}=\displaystyle\frac{G(u,v)}{H(u,v)}=F(u,v)+\frac{N(u,v)}{H(u,v)} \end{aligned} F^=H(u,v)G(u,v)=F(u,v)+H(u,v)N(u,v)

根据上式,逆滤波存在两个关键问题:

  1. 退化函数 H ( u , v ) H(u,v) H(u,v)的估计的确准确,复原的越清晰。
  2. 当退化函数 H ( u , v ) H(u,v) H(u,v)趋向于0时,后面一项的值变得过大,最终的式子受噪声项 N ( u , v ) N(u,v) N(u,v)的影响就加大。

1.1 估计退化函数 H ( u , v ) H(u,v) H(u,v)

主要有3种方法:
( 1 ) (1) (1):观察法; ( 2 ) (2) (2):试验法; ( 3 ) (3) (3):数学建模法
这些方法都是在频域上进行处理

1.1.1 观察法

寻找一个信号内容很强的区域(高对比度区域),从而忽略噪声项的影响,即:
H s ( u , v ) = G s ( u , v ) F s ^ ( u , v ) \begin{aligned} {H_{s}(u,v)}=\displaystyle\frac{G_{s}(u,v)}{\hat{F_{s}}(u,v)} \end{aligned} Hs(u,v)=Fs^(u,v)Gs(u,v)
G s ( u , v ) : {G_{s}}(u,v): Gs(u,v):当前需要复原的图像的傅里叶变换。
F s ^ ( u , v ) : {\hat{F_{s}}(u,v)}: Fs^(u,v):已经经过处理(锐化、均值滤波等)复原后的图像。

1.1.2 试验法

简而言之就是做实验模拟真实退化的过程,再根据下面的式子得到退化函数。
H ( u , v ) = G ( u , v ) A \begin{aligned} {H(u,v)}=\displaystyle\frac{G(u,v)}{A} \end{aligned} H(u,v)=AG(u,v)
假设现在有某个设备可以得到和退化图像非常近似的图像,然后对一个冲激(小光点,小光点应亮到能降低噪声的影响)成像,得到冲激退化后的FFT(对应上式的 G ( u , v ) G(u,v) G(u,v)),而一个冲激的FFT是一个常量 A A A

1.1.3 建模法 ★ \bigstar

( 1 ) (1) (1)大气湍流模型
H ( u , v ) = e − k ( u 2 + v 2 ) 5 / 6 \begin{aligned} {H(u,v)}=e^{-k(u^{2}+v^{2})^{5/6}} \end{aligned} H(u,v)=ek(u2+v2)5/6
k 是湍流常数,反映湍流的强烈程度。
k = { 0.00025 轻微湍流 0.001 中等湍流 0.0025 剧烈湍流 k= \left\{ \begin{array}{ll} 0.00025\quad\quad轻微湍流\\ 0.001\quad\quad\quad中等湍流\\0.0025\quad\quad\quad剧烈湍流 \end{array} \right. k= 0.00025轻微湍流0.001中等湍流0.0025剧烈湍流
代码:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像
img = cv2.imread('A.png',0)

# 进行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

#-------------大气湍流模型-----------------
k = 0.001  #湍流程度
degeneration_img = np.zeros(fshift.shape,dtype=complex)   #一定要指定类型
for u in range(fshift.shape[0]):
    for v in range(fshift.shape[1]):
        H = np.exp(-k*np.power(np.float64((u-fshift.shape[0]//2)**2+(v-fshift.shape[1]//2)**2),5/6))
        degeneration_img[u][v] = fshift[u][v] * H
#-----------------------------------------

# 将频域图像在空域进行显示做的处理
img1  = np.fft.ifftshift(degeneration_img)
img1  = np.fft.ifft2(img1)
img1 = np.abs(img1)
img1 = cv2.normalize(img1, None, 0, 255, cv2.NORM_MINMAX)


# 显示原始图像和退化的图像
plt.figure(figsize=(20, 20))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img1, cmap='gray')
plt.title('degeneration img'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
注意:在对degeneration_img进行初始化时,一定要指定类型dtype=complex。我在写的过程中,就忘记对类型进行指定,导致得到了错误的退化图像(大家可以尝试一下)。一般来讲不指定类型并没有多大问题,但是,由于这里是复数类型,如果不指定类型,后面语句 degeneration_img[u][v] = fshift[u][v] * H 赋值的过程中就会导致虚部自动被舍弃掉了!参考下图:

在这里插入图片描述
在这里插入图片描述

以前不清楚动态语言的坑,现在算是掉过一次坑了,以后Python写代码一定一定加类型标注!!

另外,也可以用矩阵的方法生成:(下面代码参考文章:https://blog.csdn.net/youcans/article/details/123027287)
def turbulenceBlur(img, k=0.001):  # 湍流模糊传递函数
        # H(u,v) = exp(-k(u^2+v^2)^5/6)
        M, N = img.shape[1], img.shape[0]
        u, v = np.meshgrid(np.arange(M), np.arange(N))
        radius = (u - M//2)**2 + (v - N//2)**2
        kernel = np.exp(-k * np.power(radius, 5/6))
        return kernel

( 2 ) (2) (2)运动模糊模型
当图像在 x x x 方向做速率为 x 0 ( t ) = a t / T x_{0}(t) = at/T x0(t)=at/T 的匀速直线运动 ,同时在 y y y 方向上做速率为 y 0 ( t ) = b t / T y_{0}(t) = bt/T y0(t)=bt/T 的匀速直线运动。
H ( u , v ) = T π ( u a + v b ) s i n [ π ( u a + v b ) ] e − j π ( u a + v b ) \begin{aligned} H(u,v)=\frac{T}{\pi(ua+vb)}sin[\pi(ua+vb)]e^{-j\pi(ua+vb)} \end{aligned} H(u,v)=π(ua+vb)Tsin[π(ua+vb)]e(ua+vb)

代码:

# 功能:实现运动模糊的效果
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像
img = cv2.imread('0526.tif',0)

# 进行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

#-------------运动模糊模型-----------------
a = b = 0.1
T = 1
degeneration_img = np.zeros(fshift.shape,dtype=np.complex64)   #一定要指定类型
for u in range(fshift.shape[0]):
    for v in range(fshift.shape[1]):
        uv = ((u-fshift.shape[0]//2)*a + (v-fshift.shape[1]//2)*b) * np.pi
        if uv == 0:
            degeneration_img[u][v] = fshift[u][v]
        else:
            H = T * np.sin(uv) * np.exp(np.complex64(-1j)*uv) /uv
            degeneration_img[u][v] = fshift[u][v] * H
#-----------------------------------------

# 将频域图像在空域进行显示做的处理
img1  = np.fft.ifftshift(degeneration_img)
img1  = np.fft.ifft2(img1)
img1 = np.abs(img1)
img1 = cv2.normalize(img1, None, 0, 1, cv2.NORM_MINMAX)


# 显示原始图像和退化的图像
plt.figure(figsize=(20, 20))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img1, cmap='gray')
plt.title('degeneration img'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

( 3 ) (3) (3)高斯模糊模型
H ( u , v ) = e − D 2 ( u , v ) / 2 D 0 2 D ( u , v ) = [ ( u − P / 2 ) 2 + ( v − Q / 2 ) 2 ] 1 / 2 \begin{aligned} {H(u,v)}=e^{-D^{2}(u,v)/2D_{0}^{2}}\quad\quad\\{D(u,v) = {[(u-P/2)^{2}+(v-Q/2)^{2}]^{1/2}}} \end{aligned} H(u,v)=eD2(u,v)/2D02D(u,v)=[(uP/2)2+(vQ/2)2]1/2
代码:

import cv2
import numpy as np

# 读取输入图像
img = cv2.imread('A.png', 0)

# 进行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

# 构造高斯滤波器
rows, cols = img.shape
crow, ccol = rows//2, cols//2
d = 60  # 滤波器大小
gauss = np.zeros((rows, cols))
for i in range(rows):
    for j in range(cols):
        gauss[i, j] = np.exp(-((i-crow)**2+(j-ccol)**2)/(2*d**2))

# 将高斯滤波器应用于频域图像
filtered = np.multiply(fshift, gauss)

# 进行反傅里叶变换
f_ishift = np.fft.ifftshift(filtered)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
img_back = cv2.normalize(img_back, None, 0, 1, cv2.NORM_MINMAX)

# 显示结果
cv2.imshow('Input', img)
cv2.imshow('Output', img_back)
cv2.waitKey(0)
cv2.destroyAllWindows()

1.2 直接逆滤波

不考虑噪声:
F ^ = G ( u , v ) H ( u , v ) \begin{aligned} \hat{F}=\displaystyle\frac{G(u,v)}{H(u,v)} \end{aligned} F^=H(u,v)G(u,v)
【noise1.png】:经过高斯模糊并加上高斯噪声的图片。
在没有任何先验知识的情况下,使用大气湍流模型估计图片的退化函数,然后进行逆滤波处理。
代码如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像
img = cv2.imread('noise1.png',0)

# 进行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

#-------------利用大气湍流模型估计退化传递函数-----------------
k = 0.001  #湍流程度
degeneration = np.zeros(fshift.shape,dtype=complex)   
for u in range(fshift.shape[0]):
    for v in range(fshift.shape[1]):
        H = np.exp(-k*np.power(np.float64((u+fshift.shape[0]//2)**2+(v-fshift.shape[1]//2)**2),5/6))
        degeneration[u][v] =  H
#-----------------------------------------


# 逆滤波
img1 = np.divide(fshift,degeneration)

# 将频域图像在空域进行显示做的处理
img1  = np.fft.ifftshift(img1)
img1  = np.fft.ifft2(img1)
img1 = np.abs(img1)
img1 = cv2.normalize(img1, None, 0, 255, cv2.NORM_MINMAX)


# 显示原始图像和恢复后的图像
plt.figure(figsize=(20, 20))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img1, cmap='gray')
plt.title('rec img'), plt.xticks([]), plt.yticks([])
plt.show()

滤波效果:
在这里插入图片描述
但是,只需要将上面语句degeneration[u][v] = H → \rightarrow degeneration[u][v] = H + 0.001,将0.001作为噪声的估计,就得到一定的效果:
在这里插入图片描述

1.3 半径受限逆滤波

考虑噪声:
F ^ = F ( u , v ) + N ( u , v ) H ( u , v ) \begin{aligned} \hat{F}=F(u,v)+\frac{N(u,v)}{H(u,v)} \end{aligned} F^=F(u,v)+H(u,v)N(u,v)

使用低通滤波器过滤掉高频的噪声之后再除以H(u, v)

代码:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像
img = cv2.imread('noise3.png',0)

# 进行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

#-------------大气湍流模型-----------------
k = 0.001  #湍流程度
degeneration = np.zeros(fshift.shape,dtype=complex)   #要指定类型
for u in range(fshift.shape[0]):
    for v in range(fshift.shape[1]):
        H = np.exp(-k*np.power(np.float64((u+fshift.shape[0]//2)**2+(v-fshift.shape[1]//2)**2),5/6))
        degeneration[u][v] =  H
#-----------------------------------------


# 构建低通滤波器---理想低通
# rows,cols = fshift.shape
# radius = 1
# mask = np.zeros((rows, cols),dtype=np.float64)
# for i in range(rows):
#     for j in range(cols):
#         if np.sqrt((i-rows//2)**2 + (j-cols//2)**2) <= radius:
#             mask[i, j] = 0.1
# fshift = np.multiply(fshift, mask)

# # 构建高斯低通滤波器
# rows, cols = img.shape
# crow, ccol = rows//2, cols//2
# d = 50  # 滤波器大小
# gauss = np.zeros((rows, cols))
# for i in range(rows):
#     for j in range(cols):
#         gauss[i, j] = np.exp(-((i-crow)**2+(j-ccol)**2)/(2*d**2))

# 构建巴特沃斯低通滤波器
rows, cols = img.shape
crow, ccol = rows//2, cols//2
d = 70  # 滤波器大小
butter = np.zeros((rows, cols))
for i in range(rows):
    for j in range(cols):
        butter[i, j] = 1/(1 + np.power((np.power((i-crow)**2+(j-ccol)**2,0.5)/d),20))

fshift = np.multiply(fshift, butter)
# 逆滤波
img1 = np.divide(fshift,butter)

# 将频域图像在空域进行显示做的处理
img1  = np.fft.ifftshift(img1)
img1  = np.fft.ifft2(img1)
img1 = np.abs(img1)
img1 = cv2.normalize(img1, None, 0, 1, cv2.NORM_MINMAX)


# 显示原始图像和恢复后的图像
plt.figure(figsize=(20, 20))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img1, cmap='gray')
plt.title('rec img'), plt.xticks([]), plt.yticks([])
plt.show()

cv2.imshow('org',img)
cv2.imshow('rev',img1)
cv2.waitKey(0)

滤波效果:

在这里插入图片描述

二、最小均方误差(维纳)滤波

退化图像的估计的傅里叶变换为:
F ( u , v ) ^ = [ 1 H ( u , v ) ∣ H ( u , v ) ∣ 2 ∣ H ( u , v ) ∣ 2 + K ] G ( u , v ) \begin{aligned} \hat{F(u,v)}=[\frac{1}{H(u,v)}\frac{|H(u,v)|^{2}}{|H(u,v)|^{2}+K}]{G(u,v)} \end{aligned} F(u,v)^=[H(u,v)1H(u,v)2+KH(u,v)2]G(u,v)

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读取图像
img = cv2.imread('noise2.png',0)

# 进行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

#-------------大气湍流模型-----------------
k = 0.001  #湍流程度
degeneration = np.zeros(fshift.shape,dtype=complex)   #要指定类型
for u in range(fshift.shape[0]):
    for v in range(fshift.shape[1]):
        H = np.exp(-k*np.power(np.float64((u+fshift.shape[0]//2)**2+(v-fshift.shape[1]//2)**2),5/6))
        degeneration[u][v] =  H
#-----------------------------------------


# 维纳滤波
K = 0.001
degeneration += 0.1   #加上估计的噪声
img1 = (np.conj(degeneration)/(np.conj(degeneration)*degeneration + K)) * fshift

# 将频域图像在空域进行显示做的处理
img1  = np.fft.ifftshift(img1)
img1  = np.fft.ifft2(img1)
img1 = np.abs(img1)
img1 = cv2.normalize(img1, None, 0, 1, cv2.NORM_MINMAX)


# 显示原始图像和恢复后的图像
plt.figure(figsize=(20, 20))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img1, cmap='gray')
plt.title('rec img'), plt.xticks([]), plt.yticks([])
plt.show()

滤波效果:
在这里插入图片描述

总结

主要展示了维纳滤波和逆滤波两种方法,但是滤波效果并不明显,可能是估计的退化函数与真实的退化函数不一致导致的。

参考文献

[1] 阮秋琦,阮宇智译;(美)拉斐尔·C.冈萨雷斯,理查德·E.伍兹.国外电子书与通信教材系列 数字图像处理 第4版[M].北京:电子工业出版社,2020

猜你喜欢

转载自blog.csdn.net/m0_46366547/article/details/129826768