目录
作业一
编程实现
-
图1使用卷积核 ( 1 − 1 ) \begin{pmatrix} 1 & -1 \end{pmatrix} (1−1),输出特征图
-
图1使用卷积核 ( 1 − 1 ) \begin{pmatrix} 1\\ -1\\ \end{pmatrix} (1−1),输出特征图
-
图2使用卷积核 ( 1 − 1 ) \begin{pmatrix} 1 & -1 \end{pmatrix} (1−1),输出特征图
-
图2使用卷积核 ( 1 − 1 ) \begin{pmatrix} 1\\ -1\\ \end{pmatrix} (1−1),输出特征图
-
图3使用卷积核 ( 1 − 1 ) , ( 1 − 1 ) , ( 1 − 1 − 1 1 ) \begin{pmatrix} 1 & -1 \end{pmatrix},\begin{pmatrix} 1\\ -1\\ \end{pmatrix},\begin{pmatrix} 1 &-1 \\ -1&1 \end{pmatrix} (1−1),(1−1),(1−1−11),输出特征图
输出一下图:
import numpy as np
import matplotlib.pyplot as plt
# 需要处理的图
Tu1 = np.array([[0,0,0,0,0,0,0,255,255,255,255,255,255,255] for i in range(7)])
Tu21 = np.array([[0,0,0,0,0,0,0,255,255,255,255,255,255,255] for i in range(7)])
Tu22 = np.array([[255,255,255,255,255,255,255,0,0,0,0,0,0,0] for i in range(7)])
Tu2 = np.vstack([Tu21,Tu22])
Tu3 = 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]])
# 展示图像
plt.subplot(131)
plt.imshow(Tu1,cmap="gray")
plt.title("One")
plt.subplot(132)
plt.imshow(Tu2,cmap="gray")
plt.title("Two")
plt.subplot(133)
plt.imshow(Tu3,cmap="gray")
plt.title("Three")
plt.show()
运行结果:
设置一下卷积核:
# 卷积核
JJH1 = np.array([1,-1]).reshape([1,2])
JJH2 = np.array([1,-1]).reshape([2,1])
JJH3 = np.array([[1,-1],[-1,1]])
JJH = np.array([JJH1,JJH2,JJH3])
写一下计算卷积的公式代码:
def JuanJi(JuanJiHe,Tu,Bu=1):
He_1,He_2 = JuanJiHe.shape
Tu_1,Tu_2 = Tu.shape
Jieguo = []
for i in range(int(Tu_1-He_1+1)): # 列
chuan = []
for j in range(int(Tu_2-He_2+1)): # 行
# print("i:{},j:{}".format(i,j))
Z = Tu[i:i+He_1,j:j+He_2]
# print(Z*JuanJiHe)
# print(np.sum(Z*JuanJiHe))
chuan.append(np.sum(Z*JuanJiHe))
Jieguo.append(chuan)
# print(Jieguo)
return np.array(Jieguo)
利用写的卷积方法输出一下结果:
# 保存答案
answer1 = []
answer2 = []
answer3 = []
for i in range(len(JJH)-1):
J = JuanJi(JJH[i],Tu1)
answer1.append(J)
for i in range(len(JJH)-1):
J = JuanJi(JJH[i],Tu2)
answer2.append(J)
for i in range(len(JJH)):
J = JuanJi(JJH[i],Tu3)
answer3.append(J)
把结果展示一下:
# 输出图片
for i in range(2):
plt.subplot(121+i)
plt.imshow(answer1[i],cmap="gray")
plt.show()
plt.figure()
for i in range(2):
plt.subplot(121+i)
plt.imshow(answer2[i],cmap="gray")
plt.show()
plt.figure()
for i in range(3):
plt.subplot(131+i)
plt.imshow(answer3[i],cmap="gray")
plt.show()
运行结果:
1-2题的答案:
3-4题的答案:
5题的答案:
作业二
一、概念
用自己的语言描述“卷积、卷积核、特征图、特征选择、步长、填充、感受野”。
- 卷积:指在滑动中提取特征的过程,可以形象地理解为用放大镜把每步都放大并且拍下来,再把拍下来的图片拼接成一个新的大图片的过程。
- 卷积核:图像处理时,给定输入图像,输入图像中一个小区域中像素加权平均后成为输出图像中的每个对应像素,其中权值由一个函数定义,这个函数称为卷积核。在我看来,特征就相当于是化学混合剂,而卷积核相当于是加入的提取物质,不同的卷积核提取不同的化学物质。
- 特征图:相当于提取的化学物质,也就是我们经过卷积后的结果
- 步长:成倍缩小尺寸。
- 填充:经过卷积后,会丢失边缘点或者你的输出图像会变得很小。所以我们习惯上,用0填充,来不使卷积后的图片变小。
- 感受野:是卷积神经网络每一层输出的特征图(feature map)上的像素点在输入图片上映射的区域大小。再通俗点的解释是,特征图上的一个点对应输入图上的区域。
二、探究不同卷积核的作用
1. 边缘检测:检测识别出图像图像中亮度变化剧烈的像素点构成的集合。
相关的卷积核有:
Sobel
(
1
0
−
1
2
0
−
2
1
0
−
1
)
\left( \begin{matrix} 1 & 0 & -1 \\ 2 & 0 & -2\\ 1 & 0 & -1 \end{matrix} \right)
⎝
⎛121000−1−2−1⎠
⎞Roberts
(
0
0
0
1
1
0
0
0
0
)
\left( \begin{matrix} 0 & 0 & 0 \\ 1 & 1 & 0\\ 0 & 0 & 0 \end{matrix} \right)
⎝
⎛010010000⎠
⎞Prewitt
(
1
0
−
1
1
0
−
1
1
0
−
1
)
\left( \begin{matrix} 1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1 \end{matrix} \right)
⎝
⎛111000−1−1−1⎠
⎞Compass
(
1
0
−
1
1
0
−
1
1
0
−
1
)
\left( \begin{matrix} 1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1 \end{matrix} \right)
⎝
⎛111000−1−1−1⎠
⎞等等。
2. 模糊
图像的模糊是图像处理中比较常用和简单的处理手段之一。不同类型的模糊背后其实对应的卷积核也不同,根据原理的不同,模糊的方式也有很多种,比如:均值模糊函数blur()、中值模糊函数medianBlur()、高斯平滑函数GaussianBlur()、双边滤波函数bilateralFilter()。
相应的卷积核有:
1
9
(
1
1
1
1
1
1
1
1
1
)
{1 \over 9} \left( \begin{matrix} 1 & 1 & 1\\ 1 & 1 & 1\\ 1 & 1 & 1 \end{matrix} \right)
91⎝
⎛111111111⎠
⎞等
3. 锐化
将原图像和拉普拉斯图像叠加到一起,便可以得到锐化图像。
卷积核有:
(
0
−
1
0
1
5
1
0
1
0
)
\left( \begin{matrix} 0 & -1 & 0 \\ 1 & 5 & 1\\ 0 & 1 & 0 \end{matrix} \right)
⎝
⎛010−151010⎠
⎞
三、编程实现
实现灰度图的边缘检测、锐化、模糊。
边缘检测:
代码:
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
# 求卷积的式子
def JuanJi(JuanJiHe,Tu):
He_1,He_2 = JuanJiHe.shape
Tu_1,Tu_2 = Tu.shape
Jieguo = []
for i in range(int(Tu_1-He_1+1)): # 列
chuan = []
for j in range(int(Tu_2-He_2+1)): # 行
Z = Tu[i:i+He_1,j:j+He_2]
chuan.append(np.sum(Z*JuanJiHe))
Jieguo.append(chuan)
return np.array(Jieguo)
# 先导入图片
img = Image.open("atm.jpg")
img = np.array(img.convert('L'))
plt.imshow(img,cmap="gray")
plt.title("原图")
plt.figure()
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
运行结果:
原图:
模糊:
# 这个图有点大,用一个大一点的卷积核,这个是均值模糊
JJH = np.array([ [1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400,1/400] for i in range(20)])
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
运行结果:
锐化:
JJH = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]]) # 锐化
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
运行结果:
调整卷积核参数,测试并总结。
- 将边缘检测的卷积核改为[[-1,-1, -1],[-1, 12, -1],[-1, -1,-1]]
JJH = np.array([[-1,-1, -1],[-1, 12, -1],[-1, -1,-1]])
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
运行结果:
这里我们发现,更换了一个卷积核以后,边缘检测比之前清晰很多。
2. 锐化的卷积核改为[[0,5, 0],[5, 5, 5],[0, 5,0]]
JJH = np.array([[0,5, 0],[5, 5, 5],[0, 5,0]])
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
3. 模糊的卷积核改为1/9[[1,1,1],[1,1,1],[1,1,1]]
JJH = np.array([[1/9,1/9,1/9],[1/9,1/9,1/9],[1/9,1/9,1/9]],dtype = 'float32'))
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
运行结果:
改了以后,我们发现,模糊程度不如之前的好
使用不同尺寸图片,测试并总结。
更换一个图片
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def JuanJi(JuanJiHe,Tu,Bu=1):
He_1,He_2 = JuanJiHe.shape
Tu_1,Tu_2 = Tu.shape
Jieguo = []
for i in range(int(Tu_1-He_1+1)): # 列
chuan = []
for j in range(int(Tu_2-He_2+1)): # 行
Z = Tu[i:i+He_1,j:j+He_2]
chuan.append(np.sum(Z*JuanJiHe))
Jieguo.append(chuan)
return np.array(Jieguo)
img = Image.open("abc.jpg")
img = np.array(img.convert('L'))
JJH1 = np.array([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]]) # 边缘检测
JJH2 = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]]) # 锐化
JJH3 = np.array([[1/9,1/9,1/9],[1/9,1/9,1/9],[1/9,1/9,1/9]],dtype = 'float32') # 模糊
JJH = np.array([JJH1,JJH2,JJH3])
img = Image.open("abc.jpg")
img = np.array(img.convert('L'))
answer = []
for i in range(3):
answer.append(JuanJi(JJH[i],img))
plt.imshow(img,cmap="gray")
plt.title("原图")
plt.figure()
for i in range(3):
plt.subplot(131+i)
plt.imshow(answer[i],cmap="gray")
plt.show()
运行结果:
下图中的图片依次是:边缘检测,锐化,模糊
探索更多类型卷积核。
高斯卷积核:
(
1
/
16
2
/
16
1
/
16
2
/
16
4
/
16
2
/
16
1
/
16
2
/
16
1
/
16
)
\left( \begin{matrix} {1/16} & {2/16} & {1/16}\\ {2/16} & {4/16} & {2/16}\\ {1/16}& {2/16} & {1/16} \end{matrix} \right)
⎝
⎛1/162/161/162/164/162/161/162/161/16⎠
⎞代码:
JJH = np.array([[1/16,2/16,1/16],[2/16,4/16,2/16],[1/16,2/16,1/16]],dtype = 'float32'))
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
锐化卷积核: ( − 1 − 1 − 1 − 1 9 − 1 − 1 − 1 − 1 ) \left( \begin{matrix} -1& -1 & -1 \\ -1 & 9 & -1\\ -1 & -1 & -1 \end{matrix} \right) ⎝ ⎛−1−1−1−19−1−1−1−1⎠ ⎞
JJH = np.array([[-1,-1,-1],[-1,9,-1],[-1,-1,-1]],dtype = 'float32')
answer = JuanJi(JJH,img)
plt.imshow(answer,cmap="gray")
plt.show()
运行结果:
尝试彩色图片边缘检测。
代码:
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('abc.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()
总结
这次作业对卷积学习有了更深的理解,做到后面的实验的的时候,发现原来有自带的函数,额。。。但是我写的也没错,就不改了。不同的卷积核,不同的步长对应着不同的卷积结果。这次实验大多数时间用在了自己写那个卷积公式(似乎不用自己去写)。