[23-24 秋学期]NNDL 作业6 卷积 [HBU]

2023-11-09 19:10
文章标签 作业 卷积 23 24 学期 nndl hbu

本文主要是介绍[23-24 秋学期]NNDL 作业6 卷积 [HBU],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

 一、概念

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

后接:关于使用pycharm输出卷积图像后图片仍然不清晰的可能原因以及解决方法👆

总结:


前言:卷积常用于特征提取 

实验过程中注意认真体会“特征提取”,弄清楚为什么卷积能够提取特征。


 一、概念

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

        大致看了一遍邱锡鹏《神经网络与深度学习》的卷积一节。谈谈我对这些名词概念的理解(理解不足 描述不准请见谅)。

个人理解:

卷积: 卷积可以将图像(二维)或者信号(一维) f(.)矩阵函数,通过另一个矩阵函数g(.)的操作,进行一些数学关系上的运算而得到新的函数矩阵关系h(.)。不同的函数矩阵关系即不同的卷积关系,可以得到不同的矩阵关系h(.),也就是可以提取出不同的特征。要将图像变得平滑、模糊、锐化,或者只提取边缘、局部特征等,都需要经过不同的卷积关系来提取得到。

卷积核:卷积核又称作滤波器,卷积核是一种矩阵函数,它的大小通常小于需要被卷积的矩阵。卷积核是用来从输入数据中提取特征的。比如在处理图像时,一个卷积核可能会关注图像的某个特定部分,比如边缘或颜色变化。通过滑动这个卷积核并与其覆盖的图像部分进行运算,网络可以学习到如何识别图像中的这些特征。每个卷积核都有一些可调整的参数,这些参数是通过训练网络来学习的。这样,每个卷积核都可以根据它所处理的输入数据来调整自己,从而更好地提取特征。

特征图:特征图也叫特征映射,即卷积操作后被提取出来的特征的输出结果。它描述了网络对输入数据的特征理解。特征图是一个二维矩阵,其中每个像素位置的值表示该位置的特征强度或权重。

特征选择:特征选择是卷积过程中根据卷积核的参数(想要提取的特征)而进行的特征偏好保留的过程。通过它选择输入数据中最相关的特征,而忽略不相关或冗余的特征。

步长:卷积神经网络中的步长不同于前馈神经网络反向更新中的学习率,卷积神经网络的步长表示卷积核在输入数据上每次滑动过的距离。

填充:在一维矩阵中,填充即在输入数据的左右两端各添加额外的P个0;在二维矩阵中,填充是指在矩阵周围一圈添加0。填充零可以保护一些不想丢失的特征参数。

感受野:感受野是指卷积核可以感知到的输入数据的区域。感受野描述了卷积核对输入数据的感知范围。感受野的大小可以通过改变卷积核的大小和步长来调整。


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

https://blog.csdn.net/superdont/article/details/127124819

从左至右依次为 图1 图2 图3 .

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

代码:

import numpy as np
import torch
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号#定义卷积核w1,w2
#w1是形状为1*2的卷积核,数据类型为float32,元素为[1,-1]
#w2是形状为2*1的卷积核,元素为[1,-1]
w1 = np.array([1, -1], dtype='float32').reshape([1, 1, 1, 2])
w2 = np.array([1, -1], dtype='float32').T.reshape([1, 1, 2, 1])
print('w1为:\n',w1,'\n',type(w1),'\n','形状shape为:',w1.shape)
print('w2为:\n',w2)#将卷积核转化为Tensor类型
w1 = torch.Tensor(w1)
w2 = torch.Tensor(w2)
# print('w1为:\n',w1,'\n',type(w1),'\n','形状shape为:',w1.shape)
# print('w2为:\n',w2)
print('=========')#创建两个卷积层conv1,conv2. 分别将w1,w2参数值传入到卷积层中
conv1 = torch.nn.Conv2d(1, 1, [1, 2])
conv1.weight = torch.nn.Parameter(w1)
print('卷积层conv1为:',conv1,'\n','权重w为:',conv1.weight)conv2 = torch.nn.Conv2d(1, 1, [2, 1])
conv2.weight = torch.nn.Parameter(w2)#创建图像
#创建4*6的浮点数矩阵,其中每个元素都是1
img = np.ones([4, 6], dtype='float32')
img[:, 3:] = 255. #将矩阵的第4列-第6列所有元素设置为255白色
img[:, :3] = 0. #将矩阵的前三列(索引值为0-2)的所有元素设置为0黑色
x = img.reshape([1, 1, 4, 6])#将二维图像矩阵转化为四维张量,即批次大小(Batch size)通道数
x = torch.Tensor(x)
print('转换为Tensor后的x为:\n',x)#进行卷积操作
#detach():使用detach()确保y只是简单的成为数值,而不需要梯度计算,不希望该节点反向传播
y1 = conv1(x).detach().numpy()
y2 = conv2(x).detach().numpy()plt.subplot(131).set_title('图1原图')
plt.imshow(img, cmap='gray')#squeeze()用于从数组中移除尺寸为1的维度
plt.subplot(132).set_title('图1使用卷积核为(1,-1)结果')
plt.imshow(y1.squeeze(), cmap='gray') #以灰度图像的形式显示出来
plt.subplot(133).set_title('图1使用卷积核为(1,-1)T结果')
plt.imshow(y2.squeeze(), cmap='gray')
plt.show()

