BTAD数据集实战指南:从数据预处理到模型训练的全流程解析

1次阅读
没有评论

共计 4573 个字符,预计需要花费 12 分钟才能阅读完成。

image.webp

背景介绍

BTAD(Braille Textile Anomaly Detection)数据集是工业缺陷检测领域的重要基准数据集之一,主要用于纺织品表面的缺陷检测。该数据集包含三种不同类型的纺织品缺陷,每种缺陷都有数百张高分辨率图像,并提供了精确的边界框标注。BTAD 数据集在学术界被广泛用于评估缺陷检测算法的性能,尤其是在小目标检测和复杂背景下的缺陷识别方面具有挑战性。

BTAD 数据集实战指南:从数据预处理到模型训练的全流程解析

数据加载

BTAD 数据集的目录结构通常如下:

BTAD/
├── train/
│   ├── images/
│   ├── annotations_json/
├── test/
│   ├── images/
│   ├── annotations_json/

以下是使用 Python 加载 BTAD 数据集的代码示例:

import json
import os
from PIL import Image
import numpy as np

def load_btad_dataset(base_path):
    """
    加载 BTAD 数据集
    :param base_path: 数据集根目录
    :return: 图像和标注列表
    """
    images = []
    annotations = []

    # 遍历 train 和 test 目录
    for split in ['train', 'test']:
        image_dir = os.path.join(base_path, split, 'images')
        anno_dir = os.path.join(base_path, split, 'annotations_json')

        for img_file in os.listdir(image_dir):
            if not img_file.endswith('.png'):
                continue

            # 加载图像
            img_path = os.path.join(image_dir, img_file)
            image = Image.open(img_path)
            images.append(image)

            # 加载对应的标注文件
            anno_path = os.path.join(anno_dir, img_file.replace('.png', '.json'))
            with open(anno_path, 'r') as f:
                anno = json.load(f)
            annotations.append(anno)

    return images, annotations

数据可视化

为了更好地理解数据集,我们可以使用 Matplotlib 可视化一些样本:

import matplotlib.pyplot as plt
import matplotlib.patches as patches

def visualize_sample(image, annotation):
    """
    可视化样本图像和标注
    :param image: PIL 图像
    :param annotation: 标注字典
    """
    fig, ax = plt.subplots(1)
    ax.imshow(image)

    # 绘制边界框
    for obj in annotation['objects']:
        bbox = obj['bbox']
        rect = patches.Rectangle((bbox['xmin'], bbox['ymin']),
            bbox['xmax'] - bbox['xmin'],
            bbox['ymax'] - bbox['ymin'],
            linewidth=1,
            edgecolor='r',
            facecolor='none'
        )
        ax.add_patch(rect)
        ax.text(bbox['xmin'], bbox['ymin'],
            obj['category'],
            color='white',
            bbox=dict(facecolor='red', alpha=0.5)
        )

    plt.axis('off')
    plt.show()

# 示例用法
images, annotations = load_btad_dataset('path/to/BTAD')
visualize_sample(images[0], annotations[0])

预处理技巧

工业图像通常需要特殊的预处理方法:

  1. 光照归一化:工业环境下光照条件可能不稳定,可以使用直方图均衡化或 CLAHE 方法
import cv2

def normalize_illumination(image):
    """
    光照归一化
    :param image: 输入图像
    :return: 归一化后的图像
    """
    # 转换为灰度图
    gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY)

    # CLAHE 自适应直方图均衡化
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    normalized = clahe.apply(gray)

    return Image.fromarray(normalized)
  1. ROI 提取:关注可能包含缺陷的区域,减少计算量
def extract_roi(image, annotation, margin=20):
    """
    提取感兴趣区域 (ROI)
    :param image: 输入图像
    :param annotation: 标注信息
    :param margin: 边界扩展像素
    :return: ROI 图像
    """
    img_array = np.array(image)

    # 合并所有缺陷框
    boxes = [obj['bbox'] for obj in annotation['objects']]
    xmin = min(b['xmin'] for b in boxes) - margin
    ymin = min(b['ymin'] for b in boxes) - margin
    xmax = max(b['xmax'] for b in boxes) + margin
    ymax = max(b['ymax'] for b in boxes) + margin

    # 确保不超出图像边界
    xmin = max(0, xmin)
    ymin = max(0, ymin)
    xmax = min(img_array.shape[1], xmax)
    ymax = min(img_array.shape[0], ymax)

    roi = img_array[ymin:ymax, xmin:xmax]
    return Image.fromarray(roi)

模型训练

以下是基于 PyTorch 的 ResNet 训练示例:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import models, transforms
from torch.utils.data import Dataset, DataLoader

class BTADDataset(Dataset):
    """自定义数据集类"""
    def __init__(self, images, annotations, transform=None):
        self.images = images
        self.annotations = annotations
        self.transform = transform

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

    def __getitem__(self, idx):
        image = self.images[idx]
        annotation = self.annotations[idx]

        # 转换为张量
        if self.transform:
            image = self.transform(image)

        # 创建目标张量
        # 这里简化为二分类问题(有缺陷 / 无缺陷)target = 1 if len(annotation['objects']) > 0 else 0
        target = torch.tensor(target, dtype=torch.long)

        return image, target

# 数据增强
train_transform = transforms.Compose([transforms.Resize((256, 256)),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(10),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])

# 加载数据集
images, annotations = load_btad_dataset('path/to/BTAD')
train_dataset = BTADDataset(images[:800], annotations[:800], train_transform)
test_dataset = BTADDataset(images[800:], annotations[800:], train_transform)

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

# 初始化模型
model = models.resnet18(pretrained=True)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2)  # 二分类

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

# 训练循环
for epoch in range(10):
    model.train()
    running_loss = 0.0

    for inputs, labels in train_loader:
        optimizer.zero_grad()

        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()

    print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}')

避坑指南

  1. 标注坐标转换错误:BTAD 的标注坐标是基于图像原始尺寸的,在 resize 或 crop 时要注意同步调整

  2. 类别不平衡问题:工业缺陷数据通常正负样本不均衡,可以采用以下方法:

  3. 过采样少数类

  4. 使用加权损失函数
  5. 数据增强时对少数类增加采样概率

  6. 评估指标选择:

  7. 精确率 (Precision):正确预测的正例占所有预测正例的比例

  8. 召回率 (Recall):正确预测的正例占所有实际正例的比例
  9. F1 分数:精确率和召回率的调和平均
  10. mAP:平均精确率,适用于多类别检测

延伸思考

  1. 如何改进现有流程应对小样本场景?可以考虑使用迁移学习或半监督学习方法。

  2. 对于更复杂的缺陷形状,边界框可能不够精确,可以尝试使用实例分割方法。

  3. 在实际工业环境中,如何应对实时性要求?可以考虑模型轻量化或硬件加速。

通过本文的步骤,你应该能够快速上手 BTAD 数据集并构建基础的工业缺陷检测模型。在实际应用中,还需要根据具体场景调整预处理方法和模型架构。

正文完
 0
评论(没有评论)