在图像处理领域,去噪是一个重要的任务,它旨在从含有噪声的图像中恢复出原始的、清晰的图像。本文将介绍一种基于字典学习的方法来实现图像去噪,并展示不同变换方法在重建噪声图像时的效果。
实验中,首先使用在线字典学习对图像的扭曲部分进行拟合,然后利用这个字典来重建图像的另一部分。值得注意的是,如果从无噪声的图像开始拟合字典,可能会获得更好的性能,但在这里假设无噪声图像不可用。
通常,通过比较重建图像与原始图像之间的差异来评估去噪结果。如果重建完美,差异将呈现为高斯噪声。从图表中可以看出,使用正交匹配追踪(OMP)方法,当保留两个非零系数时,结果比只保留一个非零系数时的偏差要小(边缘看起来不那么突出)。此外,它在Frobenius范数上更接近真实值。最小角回归的结果则有较强的偏差:差异让人想起原始图像的局部强度值。阈值处理显然不适用于去噪,但在这里展示是为了说明它能够以非常高的速度产生有启发性的输出,因此可能适用于其他任务,如目标分类,其中性能不一定与可视化相关。
import numpy as np
try:
# Scipy >= 1.10
from scipy.datasets import face
except ImportError:
from scipy.misc import face
raccoon_face = face(gray=True)
# 将uint8表示转换为0到1之间的浮点表示
raccoon_face = raccoon_face / 255.0
# 为提高速度而降采样
raccoon_face = (raccoon_face[::4, ::4] + raccoon_face[1::4, ::4] + raccoon_face[::4, 1::4] + raccoon_face[1::4, 1::4]) / 4.0
height, width = raccoon_face.shape
# 扭曲图像的右半部分
print("Distorting image...")
distorted = raccoon_face.copy()
distorted[:, width//2:] += 0.075 * np.random.randn(height, width//2)
Distorting image...
import matplotlib.pyplot as plt
def show_with_diff(image, reference, title):
"""辅助函数显示去噪"""
plt.figure(figsize=(5, 3.3))
plt.subplot(1, 2, 1)
plt.title("Image")
plt.imshow(image, vmin=0, vmax=1, cmap=plt.cm.gray, interpolation="nearest")
plt.xticks(())
plt.yticks(())
plt.subplot(1, 2, 2)
difference = image - reference
plt.title("Difference (norm: %.2f)" % np.sqrt(np.sum(difference**2)))
plt.imshow(difference, vmin=-0.5, vmax=0.5, cmap=plt.cm.PuOr, interpolation="nearest")
plt.xticks(())
plt.yticks(())
plt.suptitle(title, size=16)
plt.subplots_adjust(0.02, 0.02, 0.98, 0.79, 0.02, 0.2)
show_with_diff(distorted, raccoon_face, "Distorted image")
from time import time
from sklearn.feature_extraction.image import extract_patches_2d
# 从图像的左半部分提取所有参考块
print("Extracting reference patches...")
t0 = time()
patch_size = (7, 7)
data = extract_patches_2d(distorted[:, :width//2], patch_size)
data = data.reshape(data.shape[0], -1)
data -= np.mean(data, axis=0)
data /= np.std(data, axis=0)
print(f"{data.shape[0]} patches extracted in %.2fs." % (time() - t0))
Extracting reference patches...
22692 patches extracted in 0.01s.
from sklearn.decomposition import MiniBatchDictionaryLearning
print("Learning the dictionary...")
t0 = time()
dico = MiniBatchDictionaryLearning(n_components=50, batch_size=200, alpha=1.0, max_iter=10)
V = dico.fit(data).components_
dt = time() - t0
print(f"{dico.n_iter_} iterations / {dico.n_steps_} steps in {dt:.2f}.")
from sklearn.feature_extraction.image import reconstruct_from_patches_2d
print("Extracting noisy patches...")
t0 = time()
data = extract_patches_2d(distorted[:, width//2:], patch_size)
data = data.reshape(data.shape[0], -1)
intercept = np.mean(data, axis=0)
data -= intercept
print("done in %.2fs." % (time() - t0))
比较了几种不同的变换算法在重建噪声图像时的效果。这些算法包括正交匹配追踪(OMP)、最小角回归(LARS)和阈值处理。每种方法都有其特定的参数设置,以适应不同的去噪需求。
实验结果显示,正交匹配追踪(OMP)在保留两个非零系数时,其结果的偏差较小,且在Frobenius范数上更接近真实值。最小角回归的结果则有较强的偏差。阈值处理虽然不适用于去噪,但其高速的计算能力使其在目标分类等任务中具有潜在的应用价值。