运行结果:

图1原图位于最左端,可见卷积核(1,-1)提取了边缘特征,即提取表现了黑白颜色变化最剧烈的特征(也就是边缘处);卷积核(1,-1)T则将颜色对换,黑色和白色互换。


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

将图1矩阵像素值分布改为图2矩阵的像素值分布,title名称换一下即可,其余部分的代码和第一问一样:

img = np.ones([6, 6], dtype='float32')
img[:3, 3:] = 255.
img[3:, :3] = 255
img[:3, :3] = 0.

输出结果:


3. 图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
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号#创建参数w 卷积核
w1 = np.array([1, -1], dtype='float32').reshape([1, 1, 1, 2])
w2 = np.array([1, -1], dtype='float32').T.reshape([1, 1, 2, 1])
w3 = np.array([[1, -1, -1, 1]], dtype='float32').reshape([1, 1, 2, 2])
print('w3为:\n',w3)#转换为Tensor形式
w1 = torch.Tensor(w1)
w2 = torch.Tensor(w2)
w3 = torch.Tensor(w3)#创建卷积层
conv1 = torch.nn.Conv2d(1, 1, [1, 2])
conv1.weight = torch.nn.Parameter(w1)conv2 = torch.nn.Conv2d(1, 1, [2, 1])
conv2.weight = torch.nn.Parameter(w2)conv3 = torch.nn.Conv2d(1, 1, [2, 2])
conv3.weight = torch.nn.Parameter(w3)
# 创建图像
img = np.ones([9, 9], dtype='float32')
for i in range(7):img[i + 1, i + 1] = 255.img[i + 1, 7 - i] = 255.x = img.reshape([1, 1, 9, 9])
x = torch.Tensor(x)y1 = conv1(x).detach().numpy()
y2 = conv2(x).detach().numpy()
y3 = conv3(x).detach().numpy()
plt.subplot(221).set_title('图3原图')
plt.imshow(img, cmap='gray')plt.subplot(222).set_title('卷积核为(1,-1)')
plt.imshow(y1.squeeze(), cmap='gray')
plt.subplot(223).set_title('卷积核为(1,-1)T')
plt.imshow(y2.squeeze(), cmap='gray')
plt.subplot(224).set_title('卷积核为[[1 -1],[-1 1]]')
plt.imshow(y3.squeeze(), cmap='gray')
plt.show()

运行结果:


4. 实现灰度图边缘检测、锐化、模糊

使用特定卷积核,这些都是预定义的图像处理算子,例如Sobel算子、Sharpen算子、Blur算子、Emboss算子和Outline算子。它们被广泛应用于图像处理和计算机视觉任务中。

  • Sobel算子:用于边缘检测,通过计算像素点周围像素的加权差值,得到边缘强度。
  • Sharpen算子:用于图像增强,通过增加图像边缘的对比度来增强图像的清晰度。
  • Blur算子:用于图像平滑,减少图像中的噪声和细节信息。
  • Emboss算子:用于图像突出轮廓,通过增强图像边缘的对比度来突出图像的轮廓。
  • Outline算子:用于检测边缘轮廓。
import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  #用来正常显示负号# 加载图片
file_path = 'C:\\Users\\27513\\Pictures\\Camera Roll\\cat12.jpg'
im = Image.open(file_path).convert('L') #读取图片。.convert('L')表示转换为灰度图像
im = np.array(im, dtype='float32') #将图片转换为numpy矩阵#先展示原图 cmap='gray'表示以灰度图的样式展现出来
plt.subplot(331).set_title('大橘原图')
plt.imshow(im.astype('uint8'), cmap='gray')#再将原图转换为torch张量
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))
print('转换为Tensor后的im为:\n',im,'\n','im.shape为:\n',im.shape)#定义卷积核 输入、输出通道为1,卷积核大小为3*3,并且不使用偏置项
conv1 = nn.Conv2d(1, 1, 3, bias=False)
conv2 = nn.Conv2d(1, 1, 3, bias=False)
conv3 = nn.Conv2d(1, 1, 3, bias=False)
conv4 = nn.Conv2d(1, 1, 3, bias=False)
conv5 = nn.Conv2d(1, 1, 3, bias=False)
conv6 = nn.Conv2d(1, 1, 3, bias=False)
conv7 = nn.Conv2d(1, 1, 3, bias=False)
conv8 = nn.Conv2d(1, 1, 3, bias=False)#卷积核1,使用bottom_sobel底部边缘卷积核。注意形状必须匹配
bottom_sobel = np.array([[-1, -2, -1],[0, 0, 0],[1, 2, 1]], dtype='float32').reshape((1, 1, 3, 3))
conv1.weight.data = torch.from_numpy(bottom_sobel)#卷积核2,使用left_sobel左部边缘卷积核
left_sobel = np.array([[1, 0, -1],[2, 0, -2],[1, 0, -1]], dtype='float32').reshape((1, 1, 3, 3))
conv2.weight.data = torch.from_numpy(left_sobel)#卷积核3,使用right_sobel右部边缘卷积核
right_sobel = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]], dtype='float32').reshape((1, 1, 3, 3))
conv3.weight.data = torch.from_numpy(right_sobel)#卷积核4,使用top_sobel顶部边缘卷积核
top_sobel = np.array([[-1, 2, 1],[0, 0, 0],[-1, -2, -1]], dtype='float32').reshape((1, 1, 3, 3))
conv4.weight.data = torch.from_numpy(top_sobel)#卷积核5,使用sharpen锐化卷积核
sharpen = np.array([[0, -1, 0],[-1, 5, -1],[0, -1, 0]], dtype='float32').reshape((1, 1, 3, 3))
conv5.weight.data = torch.from_numpy(sharpen)#卷积核6,使用blur模糊卷积核
blur = np.array([[0.0625, 0.125, 0.0625],[0.125, 0.25, 0.125],[0.0625, 0.125, 0.0625]], dtype='float32').reshape((1, 1, 3, 3))
conv6.weight.data = torch.from_numpy(blur)#卷积核7,使用emboss突出图像轮廓卷积核
emboss = np.array([[-2, -1, 0],[-1, 1, 1],[0, 1, 2]], dtype='float32').reshape((1, 1, 3, 3))
conv7.weight.data = torch.from_numpy(emboss)#卷积核8,使用outline检测边缘轮廓卷积核
outline = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, -1]], dtype='float32').reshape((1, 1, 3, 3))
conv8.weight.data = torch.from_numpy(outline)#卷积核定义完成,使用pytorch进行卷积操作,并把结果转换为numpy数组
#Variable把张量im包装成pytorch变量。
#.data 获取到张量的原始数据
#.squeeze()用于消除大小为1的维度
y1 = conv1(Variable(im)).data.squeeze().numpy()
y2 = conv2(Variable(im)).data.squeeze().numpy()
y3 = conv3(Variable(im)).data.squeeze().numpy()
y4 = conv4(Variable(im)).data.squeeze().numpy()
y5 = conv5(Variable(im)).data.squeeze().numpy()
y6 = conv6(Variable(im)).data.squeeze().numpy()
y7 = conv7(Variable(im)).data.squeeze().numpy()
y8 = conv8(Variable(im)).data.squeeze().numpy()# 可视化
plt.axis('off') #关闭xy轴plt.subplot(332).set_title('bottom_sobel')
plt.imshow(y1, cmap='gray')
plt.axis('off')plt.subplot(333).set_title('left_sobel')
plt.imshow(y2, cmap='gray')
plt.axis('off')plt.subplot(334).set_title('right_sobel')
plt.imshow(y3, cmap='gray')
plt.axis('off')plt.subplot(335).set_title('top_sobel')
plt.imshow(y4, cmap='gray')
plt.axis('off')plt.subplot(336).set_title('锐化sharpen')
plt.imshow(y5, cmap='gray')
plt.axis('off')plt.subplot(337).set_title('模糊blur')
plt.imshow(y6, cmap='gray')
plt.axis('off')plt.subplot(338).set_title('emboss')
plt.imshow(y7, cmap='gray')
plt.axis('off')plt.subplot(339).set_title('outline')
plt.imshow(y8, cmap='gray')
plt.axis('off')
plt.show()

