NNDL 作业5:卷积

目录

作业1

编程实现

作业2

一、概念

二、探究不同卷积核的作用

三、编程实现

1、实现灰度图的边缘检测、锐化、模糊。(必做)

2、调整卷积核参数,测试并总结。(必做)

3、使用不同尺寸图片,测试并总结。(必做)

4、探索更多类型卷积核。(选做)

5、尝试彩色图片边缘检测。(选做)

总结

参考代码 


作业1

编程实现

91fdec5f7c7d404097724bc53403db9b.png

卷积神经网络工作原理的直观理解_superdont的博客-CSDN博客

1. 图1使用卷积核gif.latex?%5Cbegin%7Bpmatrix%7D%201%20%26%20-1%20%5Cend%7Bpmatrix%7D,输出特征图 

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
#图1
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')  # 将其转换为一个矩阵

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]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 1, 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()

fc48966819f340ddb1c8d1db99821438.png

卷积后:

794e2668c291490dad904b6b2dfbc271.png

2. 图1使用卷积核gif.latex?%5Cbegin%7Bpmatrix%7D%201%5C%5C%20-1%5C%5C%20%5Cend%7Bpmatrix%7D,输出特征图

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))  # 适配卷积的输入输出

cfd613b11b4148a6a49972feecf2863b.png

3. 图2使用卷积核gif.latex?%5Cbegin%7Bpmatrix%7D%201%20%26%20-1%20%5Cend%7Bpmatrix%7D,输出特征图

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592

#图2
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]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 1, 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()

cfd9ff2b1f9e47788775d73038e68208.png

卷积后:

80ff4df87e3c41ca807f179120397bb7.png

4. 图2使用卷积核gif.latex?%5Cbegin%7Bpmatrix%7D%201%5C%5C%20-1%5C%5C%20%5Cend%7Bpmatrix%7D,输出特征图 

4478fb169c494a3da1e6b26d3d9da454.png

5. 图3使用卷积核gif.latex?%5Cbegin%7Bpmatrix%7D%201%20%26%20-1%20%5Cend%7Bpmatrix%7Dgif.latex?%5Cbegin%7Bpmatrix%7D%201%5C%5C%20-1%5C%5C%20%5Cend%7Bpmatrix%7Dgif.latex?%5Cbegin%7Bpmatrix%7D%201%20%26-1%20%5C%5C%20-1%261%20%5Cend%7Bpmatrix%7D ,输出特征图 

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592

#图3
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, 255, 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')  # 将其转换为一个矩阵

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]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 1, 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()

172d625574bb42b0834fcff64efb4f9e.png

6ca6c5365fe74492a872c6d1ffe4373c.png 

e4f44bf2d8594c7fa7f10d21058c676f.png

5d38453d625a4f4bbb3bd73e8c4b8b2b.png

 

作业2

一、概念

卷积:

将图像矩阵中,从左到右,由上到下,取与滤波器同等大小的一部分,每一部分中的值与滤波器中的值对应相乘后求和,最后的结果组成一个矩阵,其中没有对核进行翻转。

卷积核:

卷积核就是图像处理时,给定输入图像,输入图像中一个小区域中像素加权平均后成为输出图像中的每个对应像素,其中权值由一个函数定义,这个函数称为卷积核。卷积神经网络中"卷积”,是为了提取图像的特征。

特征图:

每层卷积结束后得到的卷积值的组合就是特征图。

特征选择:

就是用来对原图像选择不同的卷积核进行特征提取的过程。

步长:

在进行卷积时,卷积核(滤波器)每次移动的像素单位。

填充:

在进行卷积操作前,对原矩阵进行边界填充,也就是在矩阵的边界上填充一些值,以增加矩阵的大小,通常都用“0”来进行填充的。

通过填充的方法,当卷积核扫描输入数据时,它能延伸到边缘以外的伪像素,从而使输出和输入size相同。

感受野:

卷积神经网络每一层输出的特征图(feature map)上的像素点在原始图像上映射的区域大小。指的是神经网络中神经元“看到的”输入区域。

二、探究不同卷积核的作用

参考:Image Kernels explained visually (setosa.io)

34d6f00c890649bc9017f1459ae59270.png

锐化:

锐化实际上就是计算当前点和周围点的差别,然后将这个差别加到原来的位置上

