如何训练农业类——大棚分割数据集,40765对影像,16.9g数据量,0.8米高分二,纯手工标注(arcgis标注)的大规模农业大棚分割数据集 大棚数据集在这里插入图片描述

如何使用大规模农业大棚分割数据集进行训练。这个数据集包含40765对影像,总数据量为16.9GB,分辨率为0.8米,是通过ArcGIS手工标注的。我们将使用深度学习框架(如PyTorch)和分割模型(如U-Net)来进行训练。

数据集介绍
数据集描述
数据量:40765对影像
数据大小:16.9GB
分辨率:0.8米
标注工具:ArcGIS
任务类型:语义分割
数据集目录结构
假设你的数据集目录结构如下:

深色版本
dataset/
├── images/
│ ├── train/
│ └── val/
└── masks/
├── train/
└── val/

  1. 创建数据集配置文件
    创建一个名为 greenhouse_segmentation.yaml 的文件,内容如下:

yaml
深色版本

数据集路径

train_images: ./dataset/images/train/
train_masks: ./dataset/masks/train/
val_images: ./dataset/images/val/
val_masks: ./dataset/masks/val/

类别数量

nc: 2 # 假设只有两类:大棚和背景

类别名称

names: [‘background’, ‘greenhouse’]
2. 安装必要的库
确保已经安装了 torch, torchvision, numpy, matplotlib, PIL 等依赖项:

bash
深色版本
pip install torch torchvision numpy matplotlib pillow
3. 编写数据加载器
首先,编写一个自定义的数据加载器来读取图像和对应的掩码:

python
深色版本
import os
import torch
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import numpy as np

class GreenhouseDataset(Dataset):
def init(self, image_dir, mask_dir, transform=None):
self.image_dir = image_dir
self.mask_dir = mask_dir
self.transform = transform
self.images = os.listdir(image_dir)

def __len__(self):
    return len(self.images)

def __getitem__(self, index):
    img_path = os.path.join(self.image_dir, self.images[index])
    mask_path = os.path.join(self.mask_dir, self.images[index].replace('.jpg', '.png'))  # 假设掩码文件扩展名为.png
    image = Image.open(img_path).convert("RGB")
    mask = Image.open(mask_path).convert("L")  # 灰度图像

    if self.transform:
        image = self.transform(image)
        mask = self.transform(mask)

    return image, mask

数据增强和预处理

from torchvision import transforms

transform = transforms.Compose([
transforms.Resize((256, 256)), # 调整图像大小
transforms.ToTensor(), # 转换为Tensor
])

创建数据加载器

train_dataset = GreenhouseDataset(
image_dir=‘./dataset/images/train/’,
mask_dir=‘./dataset/masks/train/’,
transform=transform
)

val_dataset = GreenhouseDataset(
image_dir=‘./dataset/images/val/’,
mask_dir=‘./dataset/masks/val/’,
transform=transform
)

train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=4)
val_loader = DataLoader(val_dataset, batch_size=16, shuffle=False, num_workers=4)
4. 定义分割模型
我们将使用U-Net作为分割模型。这里使用一个简单的U-Net实现:

python
深色版本
import torch
import torch.nn as nn
import torch.nn.functional as F

class UNet(nn.Module):
def init(self, n_channels, n_classes):
super(UNet, self).init()
self.inc = self.inconv(n_channels, 64)
self.down1 = self.down(64, 128)
self.down2 = self.down(128, 256)
self.down3 = self.down(256, 512)
self.down4 = self.down(512, 1024)
self.up1 = self.up(1024, 512)
self.up2 = self.up(512, 256)
self.up3 = self.up(256, 128)
self.up4 = self.up(128, 64)
self.outc = self.outconv(64, n_classes)

def inconv(self, in_ch, out_ch):
    return nn.Sequential(
        nn.Conv2d(in_ch, out_ch, 3, padding=1),
        nn.ReLU(inplace=True),
        nn.Conv2d(out_ch, out_ch, 3, padding=1),
        nn.ReLU(inplace=True)
    )

def down(self, in_ch, out_ch):
    return nn.Sequential(
        nn.MaxPool2d(2),
        nn.Conv2d(in_ch, out_ch, 3, padding=1),
        nn.ReLU(inplace=True),
        nn.Conv2d(out_ch, out_ch, 3, padding=1),
        nn.ReLU(inplace=True)
    )

def up(self, in_ch, out_ch):
    return nn.Sequential(
        nn.ConvTranspose2d(in_ch, out_ch, 2, stride=2),
        nn.Conv2d(out_ch, out_ch, 3, padding=1),
        nn.ReLU(inplace=True),
        nn.Conv2d(out_ch, out_ch, 3, padding=1),
        nn.ReLU(inplace=True)
    )

def outconv(self, in_ch, out_ch):
    return nn.Conv2d(in_ch, out_ch, 1)

def forward(self, x):
    x1 = self.inc(x)
    x2 = self.down1(x1)
    x3 = self.down2(x2)
    x4 = self.down3(x3)
    x5 = self.down4(x4)
    x = self.up1(x5, x4)
    x = self.up2(x, x3)
    x = self.up3(x, x2)
    x = self.up4(x, x1)
    x = self.outc(x)
    return F.sigmoid(x)
  1. 训练模型
    编写训练脚本:

python
深色版本
import torch.optim as optim
import torch.nn.functional as F

初始化模型

model = UNet(n_channels=3, n_classes=1).cuda()

定义损失函数和优化器

criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

训练循环

num_epochs = 100
best_val_loss = float(‘inf’)

for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for images, masks in train_loader:
images, masks = images.cuda(), masks.cuda()
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, masks)
loss.backward()
optimizer.step()
running_loss += loss.item() * images.size(0)

train_loss = running_loss / len(train_loader.dataset)

# 验证
model.eval()
val_loss = 0.0
with torch.no_grad():
    for images, masks in val_loader:
        images, masks = images.cuda(), masks.cuda()
        outputs = model(images)
        loss = criterion(outputs, masks)
        val_loss += loss.item() * images.size(0)

val_loss /= len(val_loader.dataset)

print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Val Loss: {val_loss:.4f}')

# 保存最佳模型
if val_loss < best_val_loss:
    best_val_loss = val_loss
    torch.save(model.state_dict(), 'best_greenhouse_segmentation_model.pth')

print(“Training complete.”)
6. 测试模型
训练完成后,你可以使用以下代码测试模型:

python
深色版本
import matplotlib.pyplot as plt

加载最佳模型

model.load_state_dict(torch.load(‘best_greenhouse_segmentation_model.pth’))
model.eval()

从验证集中选择一张图像进行测试

images, masks = next(iter(val_loader))
images, masks = images.cuda(), masks.cuda()

with torch.no_grad():
outputs = model(images)
predicted_masks = (outputs > 0.5).float()

显示结果

fig, axs = plt.subplots(3, 1, figsize=(10, 15))

axs[0].imshow(images[0].cpu().permute(1, 2, 0))
axs[0].set_title(‘Input Image’)
axs[0].axis(‘off’)

axs[1].imshow(masks[0].cpu().permute(1, 2, 0), cmap=‘gray’)
axs[1].set_title(‘Ground Truth Mask’)
axs[1].axis(‘off’)

axs[2].imshow(predicted_masks[0].cpu().permute(1, 2, 0), cmap=‘gray’)
axs[2].set_title(‘Predicted Mask’)
axs[2].axis(‘off’)

plt.show()
7. 模型优化
如果你发现模型性能不佳,可以尝试以下方法进行优化:

数据增强:增加数据增强策略,如随机裁剪、翻转等。
调整超参数:调整学习率、批量大小、训练轮次等。
使用更强大的模型:尝试使用更复杂的分割模型,如DeepLabV3、HRNet等。
增加训练数据:如果可能,增加更多标注数据以提高模型泛化能力。
希望这些详细的步骤能帮助你成功训练农业大棚分割模型

更多推荐