用eca_resnet50进行图像去噪,包含train.py、val,py、test.py,并在test.py中导出去噪后的图片
时间: 2024-04-30 21:20:18 浏览: 157
好的,首先需要安装相关的库,包括PyTorch、torchvision、Pillow、numpy等。
接着,我们可以定义一个 `ECA_ResNet50` 类,实现图像去噪的功能。具体实现代码如下:
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
class ECABlock(nn.Module):
def __init__(self, channels, kernel_size, gamma=2, b=1):
super(ECABlock, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.conv = nn.Conv1d(1, 1, kernel_size, padding=(kernel_size - 1) // 2, bias=False)
self.sigmoid = nn.Sigmoid()
self.fc = nn.Sequential(
nn.Linear(channels, channels // gamma),
nn.ReLU(inplace=True),
nn.Linear(channels // gamma, channels)
)
self.bn = nn.BatchNorm2d(channels, affine=False)
self.b = b
def forward(self, x):
b, c, _, _ = x.size()
y = self.avg_pool(x)
y = self.conv(y.squeeze(-1).transpose(-1, -2))
y = y.transpose(-1, -2).unsqueeze(-1)
y = self.sigmoid(y)
y = x * y.expand_as(x)
z = self.fc(y.view(b, c)).view(b, c, 1, 1)
out = self.bn(z) * self.b + x
return out
class ECA_ResNet50(nn.Module):
def __init__(self, num_classes=10):
super(ECA_ResNet50, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = nn.Sequential(
nn.Conv2d(64, 256, kernel_size=1, stride=1, bias=False),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
ECABlock(256, 3),
ECABlock(256, 3),
ECABlock(256, 3)
)
self.layer2 = nn.Sequential(
nn.Conv2d(256, 512, kernel_size=1, stride=2, bias=False),
nn.BatchNorm2d(512),
nn.ReLU(inplace=True),
ECABlock(512, 3),
ECABlock(512, 3),
ECABlock(512, 3),
ECABlock(512, 3)
)
self.layer3 = nn.Sequential(
nn.Conv2d(512, 1024, kernel_size=1, stride=2, bias=False),
nn.BatchNorm2d(1024),
nn.ReLU(inplace=True),
ECABlock(1024, 3),
ECABlock(1024, 3),
ECABlock(1024, 3),
ECABlock(1024, 3),
ECABlock(1024, 3),
ECABlock(1024, 3)
)
self.layer4 = nn.Sequential(
nn.Conv2d(1024, 2048, kernel_size=1, stride=2, bias=False),
nn.BatchNorm2d(2048),
nn.ReLU(inplace=True),
ECABlock(2048, 3),
ECABlock(2048, 3),
ECABlock(2048, 3)
)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(2048, num_classes)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.maxpool(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
```
接下来,我们需要定义训练、验证和测试函数。训练函数中,我们使用 `nn.MSELoss()` 作为损失函数,使用 `torch.optim.Adam()` 作为优化器,设置学习率为 0.001,训练 50 个 epoch,每个 epoch 中,我们先将模型设置为训练模式,然后遍历训练集中的每一个 batch,将输入的图像加上噪声,将加噪后的图像送入网络中,计算输出和目标图像的均方误差,并更新网络参数。每个 epoch 完成后,我们调用验证函数,计算模型在验证集上的准确率。测试函数中,我们遍历测试集中的每一个样本,将其送入网络中,得到去噪后的图像,并保存到指定的文件夹中。
具体实现代码如下:
```python
import os
import numpy as np
import argparse
from PIL import Image
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision.utils import save_image
import torchvision.transforms as transforms
def train(net, trainloader, criterion, optimizer, device):
net.train()
train_loss = 0
for i, (inputs, targets) in enumerate(trainloader):
inputs = inputs.to(device)
targets = targets.to(device)
inputs_noisy = inputs + 0.1 * torch.randn(inputs.size()).to(device)
optimizer.zero_grad()
outputs = net(inputs_noisy)
loss = criterion(outputs, inputs)
loss.backward()
optimizer.step()
train_loss += loss.item()
return train_loss / len(trainloader)
def val(net, valloader, criterion, device):
net.eval()
total = 0
correct = 0
val_loss = 0
with torch.no_grad():
for i, (inputs, targets) in enumerate(valloader):
inputs = inputs.to(device)
targets = targets.to(device)
inputs_noisy = inputs + 0.1 * torch.randn(inputs.size()).to(device)
outputs = net(inputs_noisy)
loss = criterion(outputs, inputs)
val_loss += loss.item()
_, predicted = outputs.max(1)
total += targets.size(0)
correct += predicted.eq(targets).sum().item()
return val_loss / len(valloader), correct / total
def test(net, testloader, device, output_dir):
net.eval()
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for i, (inputs, filename) in enumerate(testloader):
inputs = inputs.to(device)
inputs_noisy = inputs + 0.1 * torch.randn(inputs.size()).to(device)
outputs = net(inputs_noisy)
denoised_img = outputs.detach().cpu()
save_image(denoised_img, os.path.join(output_dir, filename[0]))
def main():
parser = argparse.ArgumentParser(description="Image Denoising with ECA-ResNet50")
parser.add_argument('--train-data', type=str, default='./train', help='path to the train data')
parser.add_argument('--val-data', type=str, default='./val', help='path to the validation data')
parser.add_argument('--test-data', type=str, default='./test', help='path to the test data')
parser.add_argument('--output-dir', type=str, default='./output/', help='output directory')
parser.add_argument('--num-epochs', type=int, default=50, help='number of epochs to train')
parser.add_argument('--batch-size', type=int, default=32, help='batch size')
parser.add_argument('--lr', type=float, default=0.001, help='learning rate')
parser.add_argument('--num-workers', type=int, default=4, help='number of workers for data loading')
parser.add_argument('--cuda', action='store_true', help='use cuda')
args = parser.parse_args()
train_transform = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor()
])
val_transform = transforms.Compose([
transforms.ToTensor()
])
test_transform = transforms.Compose([
transforms.ToTensor()
])
trainset = ImageFolderWithFilename(args.train_data, transform=train_transform)
trainloader = DataLoader(trainset, batch_size=args.batch_size, shuffle=True, num_workers=args.num_workers)
valset = ImageFolderWithFilename(args.val_data, transform=val_transform)
valloader = DataLoader(valset, batch_size=args.batch_size, shuffle=False, num_workers=args.num_workers)
testset = ImageFolderWithFilename(args.test_data, transform=test_transform)
testloader = DataLoader(testset, batch_size=1, shuffle=False, num_workers=args.num_workers)
device = torch.device('cuda' if args.cuda and torch.cuda.is_available() else 'cpu')
net = ECA_ResNet50().to(device)
criterion = nn.MSELoss()
optimizer = optim.Adam(net.parameters(), lr=args.lr)
for epoch in range(args.num_epochs):
train_loss = train(net, trainloader, criterion, optimizer, device)
val_loss, val_acc = val(net, valloader, criterion, device)
print('Epoch [{}/{}], Train Loss: {:.4f}, Val Loss: {:.4f}, Val Acc: {:.4f}'.format(
epoch+1, args.num_epochs, train_loss, val_loss, val_acc))
test(net, testloader, device, args.output_dir)
class ImageFolderWithFilename(torchvision.datasets.ImageFolder):
def __getitem__(self, index):
original_tuple = super().__getitem__(index)
path = self.imgs[index][0]
tuple_with_path = (original_tuple + (path,))
return tuple_with_path
if __name__ == '__main__':
main()
```
最后,我们可以通过以下命令运行代码:
```
python train.py --train-data <path_to_train_data> --val-data <path_to_validation_data> --test-data <path_to_test_data> --output-dir <path_to_output_directory> --num-epochs 50 --batch-size 32 --lr 0.001 --num-workers 4 --cuda
```
其中,`<path_to_train_data>`、`<path_to_validation_data>` 和 `<path_to_test_data>` 分别为训练集、验证集和测试集的路径,`<path_to_output_directory>` 为输出文件夹的路径。`--num-epochs`、`--batch-size`、`--lr` 和 `--num-workers` 分别表示训练的 epoch 数、batch size、学习率和数据加载的线程数。`--cuda` 表示使用 CUDA 进行训练(如果可用)。
阅读全文