下面可视化其中部分图像,以对比添加噪声前后的图像内容,程序如下:
plt.figure(figsize=(6,6))
for ii in np.arange(36):
plt.subplot(6,6,ii+1)
plt.imshow(images[ii,...])
plt.axis("off")
# plt.show()
plt.figure(figsize=(6,6))
for ii in np.arange(36):
plt.subplot(6,6,ii+1)
plt.imshow(images_noise[ii,...])
plt.axis("off")
# plt.show()
上述程序可以得到下面的图像,其中第一幅是原始图像,第二幅为添加噪声后的图像。可见带噪声的图像更加模糊,通过卷积自编码网络降噪器的目的是要去除图像中的噪音,获取“干净的图像。
接下来需要将图像数据集切分为训练集和验证集,并且处理为PyTorch网络可用的数据形式。
data_Y=np.transpose(images,(0,3,2,1))
data_X=np.transpose(images_noise,(0,3,2,1))
X_train,X_val,y_train,y_val=train_test_split(
data_X,data_Y,test_size=0.2,random_state=123
)
X_train=torch.tensor(X_train,dtype=torch.float32)
y_train=torch.tensor(y_train,dtype=torch.float32)
X_val=torch.tensor(X_val,dtype=torch.float32)
y_val=torch.tensor(y_val,dtype=torch.float32)
train_data=Data.TensorDataset(X_train,y_train)
val_data=Data.TensorDataset(X_val,y_val)
# print("X_train.shape:",X_train.shape)
# print("y_train.shape:",y_train.shape)
# print("X_val,shape:",X_val.shape)
# print("y_val.shape:",y_val.shape)
输出结果为:
上述程序 首先将两个数据集使用np.transpose()函数转化为[样本,通道,高,宽]的数据形式,然后使用train_test_split()函数将80%的数据用于训练集,20%的数据用于验证集,再使用Data.TensorDataset()函数将数据集中的X和Y数据进行处理,防止到统一的张量中,从输出可知,训练数据包含4000张图像,验证数据包含1000张图像。
接下来使用Data.DataLoader()函数将训练数据集合验证数据集处理为数据加载器train_loader和val_loader,并且每个batch包含32张图像。
train_loader=Data.DataLoader(
dataset=train_data,
batch_size=32,
shuffle=True,
num_workers=4,
)
val_loader=Data.DataLoader(
dataset=val_data,
batch_size=32,
shuffle=True,
num_workers=4
)
在数据预处理完成后,开始搭建卷积自编码网络。定义一个DenoiseAutoEncoder()类表示网络结果。
class DenoiseAutoEncoder(nn.Module):
def __init__(self):
super(DenoiseAutoEncoder, self).__init__()
self.Encoder=nn.Sequential(
nn.Conv2d(in_channels=3,out_channels=64,
kernel_size=3,stride=1,padding=1),
nn.ReLU(),
nn.BatchNorm2d(64),
nn.Conv2d(64,64,3,1,1),
nn.ReLU(),
nn.BatchNorm2d(64),
nn.Conv2d(64, 64, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(2,2),
nn.BatchNorm2d(64),
nn.Conv2d(64,128,3,1,1),
nn.ReLU(),
nn.BatchNorm2d(128),
nn.Conv2d(128, 128, 3, 1, 1),
nn.ReLU(),
nn.BatchNorm2d(128),
nn.Conv2d(128, 256, 3, 1, 1),
nn.ReLU(),
nn.MaxPool2d(2,2),
nn.BatchNorm2d(256)
)
self.Decoder=nn.Sequential(
nn.ConvTranspose2d(256,128,3,1,1),
nn.ReLU(),
nn.BatchNorm2d(128),
nn.ConvTranspose2d(128, 128, 3,2, 1, 1),
nn.ReLU(),
nn.BatchNorm2d(128),
nn.ConvTranspose2d(128, 64, 3, 1, 1),
nn.ReLU(),
nn.BatchNorm2d(64),
nn.ConvTranspose2d(64, 32, 3, 1, 1),
nn.ReLU(),
nn.BatchNorm2d(32),
nn.ConvTranspose2d(32, 32, 3, 1, 1),
nn.ConvTranspose2d(32, 16, 3,2, 1, 1),
nn.ReLU(),
nn.BatchNorm2d(16),
nn.ConvTranspose2d(16, 3, 3, 1, 1),
nn.Sigmoid(),
)
def forward(self,x):
encoder=self.Encoder(x)
decoder=self.Decoder(encoder)
return encoder,decoder
在上述定义的网络类中主要包含自编码模块Encoder和解码模块Decoder,在Encoder模块中,卷积核均为3*3,并且激活函数为ReLU,池化层使用最大值池化,经过多个卷积、池化和BatchNorm等操作后,图像的尺寸从96*96缩小为24*24,并且通道数会逐渐从3增加到256.但在Decoder模块中,做相反的操作,通过nn.ConvTranspose2d()函数对特征映射进行转置卷积,从而对特征映射进行放大,激活函数除最后一层使用SIgmoid外,其余层则使用ReLU激活函数。经过Decoder后,特征映射逐渐从24*24放大到96*96,并且通道数也会从256逐渐过渡到3,对应着原始的RGB图像。在网络的forward()函数中会分别输出encoder和decoder的结果。
下面使用定义的网络DenoiseAutoEncoder()类初始化基于卷积层的自编码去噪网络DAEmodel,其网络结果输出如下所示: