共计 2838 个字符,预计需要花费 8 分钟才能阅读完成。
为什么选择 BSD100 数据集
BSD100(Berkeley Segmentation Dataset 100)是图像超分辨率(Super-Resolution, SR)领域的黄金标准之一,包含 100 张高质量自然场景图像。它的价值主要体现在:

- 基准可比性:超过 70% 的超分辨率论文使用该数据集进行横向对比
- 场景多样性:涵盖城市、自然、人物等丰富场景
- 分辨率标准:所有图像统一为 481×321 或 321×481 像素
在超分辨率任务中,我们通常需要将低分辨率 (LR) 图像恢复为高分辨率 (HR) 版本。BSD100 的特殊之处在于其 HR 图像都是真实拍摄而非合成生成,这对模型的泛化能力提出更高要求。
数据集结构解析
下载解压后的目录结构如下:
BSD100/
├── HR/ # 高分辨率图像
│ ├── 0801.png
│ └── ...
└── LR_bicubic/X4/ # 双三次降采样 4 倍的低分辨率图像
├── 0801x4.png
└── ...
关键点说明:
- 文件名对应规则:
LR_bicubic/X4/0801x4.png对应HR/0801.png - 降采样倍数:官方提供 2×、3×、4×三种降采样版本
- 图像格式:全部为 PNG 格式避免压缩伪影
数据加载实战
以下是使用 Python 进行数据加载的标准流程,我们同时比较 OpenCV 和 PIL 库的处理差异:
import cv2
from PIL import Image
import numpy as np
import os
# 配置数据集路径
data_dir = './BSD100'
hr_dir = os.path.join(data_dir, 'HR')
lr_dir = os.path.join(data_dir, 'LR_bicubic/X4')
# 使用 OpenCV 加载(注意 BGR/RGB 转换)def load_with_cv2(img_path):
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转换为 RGB 格式
return img
# 使用 PIL 加载(保留 EXIF 信息)def load_with_pil(img_path):
with Image.open(img_path) as img:
img.load() # 确保 EXIF 信息读取
return np.array(img)
# 示例:加载配对的 HR/LR 图像
sample_id = '0801'
hr_img = load_with_pil(os.path.join(hr_dir, f'{sample_id}.png'))
lr_img = load_with_pil(os.path.join(lr_dir, f'{sample_id}x4.png'))
print(f'HR shape: {hr_img.shape}, LR shape: {lr_img.shape}')
# 输出示例:HR shape: (321, 481, 3), LR shape: (80, 120, 3)
预处理与增强技巧
标准化流程
# 归一化到 [0,1] 范围并转换为 Tensor
import torch
def normalize(img):
img = img.astype(np.float32) / 255.0
return torch.from_numpy(img).permute(2, 0, 1) # HWC -> CHW
# 反向归一化(用于结果可视化)def denormalize(tensor):
tensor = tensor.clamp(0, 1).permute(1, 2, 0) # CHW -> HWC
return (tensor.numpy() * 255).astype(np.uint8)
数据增强方案
- 训练阶段:
- 随机水平 / 垂直翻转(p=0.5)
- 90 度随机旋转
-
色彩抖动(亮度±0.1,对比度±0.1)
-
测试阶段:
- 仅中心裁剪保持尺寸一致
- 绝对禁止使用任何随机变换
# 示例增强实现
from torchvision import transforms
train_transform = transforms.Compose([transforms.RandomHorizontalFlip(),
transforms.RandomVerticalFlip(),
transforms.ToTensor(),])
test_transform = transforms.Compose([transforms.ToTensor(),
])
降采样方法对比
BSD100 官方使用双三次插值(bicubic interpolation)生成 LR 图像,但实际研究中常需自定义降采样方法:
def downsample(img, factor=4, mode='bicubic'):
h, w = img.shape[:2]
new_h, new_w = h // factor, w // factor
if mode == 'bicubic':
return cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_CUBIC)
elif mode == 'nearest':
return cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_NEAREST)
elif mode == 'lanczos':
return cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_LANCZOS4)
else:
raise ValueError(f'Unknown mode: {mode}')
不同方法的视觉影响:
| 方法 | 计算耗时 | 边缘平滑度 | 伪影程度 |
|---|---|---|---|
| 最近邻 | ★☆☆☆☆ | ★☆☆☆☆ | ★★★★☆ |
| 双线性 | ★★★☆☆ | ★★★☆☆ | ★★☆☆☆ |
| 双三次 | ★★★★☆ | ★★★★☆ | ★☆☆☆☆ |
| Lanczos | ★★★★★ | ★★★★★ | ★☆☆☆☆ |
性能评估指标
PSNR 计算
def psnr(hr, sr, max_val=1.0):
mse = torch.mean((hr - sr) ** 2)
return 10 * torch.log10(max_val ** 2 / mse)
SSIM 计算
from skimage.metrics import structural_similarity as ssim
def calc_ssim(hr, sr):
# 转换为灰度计算(多通道需分别计算后取平均)return ssim(hr, sr, multichannel=True, data_range=1.0)
延伸思考
- 跨数据集训练:如何将 BSD100 与 DIV2K(800 张高质图像)结合使用?
- 方案一:先 DIV2K 预训练,再 BSD100 微调
-
方案二:混合训练时调整采样比例(如 DIV2K:BSD100=4:1)
-
真实场景适配:BSD100 的 LR 图像是理想降采样结果,如何模拟手机拍摄的真实模糊?
- 添加高斯模糊核
-
引入 JPEG 压缩伪影
-
评估优化:当 PSNR 提升但视觉效果变差时,可能是什么原因?
- 过度平滑导致高频信息丢失
- 指标与人类视觉感知不一致
参考文献
正文完