运行结果:(感觉效果不是特别明显啊)


后接:关于使用pycharm输出卷积图像后图片仍然不清晰的可能原因以及解决方法👆

由上方我得到的卷积结果图可以看到,卷积的效果并没有很清晰。完全看不到模糊blur和锐化sharpen的效果(我甚至觉得它俩的卷积核是不是设置反了,检查代码后发现并没有弄反卷积核)。

       对于这个问题,我最初写完这篇博客只是认为这是pycharm显示图像性能不好的原因,就把这个问题放下了。但是魏老师关注到了这一点,给我分享了一篇博客,帮助我解决这个问题。所以我要对 卷积后效果不清晰 的这个问题进行一些解决尝试。

       魏老师分享的解决方案:

【精选】【NNDL作业】图像锐化后,为什么“蒙上了一层灰色”?_在matlab图像处理过程中,double型图像灰度值出现负数的原因-CSDN博客

简单来讲,就是图像中的像素点出现了 <0 和 >255 的情况,灰白图像像素点的值域很大(说白话就是黑、暗的地方更暗了,白、亮的的地方更亮了)进行卷积时,需要将图像的像素点值全部归一(也可以理解为映射)到[0,255]这个范围内。

在代码中若要实现像素点归一化,可以采取以下两种方式:

1. 遍历图像中的所有像素点,把>255的像素点设置为255,<0的像素点设置为0

2.使用imshow,设置imshow中参数  vmax,vmin  ,限制像素点范围

使用这两种方式,分别查看效果:

代码1: 遍历图像中的所有像素点,把>255的像素点设置为255,<0的像素点设置为0

#卷积NNDL 去灰操作
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 pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
file_path = 'C:\\Users\\27513\\Pictures\\Camera Roll\\NNDL.png'
im = Image.open(file_path).convert('L')  # 读入一张灰度图的图片
im = np.array(im, dtype='float32')  # 将其转换为一个矩阵
print('im的形状为:\n', im.shape[0], im.shape[1])
print('im为(图像处理前的矩阵):\n',im)plt.subplot(121).set_title('原始灰度图')
plt.imshow(im.astype('uint8'), cmap='gray')  # 可视化图片
plt.axis('off') #关闭xy轴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([[0, -1, 0],[-1, 5, -1],[0, -1, 0]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出
conv1.weight.data = torch.from_numpy(sobel_kernel)  # 给卷积的 kernel 赋值edge1 = conv1(Variable(im))  # 作用在图片上
print('edge1:\n', edge1)
print('edge1.shape[2]为:\n',edge1.shape[2])
print('edge1.shape[3]为:\n',edge1.shape[3])for i in range(edge1.shape[2]):for j in range(edge1.shape[3]):if edge1[0][0][i][j] > 255:edge1[0][0][i][j] = 255if edge1[0][0][i][j] < 0:edge1[0][0][i][j] = 0x = edge1.data.squeeze().numpy()
print('x的形状为:\n', x.shape)  # 输出大小
print('x为(图像去灰处理后的矩阵):\n', x)plt.subplot(122).set_title('去除灰色')
plt.imshow(x, cmap='gray')
plt.axis('off')
plt.show()

效果还是不错的,去灰后图片从视觉上来看变得清晰了,也没有灰蒙蒙的感觉。

代码2:使用imshow,设置imshow中参数  vmax,vmin  ,限制像素点范围

