NNDL 作业五:卷积

目录

作业一

作业二

概念

探究不同卷积核的作用

编程实现

总结

参考


作业一

编程实现以下要求:

 

1. 图1使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix},输出特征图

2. 图1使用卷积核\begin{pmatrix} 1\\ -1\\ \end{pmatrix},输出特征图

3. 图2使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix},输出特征图

4. 图2使用卷积核\begin{pmatrix} 1\\ -1\\ \end{pmatrix},输出特征图 

5. 图3使用卷积核\begin{pmatrix} 1 & -1 \end{pmatrix}\begin{pmatrix} 1\\ -1\\ \end{pmatrix}\begin{pmatrix} 1 &-1 \\ -1&1 \end{pmatrix} ,输出特征图 

代码实现:

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
import os
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# im = Image.open(file_path).convert('L')  # 读入一张灰度图的图片
'''
im = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
               [0, 255, 0, 0, 0, 0, 0, 255, 0],
               [0, 0, 255, 0, 0, 0, 255, 0, 0],
               [0, 0, 0, 255, 0, 255, 0, 0, 0],
               [0, 0, 0, 0, 255, 0, 0, 0, 0],
               [0, 0, 0, 255, 0, 255, 0, 0, 0],
               [0, 0, 55, 0, 0, 0, 255, 0, 0],
               [0, 255, 0, 0, 0, 0, 0, 255, 0],
               [0, 0, 0, 0, 0, 0, 0, 0, 0],
               ], dtype='float32')  # 将其转换为一个矩阵
               '''
'''
im = np.array([[0,0,0,255,255,255],
               [0,0,0,255,255,255],
               [0,0,0,255,255,255],
               [0,0,0,255,255,255],
               [0,0,0,255,255,255],
               [0,0,0,255,255,255],
               [0,0,0,255,255,255]], dtype='float32')  # 将其转换为一个矩阵
'''
im = np.array([[0, 0, 0, 255, 255, 255],
               [0, 0, 0, 255, 255, 255],
               [0, 0, 0, 255, 255, 255],
               [255, 255, 255, 0, 0, 0],
               [255, 255, 255, 0, 0, 0],
               [255, 255, 255, 0, 0, 0]], dtype='float32')  # 将其转换为一个矩阵
print(im.shape[0], im.shape[1])
plt.imshow(im.astype('uint8'), cmap='gray')  # 可视化图片
plt.title('原图')
plt.show()

im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
conv1 = nn.Conv2d(1, 1, (1, 2), bias=False)  # 定义卷积

sobel_kernel = np.array([[1, -1],
                        [-1, 1]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 2, 2))  # 适配卷积的输入输出
conv1.weight.data = torch.from_numpy(sobel_kernel)  # 给卷积的 kernel 赋值

edge1 = conv1(Variable(im))  # 作用在图片上

x = edge1.data.squeeze().numpy()
print(x.shape)  # 输出大小

plt.imshow(x, cmap='gray')
plt.show()

1.修改卷积核,检测算子以及卷积输入输出格式

sobel_kernel = np.array([[1, -1]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 1, 2))  # 适配卷积的输入输出
conv1 = nn.Conv2d(1, 1, (1, 2), bias=False)  # 定义卷积

原图:

进行第一轮卷积后的特征图: 

 

 2.修改卷积核:

sobel_kernel = sobel_kernel.reshape((1, 1, 1, 2))  # 适配卷积的输入输出

 3.修改相应位置后的特征图

 4.

 5.其中前两个卷积核依旧是一维,所以和前4题没什么变化,第三个卷积核是二维,需要修改:

sobel_kernel = sobel_kernel.reshape((1, 1, 2, 2))

特征图像分别为:

 

 

作业二

概念

用自己的语言描述卷积,卷积核,特征图,特征选择,步长,填充,感受野。

卷积:首先卷积是一种数学运算,是两个变量在某个范围内相乘求和的结果,卷积一词可以分开来解释,卷就是函数之间的翻转和滑动,积就是指积分/加权求和。

卷积核:卷积核就是图像处理时,给定输入图像,输入图像中一个小区域中像素加权平均后成为输出图像中的每个对应像素,其中权值由一个函数定义,这个函数称为卷积核。

特征图:在每个卷积层,数据都是以三维形式存在的。你可以把它看成许多个二维图片叠在一起,其中每一个称为一个特征图。在输入层,如果是灰度图片,那就只有一个特征图;如果是彩色图片,一般就是3个特征图(红绿蓝)。层与层之间会有若干个卷积核,上一层和每个特征图跟每个卷积核做卷积,都会产生下一层的一个特征图。

特征选择:从已有的M个特征中选择N个特征使得系统的特定指标最优化,是从原始特征中选择出一些最有效特征以降低数据集维度的过程,是提高学习算法性能的一个重要手段,也是模式识别中关键的数据预处理步骤。

步长:卷积核进行一次卷积后,横向移动的步长和纵向移动的步长。

填充:填充卷积过程中所缺失的部分,如线性化边缘的填充,从而使得其可以进行特征提取等操作

感受野:卷积神经网络每一层输出的特征图上的像素点在输入图片上映射的区域大小,即特征图上的一个点对应输入图上的区域。

探究不同卷积核的作用

首先可以参考此网站:Image Kernels explained visually (setosa.io)

