一种将频率滤波和空域灰度变换结合起来的图像处理方法,根据图像的照度或反射率模型作为频域处理的基础,利用压缩亮度范围和增强对比度来改善图像的质量。对增强阴影部分有较好的优势,能消除乘性噪声,能同时压缩图像的整体动态范围,并增加图像中相邻区域间的对比度,在信号与图像处理中应用广泛。
输入图像由照度分量和反射分量两部分组成,即:
f ( x , y ) = i ( x , y ) r ( x , y ) f(x,y)=i(x,y)r(x,y) f(x,y)=i(x,y)r(x,y)
其中, 0 < i ( x , y ) < ∞ 00<i(x,y)<∞为照度分量,描述照明,变化缓慢,处于低频部分; 0 < r ( x , y ) < 1 0
滤波步骤如下:
第一步:对原图做对数变换,将乘性信号转变为加性信号,即:
ln f ( x , y ) = ln i ( x , y ) + ln r ( x , y ) \ln{f(x,y)}=\ln{i(x,y)}+\ln{r(x,y)} lnf(x,y)=lni(x,y)+lnr(x,y)
但是为了避免出现 ln 0 \ln{0} ln0,所以一般采用 ln ( f ( x ) + 1 ) \ln{(f(x)+1)} ln(f(x)+1)进行计算。
第二步:做傅里叶变换,得到其对应的频域表示为:
F [ ln f ( x , y ) ] = F [ ln i ( x , y ) ] + F [ ln r ( x , y ) ] F[\ln{f(x,y)}]=F[\ln{i(x,y)}]+F[\ln{r(x,y)}] F[lnf(x,y)]=F[lni(x,y)]+F[lnr(x,y)]
照度分量 F [ ln i ( x , y ) ] F[\ln{i(x,y)}] F[lni(x,y)]频谱特性集中在低频段;反射分量 F [ ln r ( x , y ) ] F[\ln{r(x,y)}] F[lnr(x,y)]频谱特性集中在高频段。
第三步:设计一个频域滤波器H(u,v),进行对数图像的频域滤波:
S ( x , y ) = H ( x , y ) F [ ln f ( x , y ) ] = H ( x , y ) F [ ln i ( x , y ) ] + H ( x , y ) F [ ln r ( x , y ) ] S(x,y)=H(x,y)F[\ln{f(x,y)}]=H(x,y)F[\ln{i(x,y)}]+H(x,y)F[\ln{r(x,y)}] S(x,y)=H(x,y)F[lnf(x,y)]=H(x,y)F[lni(x,y)]+H(x,y)F[lnr(x,y)]
H ( x , y ) H(x,y) H(x,y)通常采用如下形式:
H m o ( u , v ) = ( γ H − γ L ) H h p ( u , v ) + γ L H_{mo}(u,v)=(\gamma_{H}-\gamma_{L})H_{hp}(u,v)+\gamma_{L} Hmo(u,v)=(γH−γL)Hhp(u,v)+γL
其中, γ L < 1 , γ H > 1 \gamma_{L}<1,\gamma_{H}>1 γL<1,γH>1,用来控制滤波器的幅度范围; H h p H_{hp} Hhp为高通滤波器,常用的有高斯高通滤波器、Butterworth高通滤波器、Laplacian滤波器等。如果采用高斯高通滤波器,则有:
H h p ( u , v ) = 1 − e − c ( D 2 ( u , v ) D 0 2 ) H_{hp}(u,v)=1-e^{-c(\frac{D^{2}(u,v)}{D_{0}^{2}})} Hhp(u,v)=1−e−c(D02D2(u,v))
其中,c为一个常数,控制高频与低频过渡段的曲线陡度,值越大表示越陡; D 0 D_{0} D0表示截止频率,其值越大对细节的增强越明显; D ( u , v ) D(u,v) D(u,v)表示和频率中心的距离。如图:
注:图片来源百度搜索
第三步:进行傅里叶反变换,返回空域对数图像:
s ( x , y ) = F − 1 [ S ( x , y ) ] = F − 1 [ H ( x , y ) F [ ln i ( x , y ) ] ] + F − 1 [ H ( x , y ) F [ ln r ( x , y ) ] ] s(x,y)=F^{-1}[S(x,y)]=F^{-1}[H(x,y)F[\ln{i(x,y)}]]+F^{-1}[H(x,y)F[\ln{r(x,y)}]] s(x,y)=F−1[S(x,y)]=F−1[H(x,y)F[lni(x,y)]]+F−1[H(x,y)F[lnr(x,y)]]
第四步:取指数,将对数的信号转换为原始形式信号,的到空域滤波结果:
g ( x , y ) = e s ( x , y ) g(x,y)=e^{s(x,y)} g(x,y)=es(x,y)
需要注意的是,在第一步操作中使用 ln ( f ( x , y ) + 1 ) \ln{(f(x,y)+1)} ln(f(x,y)+1),则此处需要使用 e s ( x , y ) − 1 e^{s(x,y)}-1 es(x,y)−1。
利用小波变换
传统的同态滤波与傅里叶变换作为变换工具,这种方法从图像的整体角度对光照不均匀进行修正,虽然可以很好地保持图像的原始面貌,但它没有充分考虑图像的空域局部特征,在增强一部分像素时导致另一部分增强。然而将小波变换作为域变换工具,在时域和频域上都具有局部性。
注:一般三层小波分解便能有较好的效果。
基于空域的同态滤波
上述两种均为频域的同态滤波方法,在转换为空域时需要花费时间,因此基于空域的同态滤波方法被人们提出。具体方法是:
第一步:进行对数变换;
第二步:对图像使用低通滤波器;
第三步:使用某一模型利用低通滤波器得到的数据来估计照明分量;
第四步:对照明分量和反射分量进行处理。
需要注意的是,该方法目前没有一种很好的方法能够对照度分量和反射分量进行估计,对特定的图像需要选取适当的滤波器并调节滤波器的系数以达到最好效果。
import cv2
import numpy as np
from skimage.metrics import peak_signal_noise_ratio
from skimage.metrics import structural_similarity
import csv
def homomorphic_filter(src, d0=10, rl=0.5, rh=2.0, c=4, h=2.0, l=0.5):
gray = src.copy()
if len(src.shape) > 2:
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) # 转换成灰度(RGB)图像
gray = np.log(1e-5 + gray) # 取对数
rows, cols = gray.shape #设置数据维度
gray_fft = np.fft.fft2(gray) # FFT傅里叶变换
gray_fftshift = np.fft.fftshift(gray_fft) # FFT中心化
M, N = np.meshgrid(np.arange(-cols // 2, cols // 2), np.arange(-rows // 2, rows // 2))
D = np.sqrt(M ** 2 + N ** 2) # 计算距离
Z = (rh - rl) * (1 - np.exp(-c * (D ** 2 / d0 ** 2))) + rl # H(u,v)传输函数,使用高斯滤波
dst_fftshift = Z * gray_fftshift
dst_fftshift = (h - l) * dst_fftshift + l
dst_ifftshift = np.fft.ifftshift(dst_fftshift)
dst_ifft = np.fft.ifft2(dst_ifftshift) # IFFT逆傅里叶变换
dst = np.real(dst_ifft) # IFFT取实部
dst = np.exp(dst) - 1 # 还原
dst = np.uint8(np.clip(dst, 0, 255))
return dst
#创建CSV表格用于存储数据
def writeCsv(image, psnr, ssim):
row = [image, psnr, ssim]
out = open("D:/homomorphic_filter/gauss/result.csv", "a", newline="")
csv_writer = csv.writer(out, dialect="excel")
csv_writer.writerow(row)
#同态滤波并计算psnr和ssim进行保存
#writeCsv("image", "psnr", "ssim")
for j in range(10, 100):
#同态滤波
img = cv2.imread('D:/homomorphic_filter/Infrared_image/00{}.jpg'.format(str(j)))
print(f"00{j}.jpg:")
img_new = homomorphic_filter(img)
#cv2.imshow("img", img)
#cv2.imshow("img_new", img_new)
cv2.imwrite("D:/homomorphic_filter/gauss/result_image/00{}.jpg".format(str(j)), img_new)
# 指标计算
img_1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 由于img是BGR图片,而img_new是RGB图像,所以计算psnr和ssim之前需要将img转化为RGB格式
psnr = peak_signal_noise_ratio(img_1, img_new)
ssim = structural_similarity(img_1, img_new, multichannel=True)
print(psnr)
print(ssim)
writeCsv(j, psnr, ssim)
#key = cv2.waitKey(0)
#cv2.destroyAllWindows()