#卷积NNDL 去灰操作
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 pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
file_path = 'C:\\Users\\27513\\Pictures\\Camera Roll\\NNDL.png'
im = Image.open(file_path).convert('L')  # 读入一张灰度图的图片
im = np.array(im, dtype='float32')  # 将其转换为一个矩阵
print('im的形状为:\n', im.shape[0], im.shape[1])
print('im为(图像处理前的矩阵):\n',im)plt.subplot(121).set_title('原始灰度图')
plt.imshow(im.astype('uint8'), cmap='gray')  # 可视化图片
plt.axis('off') #关闭xy轴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([[0, -1, 0],[-1, 5, -1],[0, -1, 0]], dtype='float32')  # 定义轮廓检测算子
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))  # 适配卷积的输入输出
conv1.weight.data = torch.from_numpy(sobel_kernel)  # 给卷积的 kernel 赋值edge1 = conv1(Variable(im))  # 作用在图片上
print('edge1:\n', edge1)
print('edge1.shape[2]为:\n',edge1.shape[2])
print('edge1.shape[3]为:\n',edge1.shape[3])x = edge1.data.squeeze().numpy()
print('x的形状为:\n', x.shape)  # 输出大小
print('x为(图像去灰处理后的矩阵):\n', x)plt.subplot(122).set_title('去除灰色')
plt.imshow(x, cmap='gray',vmax=255,vmin=0)
plt.axis('off')
plt.show()

效果与代码1做出来的一样。 成功的去除掉了图片上灰蒙蒙的感觉,细节更加明显了,但是我换了一张分辨率相对较低的图片(手机拍摄的),结果出现了相反的结果:

图片变得更暗沉了,不如原图细节明显。

会不会和图像的质量(分辨率)有关呢??我又多尝试了几幅图片,分别使用了分辨率较低分辨率较高的不同图片。

分辨率较低图片:

原始图像分辨率就不高,但是进行去灰操作后图像仍然变亮了,而且细节更明显了。

分辨率较高图片:

仔细看这几组图,都去除了灰蒙蒙的效果,而且卷积后的图片更清晰了,细节更明显了(看不清的可以点开图片放大观察)。 那么可以得出结论,和图片的分辨率没有什么关系。

那么到底和什么原因有关系呢?为什么针对不同的图片,得到的效果不同呢?先留下一个疑问吧

现在将橘猫九宫图 全部进行去灰操作,看看效果:

我把没有进行去灰操作的大橘九宫图放在下面,对比一下:

对比之下可以看到,进行的去灰操作后,sobel  emboss 和outline的卷积效果更加明显了!这三个卷积核的效果有一个共同点:增强图像边缘、轮廓特征。(尤其是对于sobel和outline卷积核的效果最为明显,图片变为了黑白对比。)

也许是大橘猫照片的边缘轮廓特征不明显,所以我又换了一张本身边缘轮廓特征就比较明显的图片进行输出(这张照片是一个表情包):

各个卷积核的效果都十分的明显!

浅浅的总结一下:

1.未解决的问题:布偶猫咪照片为何进行去灰操作之后更灰更暗了?

2.对于大部分照片,进行去灰操作的效果是成功的、显著的。不仅去除了灰蒙蒙的图片效果,还增强了图片细节!

3.能否成功地进行去灰操作,与图像的分辨率没有关系。


5. 总结不同卷积核的特征和作用。

老师分享的网址:直观地解释图像内核 (setosa.io)

进入之后可以自己调整参数、卷积核、图片,进行可视化的直观体验。示例图:

可以看到 卷积的过程为对应的像素位置相乘再求和,计算出新的像素值。这个网站真的很直观很好用!!不仅详细的展示了3*3卷积核的参数内容,而且还给出了图片进行卷积后的不同效果。

现在我以河北大学校猫-大橘学长的照片为例子,总结常用卷积核矩阵以及效果:

河北大学校猫-大橘学长 原图

1.模糊效果:

2.浮雕效果:

3.锐化:

4.轮廓:

5.边缘sobel:(效果和上一个差不多,但是卷积核矩阵里的参数不同)

6.indentity 不改变:


6. 代码解读:

老师给出了参考的代码,我先读取了自家猫咪的图片,放入代码中试着运行了一次,进行了观察:

 可以看到卷积后的图像对原图像进行了边缘特征的提取(不是很清晰,可以调高亮度)。猫咪身体的边缘轮廓、胡子、眼鼻嘴的轮廓形状特征都被提取了出来。

