文章目录
一、去模糊:反卷积RL
【PyTorch项目实战】反卷积(Deconvolution)概述
Richardson-Lucy (RL) 反卷积算法 —— 通过不断迭代更新图像估计值
二、去条纹:FFT频域滤波
去条纹算法 —— 兼容自然图像与荧光图像的频域滤波方法(FFT)
三、去暗角
四、去噪算法
| 方法 | 计算复杂度 | 边缘保留性 | 适用场景 |
|---|---|---|---|
| 均值滤波 | 低 | 弱 | 快速预处理 |
| 中值滤波 | 中 | 中 | 椒盐噪声 |
| 双边滤波 | 高 | 强 | 一般图像 |
| 非局部均值 | 高 | 强 | 工业/科研图像 |
| DnCNN | 中 | 优 | 高斯/未知噪声通用 |
1、传统去噪算法:均值滤波、中值滤波、双边滤波、非局部均值去噪

# -*- coding: utf-8 -*-
"""
图像去噪示例(传统算法)
涵盖:均值滤波、中值滤波、双边滤波、非局部均值去噪
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 设置中文显示支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# === 1. 读取图像 ===
img = cv2.imread('../image/image.jpg') # 按默认路径读取图像
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换为RGB,便于Matplotlib显示
# === 2. 添加模拟高斯噪声(用于演示) ===
noise = np.random.normal(0, 25, img.shape) # 生成均值0、方差25的高斯噪声
noisy_img = np.clip(img + noise, 0, 255).astype(np.uint8) # 添加并裁剪到合法范围
# === 3. 均值滤波 ===
mean_denoised = cv2.blur(noisy_img, (5, 5)) # 5×5均值滤波核
# === 4. 中值滤波 ===
median_denoised = cv2.medianBlur(noisy_img, 5) # 5×5中值滤波核
# === 5. 双边滤波 ===
bilateral_denoised = cv2.bilateralFilter(noisy_img, 9, 75, 75)
# 参数:9为邻域直径,75/75为颜色空间和坐标空间的高斯标准差
# === 6. 非局部均值去噪 ===
nlm_denoised = cv2.fastNlMeansDenoisingColored(
noisy_img, None, 10, 10, 7, 21
)
# 参数:hColor/hLuminance=10, templateWindowSize=7, searchWindowSize=21
# === 7. 可视化结果 ===
titles = ['原图', '加噪图', '均值滤波', '中值滤波', '双边滤波', '非局部均值']
images = [img, noisy_img, mean_denoised, median_denoised, bilateral_denoised, nlm_denoised]
plt.figure(figsize=(12, 8))
for i in range(6):
plt.subplot(2, 3, i + 1)
plt.imshow(images[i])
plt.title(titles[i])
plt.axis('off')
plt.tight_layout()
plt.show()
2、自适应方向保持去噪(方向性结构张量 + 方向性高斯加权滤波)
算法核心思想:
- 使用结构张量估计局部主方向与各向异性程度;
- 根据主方向自适应构造方向性高斯/双边滤波核(或方向性加权窗),在主方向上保持细节(低平滑),垂直方向上增强平滑;
- 在噪声较强或各向同性区域退化为普通去噪(例如NLM或双边)以保证稳定性;
- 对SEM单通道图像优化参数并提供调参建议。
算法优点:保留纤维状/条纹状微结构(SEM常见),抑制颗粒噪声;可结合多尺度(pyramid)增强鲁棒性。
参数说明与调参建议(针对SEM场景)
- sigma_grad:结构张量平滑尺度,建议在0.5~2.0之间调节。SEM细节极细时取较小值(0.6左右);噪声强时可适当增大。
- sigma_par_min / sigma_par_max:用于在低/高各向异性之间插值的平行方向sigma。越小则在主方向上越保留细节,推荐范围[0.4,2.5]。
- sigma_perp_ratio:垂直方向相对于平行方向的放大倍数,典型取值2~5,SEM中建议3左右以加强纵向平滑。
- radius:滤波半径,影响计算复杂度与局部上下文,建议5~9。
- aniso_thresh:各向异性阈值,当局部结构不明显时退化到各向同性去噪,避免误估方向导致伪影;建议0.08~0.2。

# -*- coding: utf-8 -*-
"""
SEM自适应方向保持去噪(方向性结构张量 + 方向性高斯加权滤波)
说明:
- 默认读取路径: ../image/image.jpg
- 面向单通道灰度图(SEM常用)
- 每一行均带有中文注释,便于教学与出版
"""
import cv2 # 导入OpenCV库用于图像I/O与基础操作
import numpy as np # 导入NumPy用于数值计算
from scipy import ndimage as ndi # 导入scipy.ndimage用于高阶滤波与插值
import math # 导入math用于数学函数
def compute_structure_tensor(img, sigma=1.0):
# 计算输入图像的结构张量并返回张量分量(Jxx,Jxy,Jyy)
# 参数:
# img: float32 灰度图,取值范围[0,255]或[0,1]
# sigma: 用于计算梯度前的高斯平滑尺度
I = img.astype(np.float32) # 将图像转换为float32以确保数值精度
I_smooth = ndi.gaussian_filter(I, sigma) # 先按照sigma对图像进行高斯平滑以降低噪声对梯度的影响
Ix = ndi.sobel(I_smooth, axis=1, mode='reflect') # 计算水平方向梯度(x方向)
Iy = ndi.sobel(I_smooth, axis=0, mode='reflect') # 计算垂直方向梯度(y方向)
Jxx = Ix * Ix # 结构张量分量J_xx = I_x^2
Jxy = Ix * Iy # 结构张量分量J_xy = I_x * I_y
Jyy = Iy * Iy # 结构张量分量J_yy = I_y^2
# 对结构张量分量再做一个较大尺度的高斯平滑,以得到局部统计量
Jxx = ndi.gaussian_filter(Jxx, sigma * 2.0) # Jxx局部平滑
Jxy = ndi.gaussian_filter(Jxy, sigma * 2.0) # Jxy局部平滑
Jyy = ndi.gaussian_filter(Jyy, sigma * 2.0) # Jyy局部平滑
return Jxx, Jxy, Jyy # 返回三个分量供后续特征计算
def tensor_orientation_anisotropy(Jxx, Jxy, Jyy, eps=1e-12):
# 从结构张量分量计算主方向角theta(弧度)和各向异性度aniso(0~1)
# 参数:
# Jxx,Jxy,Jyy: 结构张量分量
trace = Jxx + Jyy # 计算迹(trace)
det = Jxx * Jyy - Jxy * Jxy # 计算行列式(determinant)
# 计算特征值lambda1 >= lambda2
tmp = np.sqrt(np.maximum((Jxx - Jyy)**2 + 4.0 * Jxy * Jxy, 0.0)) # 特征值计算的中间项
lambda1 = 0.5 * (trace + tmp) # 较大特征值
lambda2 = 0.5 * (trace - tmp) # 较小特征值
# 各向异性度定义为 (lambda1 - lambda2) / (lambda1 + lambda2 + eps)
aniso = (lambda1 - lambda2) / (lambda1 + lambda2 + eps) # 归一化的各向异性度,越接近1越方向性明显
# 计算主方向角theta = 0.5 * atan2(2*Jxy, Jxx - Jyy)
theta = 0.5 * np.arctan2(2.0 * Jxy, (Jxx - Jyy + eps)) # 主方向角,范围约为(-pi/2,pi/2)
return theta, aniso # 返回角度与各向异性度
def directional_kernel(radius, sigma_parallel, sigma_perp, angle):
# 构造一个在给定角度处的方向性高斯核(未归一化)
# 参数:
# radius: 核半径(像素)
# sigma_parallel: 平行于主方向的高斯标准差(保留更多细节时取较小值)
# sigma_perp: 垂直于主方向的高斯标准差(垂直方向加大平滑)
# angle: 主方向角(弧度)
diameter = 2 * radius + 1 # 计算核直径
ys, xs = np.mgrid[-radius:radius+1, -radius:radius+1] # 生成网格坐标
# 将网格坐标旋转到主方向坐标系
cos_a = math.cos(angle) # 计算cos(angle)
sin_a = math.sin(angle) # 计算sin(angle)
x_rot = cos_a * xs + sin_a * ys # 旋转后的x坐标(平行方向)
y_rot = -sin_a * xs + cos_a * ys # 旋转后的y坐标(垂直方向)
# 方向性高斯:在平行方向使用sigma_parallel,垂直方向使用sigma_perp
kern = np.exp(-0.5 * ((x_rot**2) / (sigma_parallel**2 + 1e-12) + (y_rot**2) / (sigma_perp**2 + 1e-12)))
kern /= (np.sum(kern) + 1e-12) # 归一化核,使权重和为1
return kern # 返回方向性高斯核
def adaptive_directional_denoise(img, radius=7, sigma_grad=1.0, sigma_par_min=0.5, sigma_par_max=2.5, sigma_perp_ratio=3.0, aniso_thresh=0.15):
# 对输入灰度图执行自适应方向性去噪
# 参数:
# img: np.ndarray 单通道灰度图,dtype=u8或float32
# radius: 局部方向性滤波核半径
# sigma_grad: 用于结构张量的平滑尺度
# sigma_par_min/sigma_par_max: 平行方向sigma的范围
# sigma_perp_ratio: 垂直方向sigma = sigma_parallel * sigma_perp_ratio
# aniso_thresh: 各向异性阈值,当aniso小于此值时使用非方向性退化策略
I = img.astype(np.float32) # 将图像转为float32用于计算
Jxx, Jxy, Jyy = compute_structure_tensor(I, sigma=sigma_grad) # 计算结构张量分量
theta, aniso = tensor_orientation_anisotropy(Jxx, Jxy, Jyy) # 计算每像素主方向与各向异性度
h, w = I.shape # 获取图像高宽
output = np.zeros_like(I) # 初始化输出图像数组
pad = radius # 填充大小等于半径
I_padded = np.pad(I, pad, mode='reflect') # 对图像进行反射填充以便边界处理
theta_padded = np.pad(theta, pad, mode='reflect') # 对角度图做相同填充
aniso_padded = np.pad(aniso, pad, mode='reflect') # 对各向异性图做相同填充
# 逐像素应用方向性滤波(可向量化或分块加速,此处为清晰易懂的实现)
for y in range(h): # 遍历图像每一行像素
for x in range(w): # 遍历图像每一列像素
yy = y + pad # 计算填充后对应y坐标
xx = x + pad # 计算填充后对应x坐标
local_theta = float(theta_padded[yy, xx]) # 读取局部主方向角
local_aniso = float(aniso_padded[yy, xx]) # 读取局部各向异性度
# 根据各向异性度线性插值选择平行方向sigma(强方向性时使用小sigma以保留细节)
sigma_par = sigma_par_max - (sigma_par_max - sigma_par_min) * local_aniso
sigma_perp = sigma_par * sigma_perp_ratio # 垂直方向sigma通常大于平行方向
# 当局部各向异性低于阈值时退化到非方向性快速去噪(例如使用局部均值或高斯)
if local_aniso < aniso_thresh:
# 提取方形邻域并直接使用高斯权重做平滑
patch = I_padded[yy-pad:yy+pad+1, xx-pad:xx+pad+1] # 提取方形补丁
# 构造各向同性高斯核
ys, xs = np.mgrid[-pad:pad+1, -pad:pad+1] # 局部坐标网格
iso_kern = np.exp(-0.5 * ((xs**2 + ys**2) / ( (sigma_par * sigma_perp_ratio)**2 + 1e-12)))
iso_kern /= (np.sum(iso_kern) + 1e-12) # 归一化
val = np.sum(patch * iso_kern) # 加权求和得到中心像素的值
output[y, x] = val # 写入输出像素
else:
# 构建方向性核并应用到局部补丁
kern = directional_kernel(pad, sigma_par, sigma_perp, local_theta) # 方向性核
patch = I_padded[yy-pad:yy+pad+1, xx-pad:xx+pad+1] # 提取对应补丁
val = np.sum(patch * kern) # 使用方向性核加权求和
output[y, x] = val # 写入输出像素
return np.clip(output, 0.0, 255.0).astype(np.uint8) # 裁剪并返回uint8图像
if __name__ == '__main__':
# 演示部分:读取图像,添加合成噪声,并进行方向性去噪
img_path = r"D:\py\line\image.png" # 默认图像路径(遵循项目约定)
img_bgr = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # 读取图像(可能为16位或8位)
if img_bgr is None: # 检查图像是否成功读取
raise FileNotFoundError(f'无法读取图像: {img_path}') # 抛出文件未找到错误
# 若图像为彩色或多通道,转换为灰度;SEM一般为灰度图
if img_bgr.ndim == 3 and img_bgr.shape[2] >= 3:
img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) # 转为灰度
else:
img_gray = img_bgr.copy() # 直接复制单通道图像
# 将任何16位图像缩放到8位以便处理(若需要保留高位精度可修改此处)
if img_gray.dtype == np.uint16:
img_gray = (img_gray / 256).astype(np.uint8) # 将16位下采样到8位
# 为演示添加合成高斯噪声(真实SEM数据通常直接使用原图)
sigma_demo = 15 # 合成噪声的标准差(像素值层面)
noise = np.random.randn(*img_gray.shape) * sigma_demo # 生成高斯噪声
noisy = np.clip(img_gray.astype(np.float32) + noise, 0, 255).astype(np.uint8) # 得到加噪图
# 调用自适应方向性去噪函数
denoised = adaptive_directional_denoise(noisy, radius=7, sigma_grad=1.0, sigma_par_min=0.6, sigma_par_max=2.0, sigma_perp_ratio=3.0, aniso_thresh=0.12)
# 使用plt显示图像
import matplotlib.pyplot as plt
# 设置中文显示支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 显示原图
plt.subplot(1, 3, 1)
plt.imshow(img_gray, cmap='gray')
plt.title('原图')
plt.axis('off')
# 显示加噪图
plt.subplot(1, 3, 2)
plt.imshow(noisy, cmap='gray')
plt.title('加噪图')
plt.axis('off')
# 显示去噪图
plt.subplot(1, 3, 3)
plt.imshow(denoised, cmap='gray')
plt.title('去噪图')
plt.axis('off')
# 显示图像
plt.show()
3、DnCNN去噪卷积神经网络(PyTorch)
DnCNN(Denoising Convolutional Neural Network)是一种基于卷积神经网络的图像去噪算法,由张凯平等人在2017年提出。
- 其核心思想是利用深层卷积网络直接学习从噪声图像到“噪声成分”的映射关系,再通过将预测出的噪声从原图中减去,得到干净图像。
- 采用残差学习(Residual Learning)策略,使网络更易于训练;
- 结合批归一化(Batch Normalization)来加速收敛与稳定训练过程。
- 该模型可同时处理高斯噪声去除、JPEG压缩伪影消除以及盲去噪等任务,表现优于传统滤波方法(如BM3D),代表了深度学习在图像去噪领域的典型应用。
- 网络结构较轻,可在CPU上运行。
- channels=3:输入必须是RGB等三通道图像

# -*- coding: utf-8 -*-
"""
基于PyTorch的DnCNN图像去噪实现
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as T
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
# === 1. 定义DnCNN网络结构 ===
class DnCNN(nn.Module):
def __init__(self, channels=3, num_layers=17):
super(DnCNN, self).__init__()
layers = []
# 第一层:卷积 + ReLU
layers.append(nn.Conv2d(channels, 64, kernel_size=3, padding=1, bias=False))
layers.append(nn.ReLU(inplace=True))
# 中间层:卷积 + BN + ReLU
for _ in range(num_layers - 2):
layers.append(nn.Conv2d(64, 64, kernel_size=3, padding=1, bias=False))
layers.append(nn.BatchNorm2d(64))
layers.append(nn.ReLU(inplace=True))
# 最后一层:卷积输出噪声残差
layers.append(nn.Conv2d(64, channels, kernel_size=3, padding=1, bias=False))
self.dncnn = nn.Sequential(*layers)
def forward(self, x):
out = self.dncnn(x)
return x - out # 输出为去噪后的图像(原图减去预测噪声)
# === 2. 图像预处理函数 ===
def preprocess(img_path):
img = Image.open(img_path).convert('RGB') # 打开并转换为RGB
transform = T.Compose([T.ToTensor()]) # 转换为张量格式[0,1]
img_tensor = transform(img).unsqueeze(0) # 增加batch维度
return img, img_tensor
# === 3. 添加噪声函数 ===
def add_gaussian_noise(img_tensor, sigma=25):
noise = torch.randn_like(img_tensor) * (sigma / 255.0)
noisy = torch.clamp(img_tensor + noise, 0., 1.)
return noisy
# === 4. 推理流程 ===
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = DnCNN().to(device)
model.eval() # 推理模式
# 加载图像
img, clean = preprocess('../image/image.jpg')
noisy = add_gaussian_noise(clean)
# 输入模型
with torch.no_grad():
denoised = model(noisy.to(device)).cpu()
# 转换为可显示图像
to_pil = T.ToPILImage()
noisy_img = to_pil(noisy.squeeze())
denoised_img = to_pil(denoised.squeeze())
# === 5. 可视化对比 ===
plt.figure(figsize=(10, 4))
plt.subplot(1, 3, 1)
plt.imshow(img)
plt.title('原图')
plt.axis('off')
plt.subplot(1, 3, 2)
plt.imshow(noisy_img)
plt.title('加噪图')
plt.axis('off')
plt.subplot(1, 3, 3)
plt.imshow(denoised_img)
plt.title('去噪结果(DnCNN)')
plt.axis('off')
plt.tight_layout()
plt.show()
五、超分
1、fairSIM:一种快速而温和的超分辨率方法(显著提升图像分辨率)
fairSIM:一种快速而温和的超分辨率方法(显著提升图像分辨率)
2、RCAN:使用非常深的残差通道注意力网络实现图像超分辨率
【PyTorch项目实战】超分RCAN:使用非常深的残差通道注意力网络实现图像超分辨率 —— (自研)解决了RCAN恢复图像的模糊性
499

被折叠的 条评论
为什么被折叠?



