图像去噪–总变差去噪(TV)
引用资料:
1.全变分图像去噪算法(TV)
2.TV去噪的理解
总变差去噪 (Total Variation Denoising) 是一种经典的图像去噪方法,能够有效减少噪声,同时保留图像的边缘细节。该方法的核心思想是通过最小化图像的“总变差”来实现图像平滑,避免过度平滑损失边缘。
下图来自:1.全变分图像去噪算法(TV)
下图来自:1.全变分图像去噪算法(TV)
1.1 定义全变分
1.1.1 数学定义
全变分(TV)度量图像中梯度变化的总量,它是衡量图像平滑程度的一个关键指标。在图像去噪中,全变分的定义帮助我们描述图像的整体变化,尤其是边缘区域的变化。
1.1.2 疑问一:为什么要对图像梯度求绝对值?
1.1.3 疑问二:为什么要对图像梯度的绝对值进行积分?
1.2 能量泛函建模
1.2.1 数学定义
1.2.2 疑问一:什么是泛函?
1.2.3 疑问二:泛函在图像去噪方面的作用?
1.3 求解欧拉-拉格朗日方程
1.4 梯度下降法
1.5 有限差分求近似解
1.6 代码实现
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 定义 PSNR 计算函数
def calculate_psnr(original, denoised):
mse = np.mean((original - denoised) ** 2)
if mse == 0: # 避免除零
return float('inf')
max_pixel = 255.0
psnr = 20 * np.log10(max_pixel / np.sqrt(mse))
return psnr
# 定义 TV 去噪(梯度下降法)
def tv_denoise(image, lambda_tv=0.1, iterations=100, tau=0.125):
u = image.astype(np.float64)
m, n = u.shape
for i in range(iterations):
# 计算梯度
u_x = np.roll(u, -1, axis=1) - u # x方向梯度
u_y = np.roll(u, -1, axis=0) - u # y方向梯度
# 计算梯度的模长
grad_u = np.sqrt(u_x**2 + u_y**2 + 1e-8) # 避免除零
# 更新u,使用离散梯度下降
u = u + tau * (np.roll(u_x / grad_u, 1, axis=1) - u_x / grad_u + np.roll(u_y / grad_u, 1, axis=0) - u_y / grad_u) - tau * lambda_tv * (u - image)
return np.clip(u, 0, 255).astype(np.uint8)
# 打开图片并转换为灰度图像
img_dir = r'D:\Document\Experiment\data\image1.jpg'
gray = cv.imread(img_dir, 0) # 读取图像并转换为灰度
image_array = np.array(gray)
# 定义高斯噪声的参数
mean = 0 # 均值
sigma = 20 # 调低噪声强度(标准差)
# 生成高斯噪声
gaussian_noise = np.random.normal(mean, sigma, image_array.shape)
# 将噪声加入图像
noisy_image = image_array + gaussian_noise
# 将噪声后的图像剪裁到0-255范围内,并转换为uint8
noisy_image_clipped = np.clip(noisy_image, 0, 255).astype(np.uint8)
# 调用 TV 去噪
denoised_image = tv_denoise(noisy_image_clipped, lambda_tv=0.1, iterations=100, tau=0.125)
# 计算原始图像和去噪图像的 PSNR
psnr_noisy = calculate_psnr(image_array, noisy_image_clipped)
psnr_denoised = calculate_psnr(image_array, denoised_image)
# 显示原图、噪声图像和去噪后的图像
plt.figure(figsize=(15, 5))
plt.subplot(1, 3, 1)
plt.title('Original Image')
plt.imshow(image_array, cmap='gray')
plt.subplot(1, 3, 2)
plt.title(f'Noisy Image (PSNR: {psnr_noisy:.2f})')
plt.imshow(noisy_image_clipped, cmap='gray')
plt.subplot(1, 3, 3)
plt.title(f'Denoised Image (PSNR: {psnr_denoised:.2f})')
plt.imshow(denoised_image, cmap='gray')
plt.show()
目前没有分析去噪后PSNR值下降的原因