目录
作业1
编程实现
作业2
一、概念
二、探究不同卷积核的作用
三、编程实现
1、实现灰度图的边缘检测、锐化、模糊。(必做)
2、调整卷积核参数,测试并总结。(必做)
3、使用不同尺寸图片,测试并总结。(必做)
4、探索更多类型卷积核。(选做)
5、尝试彩色图片边缘检测。(选做)
总结:
卷积常用于特征提取
实验过程中注意认真体会“特征提取”,弄清楚为什么卷积能够提取特征。
1. 图1使用卷积核,输出特征图
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图片
def create_pic():
picture = torch.Tensor([[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]])
return picture
#确定卷积网络
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#确定卷积层
kernel = torch.tensor([-1.0,1.0])
#更改卷积层的形状适应卷积函数
kshape = (1,1,1,2)
#生成模型
model = MyNet(kernel=kernel,kshape=kshape)
#生成图片
picture = create_pic()
#更改图片的形状适应卷积层
picture = torch.reshape(picture,(1,1,5,6))
output = model(picture)
output = torch.reshape(output,(5,5))
plt.imshow(output,cmap='gray')
plt.show()
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图片
def create_pic():
picture = torch.Tensor([[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]])
return picture
#确定卷积网络
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#确定卷积层
kernel = torch.tensor([-1.0,1.0])
#更改卷积和的形状为转置
kshape = (1,1,2,1)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,5,6))
output = model(picture)
output = torch.reshape(output,(6,4))
plt.imshow(output,cmap='gray')
plt.show()
3. 图2使用卷积核,输出特征图
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图像
def create_pic():
picture = torch.Tensor([[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]])
return picture
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#确定卷积核
kernel = torch.tensor([-1.0,1.0])
kshape = (1,1,1,2)
#生成模型
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,6,6))
print(picture)
output = model(picture)
output = torch.reshape(output,(6,5))
print(output)
plt.imshow(output,cmap='gray')
plt.show()
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图像
def create_pic():
picture = torch.Tensor([[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]])
return picture
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#确定卷积核
kernel = torch.tensor([-1.0,1.0])
kshape = (1,1,2,1)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,6,6))
print(picture)
output = model(picture)
output = torch.reshape(output,(5,6))
print(output)
plt.imshow(output,cmap='gray')
plt.show()
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图像
def create_pic():
picture = torch.Tensor(
[[255,255,255,255,255,255,255,255,255],
[255,0 ,255,255,255,255,255,0 ,255],
[255,255,0 ,255,255,255,0 ,255,255],
[255,255,255,0 ,255,0 ,255,255,255],
[255,255,255,255,0 ,255,255,255,255],
[255,255,255,0 ,255,0 ,255,255,255],
[255,255,0 ,255,255,255,0 ,255,255],
[255,0 ,255,255,255,255,255,0 ,255],
[255,255,255,255,255,255,255,255,255],])
return picture
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#生成卷积核
kernel = torch.tensor([-1.0,1.0])
#更改卷积核的形状适应卷积函数
kshape = (1,1,1,2)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,9,9))
print(picture)
output = model(picture)
output = torch.reshape(output,(9,8))
print(output)
plt.imshow(output,cmap='gray')
plt.show()
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图像
def create_pic():
picture = torch.Tensor(
[[255,255,255,255,255,255,255,255,255],
[255,0 ,255,255,255,255,255,0 ,255],
[255,255,0 ,255,255,255,0 ,255,255],
[255,255,255,0 ,255,0 ,255,255,255],
[255,255,255,255,0 ,255,255,255,255],
[255,255,255,0 ,255,0 ,255,255,255],
[255,255,0 ,255,255,255,0 ,255,255],
[255,0 ,255,255,255,255,255,0 ,255],
[255,255,255,255,255,255,255,255,255],])
return picture
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#生成卷积核
kernel = torch.tensor([-1.0,1.0])
kshape = (1,1,2,1)
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,9,9))
print(picture)
output = model(picture)
output = torch.reshape(output,(8,9))
print(output)
plt.imshow(output,cmap='gray')
plt.show()
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F
import numpy as np
#生成图像
def create_pic():
picture = torch.Tensor(
[[255,255,255,255,255,255,255,255,255],
[255,0 ,255,255,255,255,255,0 ,255],
[255,255,0 ,255,255,255,0 ,255,255],
[255,255,255,0 ,255,0 ,255,255,255],
[255,255,255,255,0 ,255,255,255,255],
[255,255,255,0 ,255,0 ,255,255,255],
[255,255,0 ,255,255,255,0 ,255,255],
[255,0 ,255,255,255,255,255,0 ,255],
[255,255,255,255,255,255,255,255,255],])
return picture
class MyNet(torch.nn.Module):
def __init__(self,kernel,kshape):
super(MyNet, self).__init__()
kernel = torch.reshape(kernel,kshape)
self.weight = torch.nn.Parameter(data=kernel, requires_grad=False)
def forward(self, picture):
picture = F.conv2d(picture,self.weight,stride=1,padding=0)
return picture
#确定卷积核
kernel = torch.tensor([[1.0,-1.0],
[-1.0,1.0]])
#更改卷积核的大小适配卷积函数
kshape = (1,1,2,2)
#生成网络模型
model = MyNet(kernel=kernel,kshape=kshape)
picture = create_pic()
picture = torch.reshape(picture,(1,1,9,9))
print(picture)
output = model(picture)
output = torch.reshape(output,(8,8))
print(output)
plt.imshow(output,cmap='gray')
plt.show()
用自己的语言描述“卷积、卷积核、特征图、特征选择、步长、填充、感受野”。
数值不同:
利用该网址进行探究 Image Kernels explained visually (setosa.io)
模糊
浮雕效果
锐化
底部轮廓检测
边缘检测
大小不同:卷积核的大小一般有1x1,3x3和5x5的尺寸(一般是奇数x奇数)
小卷积核优势:
一:整合了一个以上个非线性激活层,代替单一非线性激活层,增加了非线性的拟合能力。
二:减少了网络参数。以3个3*3的级联卷积代替1个7*7的卷积为例:可以减少7*7-3*3*\3=22个参数,减少了45%的参数。以2个3*3的级联卷积代替1个5*5的卷积为例:可以减少5*5-2*3*3=7个参数,减少了28%的参数。
三:减少了计算量。以3个3*3的级联卷积代替1个7*7的卷积为例:可以减少7*7*L-3*3*3*L=22*L次计算,减少了45%的计算量。以2个3*3的级联卷积代替1个5*5的卷积为例:可以减少5*5*L-2*3*3*L=7*L次计算,减少了28%的计算量。
四:有感于1*1卷积核中还可以起到对通道数的升降进行控制的作用 (达到特征降维和升维的作用)。多个小卷积核的串联是否也可以在网络结构搜索中,给通道数设置增加更多的灵活性。
基于以上几个理解所以,一般都用3作为卷积核大小。
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 = '111.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()
边缘检测
锐化
模糊
修改步长stride=10
步长增加,提取的特征和之前相比不全面。有可能错失一些有用的特征。使图像变得模糊但但计算量会减小
加入padding=5
加入padding后图像提取的特征会更全面 但同时可能造成计算量增大
上图尺寸为
1056 1080
(1064, 1088)
修改图片为
1280 727
(1278, 725)
边缘检测
锐化
模糊
stride=10
padding=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('333.jpg').convert('L') # 读入一张灰度图的图片
im = np.array(im, dtype='float32') # 将其转换为一个矩阵
#print(im.shape[0],im.shape[1]) 448*448
# 可视化图片
plt.imshow(im.astype('uint8'), cmap='gray')
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
conv1 = nn.Conv2d(in_channels=1,out_channels=1, kernel_size=3, bias=False,stride=1,padding=1) # 定义卷积
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()
这次实验对图像进行卷积操作对图像特征进行提取,了解体会了不同的卷积核对图像的影响和作用,实验过程中通过调整卷积核参数进行实验研究,不同的图片不同的操作变化有的不明显有的效果很好,通过本次实验使我对卷积核的理解更加深刻,
ref:
如何通俗易懂地解释卷积? - 马同学的回答 - 知乎 https://www.zhihu.com/question/22298352/answer/228543288
https://blog.csdn.net/program_developer/article/details/80958716
https://blog.csdn.net/qq_41554005/article/details/107369139
https://blog.csdn.net/mrliuzhao/article/details/106011640