【图像增强】去条纹 + 去暗角 + 去模糊 + 去噪 + 超分

部署运行你感兴趣的模型镜像

一、去模糊:反卷积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恢复图像的模糊性

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖墩会武术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值