【计算机视觉】三、图像处理——实验:图像去模糊和去噪、提取边缘特征

文章目录

  • [0. 实验环境](#0. 实验环境)
  • [1. 理论基础](#1. 理论基础)
    • [1.1 滤波器(卷积核)](#1.1 滤波器(卷积核))
    • [1.2 PyTorch:卷积操作](#1.2 PyTorch:卷积操作)
  • [2. 图像处理](#2. 图像处理)
    • [2.1 图像读取](#2.1 图像读取)
    • [2.2 查看通道](#2.2 查看通道)
    • [2.3 图像处理](#2.3 图像处理)
  • [3. 图像去模糊](#3. 图像去模糊)
  • [4. 图像去噪](#4. 图像去噪)
    • [4.1 添加随机噪点](#4.1 添加随机噪点)
    • [4.2 图像去噪](#4.2 图像去噪)

0. 实验环境

本实验使用了PyTorch深度学习框架,相关操作如下:

shell 复制代码
conda create -n DL python==3.11
shell 复制代码
conda activate DL
shell 复制代码
conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia
shell 复制代码
conda install matplotlib
shell 复制代码
conda install pillow numpy
软件包 本实验版本
matplotlib 3.8.0
numpy 1.26.3
pillow 10.0.1
python 3.11.0
torch 2.1.2
torchaudio 2.1.2
torchvision 0.16.2

1. 理论基础

二维卷积运算是信号处理和图像处理中常用的一种运算方式,当给定两个二维离散信号或图像 f ( x , y ) f(x, y) f(x,y) 和 g ( x , y ) g(x, y) g(x,y),其中 f ( x , y ) f(x, y) f(x,y) 表示输入信号或图像, g ( x , y ) g(x, y) g(x,y) 表示卷积核。二维卷积运算可以表示为: h ( x , y ) = ∑ m ∑ n f ( m , n ) ⋅ g ( x − m , y − n ) h(x, y) = \sum_{m}\sum_{n} f(m, n) \cdot g(x-m, y-n) h(x,y)=m∑n∑f(m,n)⋅g(x−m,y−n)其中 ∑ m ∑ n \sum_{m}\sum_{n} ∑m∑n 表示对所有 m , n m, n m,n 的求和, h ( x , y ) h(x, y) h(x,y) 表示卷积后的输出信号或图像。

在数学上,二维卷积运算可以理解为将输入信号或图像 f ( x , y ) f(x, y) f(x,y) 和卷积核 g ( x , y ) g(x, y) g(x,y) 进行对应位置的乘法 ,然后将所有乘积值相加得到输出信号或图像 h ( x , y ) h(x, y) h(x,y) 。这个过程可以用于实现一些信号处理和图像处理的操作,例如模糊、边缘检测、图像增强等。

详见:【深度学习】Pytorch 系列教程(七):PyTorch数据结构:2、张量的数学运算(5):二维卷积及其数学原理

1.1 滤波器(卷积核)

在图像处理中,卷积经常作为特征提取的有效方法.一幅图像在经过卷积操作后得到结果称为特征映射 (Feature Map)。图5.3给出在图像处理中几种常用的滤波器,以及其对应的特征映射.图中最上面的滤波器是常用的高斯滤波器 ,可以用来对图像进行平滑去噪 ;中间和最下面的滤波器可以用来提取边缘特征

python 复制代码
# 高斯滤波~平滑去噪
conv_kernel1 = torch.tensor([[1/16, 1/8, 1/16],
                            [1/8, 1/4, 1/8],
                            [1/16, 1/8, 1/16]], dtype=torch.float).unsqueeze(0).unsqueeze(0)
# 提取边缘特征
conv_kernel2 = torch.tensor([[0, 1, 0],
                            [1, -4, 1],
                            [0, 1, 0]], dtype=torch.float).unsqueeze(0).unsqueeze(0)
conv_kernel3 = torch.tensor([[0, 1, 1],
                            [-1, 0, 1],
                            [-1, -1, 0]], dtype=torch.float).unsqueeze(0).unsqueeze(0)
print(conv_kernel1.size())
  • 上述均为3x3的单通道卷积核,需要拓展为四维张量(PyTorch就是这么设计的~)

1.2 PyTorch:卷积操作

python 复制代码
def conv2d(img_tensor, conv_kernel):
    convolved_channels = []
    for i in range(3):
        channel_input = img_tensor[:, i, :, :]  # 取出每个通道的输入
        convolved = F.conv2d(channel_input, conv_kernel, padding=1)  
        convolved_channels.append(convolved)

    # 合并各通道卷积后的结果
    output = torch.cat(convolved_channels, dim=1)
    # 将张量转换为NumPy数组,进而转换为图像
    output_img = output.squeeze().permute(1, 2, 0).numpy().astype(np.uint8)
    output_img = Image.fromarray(output_img)
    return output_img

2. 图像处理

2.1 图像读取

python 复制代码
img = Image.open('1.jpg')  
# img = img.resize((128, 128))  # 调整图像大小

img_tensor = torch.tensor(np.array(img), dtype=torch.float).permute(2, 0, 1).unsqueeze(0)

print(img_tensor.shape)
  • 将图像转换为PyTorch张量:将通道顺序从HWC转换为CHW,并在第一个维度上增加一个维度~卷积操作使用四维张量

2.2 查看通道

本部分内容纯属没事儿闲的~

python 复制代码
img = Image.open('1.jpg')  
img_tensor = torch.tensor(np.array(img), dtype=torch.float).permute(2, 0, 1).unsqueeze(0)
channel1 = img_tensor[:, 0, :, :]  # 提取每个通道
channel2 = img_tensor[:, 1, :, :] 
channel3 = img_tensor[:, 2, :, :]  
plt.figure(figsize=(12, 12)) 
plt.subplot(1, 4, 1)
plt.imshow(img)
plt.axis('off')
plt.subplot(1, 4, 2)
channel1_img = channel1.squeeze().numpy().astype(np.uint8)
channel1_img = Image.fromarray(channel1_img)
plt.imshow(channel1_img)
plt.axis('off')
plt.subplot(1, 4, 3)
channel2_img = channel2.squeeze().numpy().astype(np.uint8)
channel2_img = Image.fromarray(channel2_img)
plt.imshow(channel2_img)
plt.axis('off')
plt.subplot(1, 4, 4)
channel3_img = channel3.squeeze().numpy().astype(np.uint8)
channel3_img = Image.fromarray(channel3_img)
plt.imshow(channel3_img)
plt.axis('off')

2.3 图像处理

python 复制代码
def plot_img(img_tensor): 
    output_img1 = conv2d(img_tensor, conv_kernel1)
    output_img2 = conv2d(img_tensor, conv_kernel2)
    output_img3 = conv2d(img_tensor, conv_kernel3)
    
    plt.subplot(2, 2, 1)
    plt.title('原始图像', fontproperties=font)
    plt.imshow(img)
    plt.axis('off')  
    plt.subplot(2, 2, 2)
    plt.title('平滑去噪', fontproperties=font)
    plt.imshow(output_img1)
    plt.axis('off')  
    plt.subplot(2, 2, 3)
    plt.imshow(output_img2)
    plt.title('边缘特征1', fontproperties=font)  
    plt.axis('off')  
    plt.subplot(2, 2, 4)
    plt.imshow(output_img3)
    plt.title('边缘特征2', fontproperties=font)  
    plt.axis('off')  
    plt.show()
python 复制代码
font = FontProperties(fname='C:\Windows\Fonts\simkai.ttf', size=16)  # 使用楷体
plt.figure(figsize=(12, 12))  # 设置图大小12*12英寸
plot_img(img_tensor)  
  • 如图所示,图像提取边缘特征效果明显
  • 但图片过于高清,plt输出的(12英寸)原始图像、平滑去噪图像都很模糊~,下面会先降低像素,然后进行去模糊去噪实验
  • 原图为

3. 图像去模糊

python 复制代码
img = Image.open('2.jpg')  
img = img.resize((480, 480))  # 调小图像~先使原图变模糊
img_tensor = torch.tensor(np.array(img), dtype=torch.float).permute(2, 0, 1).unsqueeze(0)
conv_kernel4 = torch.tensor([[0, 0, 0],
                            [0, 2, 0],
                            [0, 0, 0]], dtype=torch.float).unsqueeze(0).unsqueeze(0)
conv_kernel5 = torch.ones(3, 3).unsqueeze(0).unsqueeze(0)/9
# print(conv_kernel4-conv_kernel5)
font = FontProperties(fname='C:\Windows\Fonts\simkai.ttf', size=32) 
plt.figure(figsize=(32, 32))  
plt.subplot(2, 2, 1)
plt.title('原始图像', fontproperties=font)
plt.imshow(img)
plt.axis('off')  
plt.subplot(2, 2, 2)
plt.title('线性滤波-2', fontproperties=font)
plt.imshow(conv2d(img_tensor, conv_kernel4))
plt.axis('off')  
plt.subplot(2, 2, 3)
plt.imshow(conv2d(img_tensor, conv_kernel5))
plt.title('均值滤波器:模糊', fontproperties=font)  
plt.axis('off')  
plt.subplot(2, 2, 4)
plt.imshow(conv2d(img_tensor, conv_kernel4-conv_kernel5))
plt.title('锐化滤波器:强调局部差异', fontproperties=font)  
plt.axis('off')  
plt.show()

4. 图像去噪

4.1 添加随机噪点

python 复制代码
img = Image.open('1.jpg')  
img = img.resize((640, 640))  # 调小图像~先使原图变模糊
img_tensor = torch.tensor(np.array(img), dtype=torch.float).permute(2, 0, 1).unsqueeze(0)


noise = torch.randn_like(img_tensor)    # 与图像相同大小的随机标准正态分布噪点
noisy_img_tensor = img_tensor + noise   # 将噪点叠加到图像上
noisy_img = noisy_img_tensor.squeeze(0).permute(1, 2, 0).to(dtype=torch.uint8)
noisy_img = Image.fromarray(noisy_img.numpy())

4.2 图像去噪

python 复制代码
# conv_kernel1 = torch.tensor([[1/16, 1/8, 1/16],
#                             [1/8, 1/4, 1/8],
#                             [1/16, 1/8, 1/16]], dtype=torch.float).unsqueeze(0).unsqueeze(0)
# # 生成随机3x3高斯分布
# random_gaussian = torch.randn(3, 3).unsqueeze(0).unsqueeze(0)
# print(random_gaussian)
font = FontProperties(fname='C:\Windows\Fonts\simkai.ttf', size=32)  # 使用楷体
plt.figure(figsize=(32, 32))  
plt.subplot(1, 3, 1)
plt.title('原始图像', fontproperties=font)
plt.imshow(img)
plt.axis('off')  
plt.subplot(1, 3, 2)
plt.title('噪点图像', fontproperties=font)
plt.imshow(noisy_img)
plt.axis('off')  
plt.subplot(1, 3, 3)
plt.title('去噪图像', fontproperties=font)
plt.imshow(conv2d(noisy_img_tensor, conv_kernel1))
plt.axis('off') 
plt.show()
相关推荐
RAY_010410 分钟前
Python—数据容器
开发语言·python
June bug14 分钟前
【python基础】python和pycharm的下载与安装
开发语言·python·pycharm
im_AMBER1 小时前
python实践思路(草拟计划+方法)
开发语言·python
站大爷IP1 小时前
Python与JSON:结构化数据的存储艺术
python
通街市密人有1 小时前
PanTS: The Pancreatic Tumor Segmentation Dataset
人工智能·深度学习·计算机视觉
大菠萝学姐2 小时前
基于Spring Boot和Vue的高校图书馆座位预约系统的设计与实现
java·vue.js·spring boot·后端·python·mysql·vue
Tomorrow'sThinker2 小时前
[特殊字符] Python 批量生成词云:读取词频 Excel + 自定义背景 + Excel to.png 流程解析
python·excel
心 爱心 爱2 小时前
DAS3D: Dual-modality Anomaly Synthesis for 3D Anomaly Detection 论文精读
计算机视觉·异常检测·重建·判别器·多模态目标异常检测·三维异常检测·异常合成
PyAIExplorer3 小时前
图像处理中的霍夫变换:直线检测与圆检测
图像处理·人工智能
野指针121383 小时前
【使用Flask基于PaddleOCR3.0开发一个接口 调用时报错RuntimeError: std::exception】
python·flask