如果核的中心值是负数,就是在强调边缘,在锐化边缘

format,png

边缘检测:

931848d0564a46bda0252c80899626fb.png

979f33c5a4d5437d9f3acd43ec98ae0d.png

浮雕:

浮雕滤波器可以给图像一种3D阴影的效果。

只要将中心一边的像素减去另一边的像素就可以了。这时候,像素值有可能是负数,我们将负数当成阴影,将正数当成光,然后我们对结果图像加上128的偏移。这时候,图像大部分就变成灰色了。

45度的浮雕滤波器

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h4eGp4dw==,size_16,color_FFFFFF,t_70

三、编程实现

1、实现灰度图边缘检测、锐化、模糊。(必做)

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
file_path = '皮卡丘1.jpg'
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()

e0c692d936d749acabbc7bd54532e468.png

边缘检测:

035569caf52c42168dcb4c2c887ea4bb.png

锐化:

2143445f613746bc8333ff5de44029d3.png

模糊:

e8e15c7160864049a21512fcf4a9da76.png

2、调整卷积核参数,测试并总结。(必做)

以锐化为例:

57941fe1154841628f0dc6c2bbe82d32.png

当步长为1时:

4ec081587889494c88fec8025769492d.png

当步长为5时:

106d0f53f1d84e36b9642f1a6de528d1.png

当步长为10时:

28c39ccc4f5b48debbcced61e86edf3b.png

当步长为20时:

15cd57f57eed462f8045d0ce776c6517.png

步长越长,图像越模糊,图像的特征越不明显,可能有损失。 

3、使用不同尺寸图片,测试并总结。(必做)

793ae5986e004d73b929f75fc02430d1.png

边缘检测:

dc30178972b84af2832db2d66a877c7c.png

锐化:

b15b48e5391b40de884a1de9f8d8a88d.png

模糊:

a2385779b02a48c78cb2fc036820260e.png

对不同的图片,卷积的效果也有差异,该题中图片的边缘检测效果很清晰,不如前面的图片效果。模糊卷积后的效果也不是很好,模糊的效果不明显。

4、探索更多类型卷积核。(选做)

# 浮雕卷积核
sobel_kernel = np.array([[-2, -1, 0],
                         [-1, 1, -1],
                         [0, 1, 2]], dtype='float32')  # 定义轮廓检测算子

4f2d99f1c03941fba01f3f29c68a837b.png

# bottom sobel卷积核
sobel_kernel = np.array([[-1, -2, -1],
                         [0, 0, 0],
                         [1, 2, 1]], dtype='float32')  # 定义轮廓检测算子

acc5d4aa33484884a95e1ccbddd5d9d2.png

5、尝试彩色图片边缘检测。(选做)

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
from PIL import Image
import matplotlib.pyplot as plt

im = Image.open('皮卡丘1.jpg').convert('L') # 读入一张灰度图的图片
im = np.array(im, dtype='float32') # 将其转换为一个矩阵

plt.imshow(im.astype('uint8'), cmap='gray')
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))

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

edge1 = conv1(Variable(im)) # 作用在图片上
edge1 = edge1.data.squeeze().numpy() # 将输出转换为图片的格式
plt.imshow(edge1, cmap='gray')

plt.show()

bf8afb55fe1f4daaa6e986a7e3b437c6.jpeg58029ade1e7f46d88cd7b81ad0e7f99c.png

总结

本次作业的心得体会,重点谈谈卷积能够提取特征的原理。

卷积神经网络CNN实际上是通过带有label的训练数据来train由一个个特征判断系统中的运算法则,对于图像特征提取而言,系统的运算法则可能比较复杂,通过卷积的方式将复杂判断系统的运算法则变为一个个易于计算的卷积核,从而更方便地提取图像特征,完成对图像的分析与处理。

这次作业学习实践了对图像进行卷积的操作,特别是对图像特征的提取,了解体会了不同的卷积核对图像的影响和作用。这次作业是卷积神经网络学习的开始,加油!

参考代码 

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as plt
 
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
file_path = 'deer.jpg'
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 = 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()

参考:

http://t.csdn.cn/GQ5ip

http://t.csdn.cn/XWzAt

http://t.csdn.cn/9PEyf

http://t.csdn.cn/mxZBv

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值