【图像处理基石】图像复原方面有哪些经典算法?
图像复原是指对退化的图像进行处理,恢复其原始状态的过程。入门级的经典图像复原算法主要针对噪声去除和模糊修复,以下是几种最基础且常用的算法,以及它们的Python实现:
一、经典入门算法简介
- 均值滤波:通过计算像素邻域的平均值来平滑图像,适用于去除高斯噪声,但会模糊边缘。
- 中值滤波:用邻域像素的中值替代中心像素,对椒盐噪声(随机出现的黑白点)效果显著,能较好保留边缘。
- 逆滤波:基于退化模型的频域方法,假设已知退化函数(如模糊核),直接在频域进行逆操作(对初学者理解退化模型很有帮助)。
- 维纳滤波:在逆滤波基础上加入噪声统计特性,是一种自适应滤波,对噪声更稳健。
二、Python实现
以下代码使用OpenCV
处理图像,NumPy
进行数值计算,Matplotlib
显示结果。请先安装依赖:pip install opencv-python numpy matplotlib
import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取图像(转为灰度图便于处理)
def load_image(path):img = cv2.imread(path)if img is None:raise ValueError("无法读取图像,请检查路径")return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 添加噪声(模拟退化)
def add_noise(img, noise_type="gaussian", param=0.01):"""添加噪声:- gaussian:高斯噪声,param为噪声方差- salt_pepper:椒盐噪声,param为噪声比例"""img = img.astype(np.float32) / 255.0 # 归一化到[0,1]if noise_type == "gaussian":noise = np.random.normal(0, param, img.shape)noisy_img = img + noiseelif noise_type == "salt_pepper":noisy_img = img.copy()# 椒盐噪声比例salt_ratio = param / 2pepper_ratio = param / 2# 随机生成盐噪声(白点)salt = np.random.rand(*img.shape) < salt_rationoisy_img[salt] = 1.0# 随机生成椒噪声(黑点)pepper = np.random.rand(*img.shape) < pepper_rationoisy_img[pepper] = 0.0else:raise ValueError("噪声类型仅支持'gaussian'或'salt_pepper'")return np.clip(noisy_img, 0, 1) # 确保值在[0,1]范围内# 1. 均值滤波
def mean_filter(img, kernel_size=3):"""简单均值滤波:计算邻域平均值"""h, w = img.shapepad = kernel_size // 2# 边缘填充padded = np.pad(img, pad, mode="edge")result = np.zeros_like(img)for i in range(h):for j in range(w):# 取邻域neighborhood = padded[i:i+kernel_size, j:j+kernel_size]result[i, j] = np.mean(neighborhood)return result# 2. 中值滤波
def median_filter(img, kernel_size=3):"""中值滤波:用邻域中值替代中心像素"""h, w = img.shapepad = kernel_size // 2padded = np.pad(img, pad, mode="edge")result = np.zeros_like(img)for i in range(h):for j in range(w):neighborhood = padded[i:i+kernel_size, j:j+kernel_size]result[i, j] = np.median(neighborhood)return result# 3. 逆滤波(假设退化模型为模糊+噪声)
def inverse_filter(noisy_img, blur_kernel, snr=10):"""逆滤波:频域中对退化图像除以模糊核- blur_kernel:退化函数(模糊核)- snr:信噪比(用于简化噪声处理)"""# 傅里叶变换img_fft = np.fft.fft2(noisy_img)# 模糊核填充到与图像同尺寸kernel_padded = np.zeros_like(noisy_img)k_h, k_w = blur_kernel.shapekernel_padded[:k_h, :k_w] = blur_kernelkernel_fft = np.fft.fft2(kernel_padded)# 逆滤波(加入小值避免除零)eps = 1e-5 # 防止除以零restored_fft = img_fft / (kernel_fft + eps)# 逆傅里叶变换restored = np.fft.ifft2(restored_fft).realreturn np.clip(restored, 0, 1)# 4. 维纳滤波
def wiener_filter(noisy_img, blur_kernel, snr=10):"""维纳滤波:频域中自适应处理,公式为 |H*|²/(|H|² + S_n/S_s) * G- H为退化函数,G为退化图像频谱,S_n/S_s为噪声功率谱与信号功率谱比"""# 傅里叶变换img_fft = np.fft.fft2(noisy_img)# 模糊核填充kernel_padded = np.zeros_like(noisy_img)k_h, k_w = blur_kernel.shapekernel_padded[:k_h, :k_w] = blur_kernelkernel_fft = np.fft.fft2(kernel_padded)# 计算维纳滤波系数kernel_conj = np.conj(kernel_fft) # 共轭kernel_mag_sq = np.abs(kernel_fft) **2 # 幅度平方noise_power = 1.0 / snr # 简化:噪声功率 = 1/SNRwiener_coeff = kernel_conj / (kernel_mag_sq + noise_power)# 应用滤波restored_fft = wiener_coeff * img_fftrestored = np.fft.ifft2(restored_fft).realreturn np.clip(restored, 0, 1)# 展示结果
def show_results(original, degraded, restored, title):plt.figure(figsize=(12, 4))plt.subplot(131)plt.imshow(original, cmap="gray")plt.title("原图")plt.axis("off")plt.subplot(132)plt.imshow(degraded, cmap="gray")plt.title("退化图")plt.axis("off")plt.subplot(133)plt.imshow(restored, cmap="gray")plt.title(title)plt.axis("off")plt.tight_layout()plt.show()# 主函数:测试各算法
if __name__ == "__main__":# 读取图像(替换为自己的图像路径)img = load_image("test_image.jpg") # 请确保有此图像,或用cv2.imread的默认图像测试# 1. 测试中值滤波(针对椒盐噪声)salt_pepper_img = add_noise(img, "salt_pepper", param=0.05) # 5%椒盐噪声median_restored = median_filter(salt_pepper_img, kernel_size=3)show_results(img, salt_pepper_img, median_restored, "中值滤波复原")# 2. 测试均值滤波(针对高斯噪声)gaussian_img = add_noise(img, "gaussian", param=0.01) # 高斯噪声(方差0.01)mean_restored = mean_filter(gaussian_img, kernel_size=3)show_results(img, gaussian_img, mean_restored, "均值滤波复原")# 3. 测试逆滤波和维纳滤波(针对模糊+噪声)# 定义模糊核(模拟运动模糊)blur_kernel = np.ones((5, 5)) / 25 # 简单均值模糊核# 先模糊图像,再添加噪声blurred_img = cv2.filter2D(img.astype(np.float32)/255, -1, blur_kernel)blurred_noisy_img = add_noise(blurred_img, "gaussian", param=0.005)# 逆滤波复原inverse_restored = inverse_filter(blurred_noisy_img, blur_kernel)show_results(img, blurred_noisy_img, inverse_restored, "逆滤波复原")# 维纳滤波复原wiener_restored = wiener_filter(blurred_noisy_img, blur_kernel, snr=20)show_results(img, blurred_noisy_img, wiener_restored, "维纳滤波复原")
三、算法说明与使用建议
1.** 均值滤波 :实现简单,但会模糊图像细节,适合初步平滑高斯噪声。
2. 中值滤波 :是去除椒盐噪声的首选,3x3核效果较好(核过大会导致过度模糊)。
3. 逆滤波 :理论简单但实用性低(对噪声极其敏感),主要用于理解退化模型(退化图像 = 原图 * 退化函数 + 噪声
)。
4. 维纳滤波 **:比逆滤波更实用,通过引入信噪比动态调整滤波强度,适合同时存在模糊和噪声的场景。
四、扩展学习
入门后可进一步学习:
- 非局部均值滤波(更先进的噪声去除,保留细节能力强)
- BM3D(当前最优的噪声去除算法之一)
- 盲去卷积(无需已知退化函数的模糊修复)
这些算法的核心思想仍是基于邻域信息或频域分析,掌握经典算法后更容易理解高级方法。