图像内核是一个小矩阵,用于应用在Photoshop或Gimp中可能找到的效果,例如模糊,锐化,勾勒轮廓或浮雕。它们还用于机器学习中的“特征提取”,这是一种确定图像中最重要的部分的技术。在这种情况下,该过程通常被称为“卷积”.

不同卷积核对于图像卷积的影响如下

缩进内核使映像保留不变:

 模糊核不再强调相邻像素值的差异。

 锐化内核强调相邻像素值的差异。这使得图像看起来更生动清晰

 sobel 核用于显示特定方向上相邻像素值的差异

轮廓核(也称为“边缘”核)用于突出显示像素值的巨大差异。

浮雕核(类似于sobel核,有时被称为相同的意思)通过强调给定方向上像素的差异来产生深度的错觉。

大小卷积核的差异:

大卷积核:感受野大,可以审视更为宽广区域的特征图,所获得的全局特征越好;

小卷积核:语义表达强,计算量也会变少,参数量变少,梯度消失的问题得到优化;

现在多用几个小卷积核去取代一个大卷积核,优点很多,比如深度增加带来的非线性激活函数多了,语义表达强了,计算量也会变少,参数量也同样变少,梯度消失的问题因为BN等技术出现得到了很好的优化。

编程实现

  1. 实现灰度图的边缘检测、锐化、模糊。(必做)
  2. 调整卷积核参数,测试并总结。(必做)
  3. 使用不同尺寸图片,测试并总结。(必做)
  4. 探索更多类型卷积核。(选做)
  5. 尝试彩色图片边缘检测。(选做)

代码实现:

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
import os
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
file_path = '123.png'
im = Image.open(file_path).convert('L')  # 读入一张灰度图的图片
im = np.array(im, dtype='float32')  # 将其转换为一个矩阵
print(im.shape[0], im.shape[1])
plt.imshow(im.astype('uint8'), cmap='gray')  # 可视化图片
plt.title('原图')
plt.show()

im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
conv1 = nn.Conv2d(1, 1, 3, bias=False)  # 定义卷积
'''
# 边缘检测
sobel_kernel = np.array([[-1, -1, -1],
                         [-1, 8, -1],
                         [-1, -1, -1]], dtype='float32')  # 定义轮廓检测算子
                         '''

# 锐化
sobel_kernel = np.array([[0, -1, 0],
                         [-1, 5, -1],
                         [0, -1, 0]], dtype='float32')  # 定义轮廓检测算子
                         
'''
# 模糊
sobel_kernel = np.array([[0.0625, 0.125, 0.0625],
                         [0.125, 0.25, 0.125],
                         [0.0625, 0.125, 0.0625]], dtype='float32')  # 定义轮廓检测算子
                         '''
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出
conv1.weight.data = torch.from_numpy(sobel_kernel)  # 给卷积的 kernel 赋值

edge1 = conv1(Variable(im))  # 作用在图片上

x = edge1.data.squeeze().numpy()
print(x.shape)  # 输出大小

plt.imshow(x, cmap='gray')
plt.show()

1.通过修改不同的算子(矩阵)以达到不同的卷积效果。

原图:

边缘检测:

锐化:

模糊:

 2.

stride=1 表示步长为1,即每次矩阵移动一个列再构成一个矩阵,padding 是对边缘进行填充,padding=1表示填充一行一列,等于2 表示填充两行两列;
groups表示的是分组卷积,分组卷积是可以减少计算量;
dilation:是对核矩阵进行填充,如果原始的核大小是33的且dilation=2 则核大小就变成了77的了;
bias是偏置项;

改变卷积核中的参数,语句conv1 = nn.Conv2d(1, 1, 3, bias=False)中有许多默认参数,例如步长stride,padding,groups等,现将步长进行不同赋值:

当stride=1时,即是原图。当stride=3时:

 当设置stride=10时:

 变得比较模糊,这是因为步长为矩阵每次移动步长个列再构成一个矩阵,当步长较大时就会掠过一部分列,从而缺失,而导致图像变模糊。

3.使用不同尺度图片测试

上面实验中所使用的图像大小为630,503.

630 503
(63, 51)

下面改变实验图片

 所修改图像大小为301,812

301 812
(299, 810)

锐化:

 边缘检测:

总结:通过对比可以发现,对于不同的图片,使用相同的锐化,边缘检测等卷积处理,当图像较大时,所处理出的图像较为清晰,效果好于小图片,对于现实拍摄图片手绘图片所呈现的结果也有不同。

4.探索更多类型卷积核

只需要将上述程序中的卷积核矩阵部分进行改变,观察结果

浮雕核:

 5.尝试彩色图片边缘检测

基于我们所学习的另外一门课程,数字图像处理,对于彩色图片的边缘检测等操作,我们可以先将彩色图片转为灰度图片,然后再进行灰度图片的边缘检测操作。

 代码实现

import cv2
 
image = cv2.imread('./images/sunflower.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imwrite('./images/gray_sunflower.jpg', image)

边缘检测

锐化 

 

总结

通过本次完成作业的过程,学到的东西并不比一次实验学到的少,首先是加深学习了卷积的一系列知识点,对于卷积的操作过程更加娴熟,卷积核具有很多类型,不同的卷积核所形成的效果不同,所卷积图片的尺寸大小也会影响最终结果,不同的步长等卷积核参数等等都会有影响。

参考

卷积神经网络nn.Conv2d函数

彩色图转为灰度图python

NNDL 作业5:卷积_HBU_David的博客-CSDN博客

AI Studio,博客园

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值