第四章 公开数据集介绍:Cell Image Library、ISBI 等

做细胞分类,最头疼的往往不是模型怎么搭,而是数据从哪来。我刚入行那会儿,自己拍了几百张显微图像,结果标签质量参差不齐,折腾一个月效果还不如人家公开数据集跑出来的 baseline。从那以后,我养成了习惯:先看看有没有成熟的数据集能用。

这一章我挑几个在学界和工业界都常用的公开数据集,结合我踩过的坑,带你快速上手。你想想看,与其自己从头标注几千张细胞图,不如站在前人的肩膀上——但前提是,你得知道哪个肩膀更靠谱。

4.1 Cell Image Library (CIL)

CIL 是美国细胞生物学学会维护的在线资源库,收录了超过 30 万张显微图像,涵盖各种细胞类型、染色方式和成像模态。它的最大优点是数据集结构统一,每张图都附有元数据(细胞系、荧光标记、缩放比例等)。

我比较常用的一个子集是 CIL 的“Cell Classification Benchmark”,大概 2000 张 HeLa 细胞的明场 + 荧光双通道图像,分辨率 1024×1024,标注了细胞核和细胞质的分割掩膜。

个人经验:CIL 提供了 REST API,可以按条件检索。但要注意,部分图像是 16 位 TIFF,读取时记得归一化到 0-255,不然模型训练 loss 直接炸掉。

如果你想用 Python 快速下载,可以参考下面这段脚本。注意 URL 我用了占位符,实际使用时替换成 CIL 的 API endpoint 就行。

import requests
import tifffile as tiff
from io import BytesIO

# 假设已获取 image_id 列表
image_ids = ['CIL_10001', 'CIL_10002']
base_url = 'https://api.cellimagelibrary.org/image/'

for img_id in image_ids:
    resp = requests.get(f'{base_url}{img_id}/download')
    if resp.status_code == 200:
        img_data = tiff.imread(BytesIO(resp.content))
        # 归一化到 [0,1]
        img_norm = (img_data - img_data.min()) / (img_data.max() - img_data.min())
        print(f'{img_id} downloaded, shape: {img_norm.shape}')

4.2 ISBI 细胞分割挑战数据集

ISBI(国际生物医学成像研讨会)每年都会组织分割挑战,留下的数据集是实打实的“黄金标准”。其中最经典的是 DIC-C2DH-HeLa —— 用微分干涉差显微镜拍的 HeLa 细胞序列,每帧都有像素级标注。

这个数据集的特点是:

  • 图像尺寸 1024×1024,时序长度 100 帧左右
  • 细胞形态多变,分裂和凋亡案例丰富
  • 标注仅包含细胞边界,不区分细胞质与细胞核

我曾经用它训练分割模型时发现一件怪事:验证集 Dice 很高,但预测结果里总有细碎的假阳性。折腾两天才意识到——原图的对比度在空间上分布不均,边缘细胞偏暗。后来加了局部对比度归一化,问题才解决。

避坑:ISBI 数据集通常是 TIFF 堆栈或 HDF5 格式。不要直接扔进 OpenCV 的 imread 里,它只能读前几帧。用 tifffile 或 h5py 才是正解。
import tifffile as tiff
import numpy as np

# 读取 100 帧序列
stack = tiff.imread('DIC-C2DH-HeLa.tif')
print(f'Volume shape: {stack.shape}')  # (100, 1024, 1024)

# 局部对比度归一化
from skimage.exposure import equalize_adapthist
stack_norm = np.array([equalize_adapthist(frame) for frame in stack])

4.3 其他常用数据集一览

除了上面两个,还有几个数据集我经常拿来当补充测试集。下面这个表帮你快速对比:

