1.概述
卷积在 pytorch 中的卷积操作通常用 torch.nn.Conv2d()实现,这种形式对于输入的要求都是:
- 首先需要输入是一个 torch.autograd.Variable() 的类型,但是现在Variable() 和tensor类型合并了,所以输入为tensor类型即可;
- 输入大小是 (batch, channel, H, W),其中 batch 表示输入的一批数据的数目,第二个是输入的通道数,一般一张彩色的图片是 3,灰度图是 1,而卷积网络过程中的通道数比较大,会出现几十到几百的通道数,H 和 W 表示输入图片的高度和宽度
- 注意卷积核的shape要和输入图像的shape值相同
2.整体流程:
- 利用cv2读取灰度图
- 将图片转换成numpy.ndarray格式,且dtype=‘float32’
- 转成tensor格式,并且reshape成 (batch,channal,h,w)形式
- 卷积,激活函数,池化(注:sobel_kernel 要和img一个shape)
3.具体实现
import numpy as np
import torch
from torch import nn
import torch.nn.functional as F
import cv2
'''
流程:
1.利用cv2读取灰度图
2.将图片转换成numpy.ndarray格式,且dtype='float32'
3.转成tensor格式,并且reshape成 (batch,channal,h,w)形式
4.卷积,激活函数,池化(注:sobel_kernel 要和img一个shape)
'''
im=cv2.imread("./contours.png",0) # 读入一张灰度图的图片 466*619
im = np.array(im, dtype='float32') # 将其转换为一个矩阵
im = torch.from_numpy(im.reshape((1, 1, im.shape[0], im.shape[1]))) # torch.Size([1, 1, 466, 619])
conv1 = nn.Conv2d(1, 1, 3, bias=False) # 定义卷积
sobel_kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype='float32') # 定义轮廓检测算子 3*3
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3)) # 适配卷积的输入输出 3*3=1*1*3*3
conv1.weight.data = torch.from_numpy(sobel_kernel) # 给卷积的 kernel 赋值,假如不赋值,会自动赋予一个kernel_size=3的卷积核
edge1 = conv1(im) # 进行卷积
# edge1 = edge1.data.squeeze().numpy() # 将输出转换为图片的格式,(464, 617),<class 'tuple'>,为了方便展示图片
x=F.relu(edge1) #加入一层激活函数
# 最大池化层
pool1 = nn.MaxPool2d(2, 2)
x = pool1(x) #加入一层池化
#print(x.data) # torch.Size([1, 1, 232, 308]) tensor
x = x.data.squeeze().numpy() # (232, 308) numpy
#print(x.shape)#输出大小
cv2.imshow('img',x)
cv2.waitKey(0)