我print了其中几个重要的参数值,用于更好的理解卷积网络运行的过程:

老师提供代码+自己的解读注释:

import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from PIL import Image
import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  #用来正常显示负号 #有中文出现的情况,需要u'内容
# https://blog.csdn.net/weixin_40123108/article/details/83510592
file_path = 'C:\\Users\\27513\\Pictures\\Camera Roll\\cat10.jpg'# 读入一张灰度图的图片,convert('L')表示这张图像已经自动转换为灰度图
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()#将numpy数据的图像重塑为torch张量,以适应卷积操作
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1])))#定义卷积层conv1,该卷积层输入通道数为1,输出通道数为1,卷积核大小为3*3,且无偏置项
conv1 = nn.Conv2d(1, 1, 3, bias=False)
print('卷积conv1的内容:', conv1)#定义轮廓检测算子,为numpy数组类型(定义卷积核),用于轮廓检测
sobel_kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, -1]], dtype='float32')
#适配卷积的输入输出
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))
print('改变适配输入输出形状的卷积核:\n',sobel_kernel,'\n',type(sobel_kernel))
#给卷积的 kernel 赋值w
conv1.weight.data = torch.from_numpy(sobel_kernel)
print('w参数值:',conv1.weight.data)# 作用在图片上 Variable(im)是将输入图像转换为Variable类型,方便计算
edge1 = conv1(Variable(im))#squeeze()消除大小为1的维度,使数据更便于处理。
x = edge1.data.squeeze().numpy()
print('卷积后图像形状:',x.shape)  # 输出大小plt.imshow(x, cmap='gray')
plt.title('卷积后图像')
plt.show()

>卷积层conv1的建立

输出的卷积层conv1信息为:
                      Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1), bias=False)

> sobel_kernel边缘检测算子(卷积核)的建立

   np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype='float32')是在创建一个3x3的浮点数数组,这个数组就是Sobel算子,通过与图像进行卷积,可以用来检测图像的边缘。这个算子在中心位置(也就是8的位置)有一个峰值,而在其他位置的值都是负数。这样,当这个算子和图像进行卷积时,会在边缘的位置产生较大的正数响应。

    sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))是将这个2D数组重塑为一个4D数组。在PyTorch中,卷积操作需要输入具有四维的张量,这四维分别是:批次大小(batch size),通道数量(channel数量),高度(height),宽度(width)。在这段代码中,批次大小和通道数量都为1,所以需要将2D的Sobel算子重塑为3D的张量,这样就可以将其用于卷积操作。


总结:

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

1.在代码部分,我了解到了在pytorch中,卷积操作需要输入具有4维张量,这四维张量分别是

  1. 批次大小(Batch Size):表示一次输入的样本数量。
  2. 通道数量(Channel Count):表示输入的每个样本具有多少个通道。对于彩色图像,这个                                                通道数量通常为3(RGB)。对于灰度图像,这个通道数量为1。
  3. 高度(Height):表示输入的每个样本的高度。
  4. 宽度(Width):表示输入的每个样本的宽度。

因此,一个典型的四维卷积输入张量形状可能为(Batch Size, Channel Count, Height, Width)。例如,如果有一个包含32个样本,每个样本都是3通道的彩色图像,图像大小为64x64,那么这个输入张量的形状将会是(32, 3, 64, 64)。

2.pytorch中的Variable类型是什么?

文心一言中我得到了如下解答:

pytorch官网中我得到了如下解答:

               意思就是Tensor已经替代了Variable类,新的pytorch已经剔除Variable类了。

一位博主的回答:

现在对我Variable有了更深一步的了解啦!
 

3.在网站中,获得了直观的卷积神经网络作用效果的体验:

   进入网站后,首先需要了解灰度图像是如何在计算机中展现出来的,灰度图像在计算机中以二维矩阵的方式存储,可以通过滑动鼠标到不同的像素点,观察对应灰度图上展示出来的效果。这些像素点的范围在[0,255],0展现为黑色,255展现为白色。

之后便可以通过调整卷积核(3*3矩阵)来展现不同的图像卷积后的效果:


对于文章中引用的博客链接和网络资料,在此鸣谢:

魏老师原博客:【23-24 秋学期】NNDL 作业6 卷积-CSDN博客

【精选】NNDL 作业5:卷积_笼子里的薛定谔的博客-CSDN博客