数据集细胞类型图像数量分辨率标注内容
BBBC (Broad Bioimage Benchmark Collection)多种(U2OS, HeLa)1000+512×512 ~ 2048×2048细胞核、细胞质轮廓
MoNuSeg人组织切片细胞核44 张全切片1000×1000 左右核分割多边形
Cell Tracking Challenge多种(荧光、明场)50+ 序列VGA ~ 4K分割 + 轨迹
LIVECell活细胞相位对比5000+ 已分割1280×1024细胞实例分割掩膜
我的建议:初学者先从 BBBC 入手,它的数据格式最规整,标注质量也最高。
BBBC 的下载地址在 https://bbbc.broadinstitute.org/,每个子集都有独立的 DOI,引用写论文很方便。

4.4 数据下载与预处理最佳实践

拿到公开数据集之后,第一件事不是直接训练,而是按以下步骤处理:

  1. 统一格式:所有图像转成 .png 或 .npy,避免 TIFF 的压缩差异。
  2. 尺寸对齐:用插值或 padding 缩放到 512×512,节省显存。
  3. 归一化:强度到 [0,1] 或 z-score,保持输入分布一致。
  4. 划分策略:按细胞系或实验批次划分,不要所有数据混洗——否则你会在验证集上“作弊”。
  5. 存储优化:打成 HDF5 或 TFRecord,减少小文件 IO 时间。

下面是一个统一的预处理脚本骨架,我把常用的参数都写在配置里:

# config.yaml
dataset:
  name: "BBBC002"
  image_dir: "./raw"
  output_dir: "./processed"
  target_size: [512, 512]
  normalization: "minmax"   # minmax / zscore
  train_ratio: 0.7
  val_ratio: 0.15
  test_ratio: 0.15
# preprocess.py
import cv2, yaml, numpy as np, h5py
from glob import glob
from sklearn.model_selection import train_test_split

with open('config.yaml') as f:
    cfg = yaml.safe_load(f)

imgs = sorted(glob(f"{cfg['image_dir']}/*.tif"))
labels = sorted(glob(f"{cfg['image_dir']}/*_mask.tif"))

# 按文件名分组,确保图像-掩膜对应
pairs = list(zip(imgs, labels))
train_pairs, val_pairs = train_test_split(
    pairs, test_size=cfg['val_ratio'] + cfg['test_ratio'], random_state=42
)
# 再分 val 和 test
val_pairs, test_pairs = train_test_split(val_pairs, test_size=0.5, random_state=42)

def process(pair_list, out_h5):
    with h5py.File(out_h5, 'w') as f:
        for i, (img_path, mask_path) in enumerate(pair_list):
            img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
            mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
            img = cv2.resize(img, cfg['target_size'])
            mask = cv2.resize(mask, cfg['target_size'], interpolation=cv2.INTER_NEAREST)
            if cfg['normalization'] == 'minmax':
                img = (img - img.min()) / (img.max() - img.min() + 1e-8)
            f.create_dataset(f'img_{i}', data=img)
            f.create_dataset(f'mask_{i}', data=mask)

process(train_pairs, 'train.h5')
process(val_pairs, 'val.h5')
process(test_pairs, 'test.h5')

4.5 本章核心框架:从数据集到分类模型

为了让你对整个流程有个宏观认识,我画了一张图。从数据集选择到特征提取,再到分类训练——每一步的输入输出都标清楚了。

公开数据集 → 分类模型构建流程 Cell Image Library ISBI 分割挑战 BBBC / 其他 数据下载与解析 预处理(归一化/增强) 特征提取(手工/CNN) 分类模型训练与评估 注意 数据集划分时不要 混洗不同实验批次 否则模型会过拟合

图里我用三种颜色代表不同数据源,中间两条虚线表示你可以选择直接从 CIL 下载并一路走到预处理。实际操作时,我建议先在 BBBC 上跑通完整 pipeline,再去碰 ISBI 的多时序数据——因为时序数据多了时间维,踩坑概率翻倍。

核心思路:公开数据集的价值在于“可复现”和“可比较”。用一套固定的预处理流程,多数据集交叉验证,才能证明你模型的泛化能力。

嗯,数据集这块就聊这么多。下面前人的坑我已经替你们填平了一部分,具体怎么用,还要看你的任务需求。记住:数据质量永远比模型结构重要。