浅谈Pytorch中的Variable的使用方法_pytorch variable-CSDN博客

直观地解释图像内核 (setosa.io)

这篇关于[23-24 秋学期]NNDL 作业6 卷积 [HBU]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/378045

相关文章

龙蜥操作系统Anolis OS-23.x安装配置图解教程(保姆级)

《龙蜥操作系统AnolisOS-23.x安装配置图解教程(保姆级)》:本文主要介绍了安装和配置AnolisOS23.2系统,包括分区、软件选择、设置root密码、网络配置、主机名设置和禁用SELinux的步骤,详细内容请阅读本文,希望能对你有所帮助... ‌AnolisOS‌是由阿里云推出的开源操作系统,旨

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

Science|癌症中三级淋巴结构的免疫调节作用与治疗潜力|顶刊精析·24-09-08

小罗碎碎念 Science文献精析 今天精析的这一篇综述,于2022-01-07发表于Science,主要讨论了癌症中的三级淋巴结构(Tertiary Lymphoid Structures, TLS)及其在肿瘤免疫反应中的作用。 作者类型作者姓名单位名称(中文)通讯作者介绍第一作者Ton N. Schumacher荷兰癌症研究所通讯作者之一通讯作者Daniela S. Thomm

基于深度学习 卷积神经网络resnext50的中医舌苔分类系统

项目概述 本项目旨在通过深度学习技术,特别是利用卷积神经网络(Convolutional Neural Networks, CNNs)中的ResNeXt50架构,实现对中医舌象图像的自动分类。该系统不仅能够识别不同的舌苔类型,还能够在PyQt5框架下提供一个直观的图形用户界面(GUI),使得医生或患者能够方便地上传舌象照片并获取分析结果。 技术栈 深度学习框架:采用PyTorch或其他

华为23年笔试题

消息传输 题目描述 在给定的 m x n (1 <= m, n <= 1000) 网格地图 grid 中,分布着一些信号塔,用于区域间通信。 每个单元格可以有以下三种状态:  值 0 代表空地,无法传递信号;  值 1 代表信号塔 A,在收到消息后,信号塔 A 可以在 1ms 后将信号发送给上下左右四个方向的信号塔; 值 2 代表信号塔 B,在收到消息后,信号塔 B 可以在 2ms

SIGMOD-24概览Part7: Industry Session (Graph Data Management)

👇BG3: A Cost Effective and I/O Efficient Graph Database in ByteDance 🏛机构:字节 ➡️领域: Information systems → Data management systemsStorage management 📚摘要:介绍了字节新提出的ByteGraph 3.0(BG3)模型,用来处理大规模图结构数据 背景

如何将卷积神经网络(CNN)应用于医学图像分析:从分类到分割和检测的实用指南

引言 在现代医疗领域,医学图像已经成为疾病诊断和治疗规划的重要工具。医学图像的类型繁多,包括但不限于X射线、CT(计算机断层扫描)、MRI(磁共振成像)和超声图像。这些图像提供了对身体内部结构的详细视图,有助于医生在进行准确诊断和制定个性化治疗方案时获取关键的信息。 1. 医学图像分析的挑战 医学图像分析面临诸多挑战,其中包括: 图像数据的复杂性:医学图像通常具有高维度和复杂的结构

Java高级Day38-网络编程作业

112.网络编程作业 //1.使用字符流的方式,编写一个客户端程序和服务器端程序//2.客户端发送"name",服务器端接收到后,返回"我是nova"//3.客户端发送"hobby",服务器端接收到后,返回"编写java程序"//4.不是这两个问题,回复"你说啥呢"​​===============//客户端//===============public class SocketT

【A题成品论文已出】24数学建模国赛A题成品论文(附参考代码)免费分享

A 题  “板凳龙”  闹元宵 摘要 “板凳龙”是一种传统的民俗文化活动,通常由许多板凳连接成龙的形状进行表演。本文基于螺旋线和板凳龙的运动特性,建立数学模型来分析舞龙队在不同情况下的运动轨迹、调头路径和速度优化等问题。问题主要涉及板凳龙的行进路径、碰撞避免、调头空间的设计,以及如何优化龙头的速度,以确保龙身与龙尾的行进安全。 针对问题一,舞龙队由223节板凳组成,龙头前把手的速度为1