LUNA16肺结节数据集
本文介绍了LUNA16肺结节检测数据集的预处理方法,包括格式转换和标注处理。首先将原始.mhd/.zraw格式CT图像转换为.png格式,并生成适用于目标检测的json/xml/yolo格式标签。进一步针对分割任务,使用LabelMe对结节进行精细掩膜标注,提供转换为YOLO实例分割格式和mask格式的方法,支持UNet等模型的训练。预处理后的数据集包含888个CT样本的1186个结节标注,涵盖不
肺结节自动检测在早期肺癌筛查中具有重要意义,LUNA16(LUng Nodule Analysis 2016)数据集是该任务中广泛使用的标准数据集之一。本文将介绍 LUNA16 数据集的基本信息、数据格式转换流程以及如何准备训练数据,帮助初学者快速上手医学图像处理任务。
一、LUNA16 数据集简介
LUNA16 是一个从 LIDC-IDRI 数据集中提取的子集,主要用于肺结节自动检测任务。数据集中包含了 888 个低剂量胸部 CT 扫描样本,共有1186个结节,直径从3.170毫米到27.442毫米不等,涵盖了不同大小的肺部结节。LUNA16数据集中的图像采用.mhd和.zraw格式,这些格式在医学影像处理领域较为常见,但由于其特殊性,直接处理和可视化存在一定困难。
二、Lung16目标检测数据集
为简化图像的读取与处理,本文对原始的 .mhd 与 .zraw 格式图像进行了预处理,将所有 CT 图像切片转换为常见的 .png 格式,同时根据官方标注信息生成了适用于深度学习训练的标签文件,**标签包含了 json、xml、yolo三种格式。**旨在支持如YOLO、Faster R-CNN、SSD等主流目标检测算法的训练与评估。

为了更直观地了解处理后的数据效果,下面展示部分转换后的图像切片及其对应的肺结节标注框。每张图像均来源于原始的 CT 切片,经过窗口调节和格式转换处理,最终保存为 .png 格式,并在对应位置绘制结节的边界框。



三、LUNA16目标分割数据集
3.1 原始标注
在完成目标检测数据集构建的基础上,本文进一步对肺结节进行了精细化的掩膜标注(mask annotation),以支持更高级的语义分割与实例分割任务。
具体而言,本文以目标检测结果中的边界框为参考,结合原始 CT 图像内容,使用 LabelMe 软件对每一个肺结节区域进行逐个手动标注,精确描绘其轮廓,生成对应的 JSON 格式标注文件。每个 JSON 文件中包含了结节边界的多边形坐标信息,可用于自动生成二值掩膜图或直接用于实例分割模型训练。
如下图所示,在每张图像中,我们严格遵循每个结节的实际形态进行轮廓描绘,确保掩膜区域与实际病灶最大程度吻合。这种高质量的人工标注为分割模型提供了可靠的监督信号,有助于提升模型对细小或边缘模糊结节的识别能力。


3.2 yolo 格式
为了支持 YOLO 系列实例分割模型(如 YOLOv8-seg)的训练,本文提供了将 LabelMe 生成的 JSON 标注文件转换为 YOLO 实例分割格式 的转换代码。该过程的核心在于:提取 JSON 文件中的多边形坐标点,并将其按照图像尺寸进行归一化处理,以满足 YOLO 格式对坐标规范的要求。代码如下所示:
import json
import os
class_dict = {
"pulmonary_nodule": 0
}
def translate_info(label_json, label_txt):
# 检查json文件是否存在
assert os.path.exists(label_json), "file:{} not exist...".format(label_json)
# read json
with open(label_json, "r") as f1:
data = json.load(f1)
img_height = data['imageHeight']
img_width = data['imageWidth']
object_num = len(data['shapes'])
with open(label_txt, "w") as f:
for index in range(object_num):
seg_label = []
# 获取每个object的类别信息和关键点信息
class_name = data['shapes'][index]['label']
class_index = class_dict[class_name] # 目标id从0开始
seg_label.append(class_index)
seg_points = data['shapes'][index]['points']
for point in seg_points:
point_x = round(point[0] / img_width, 6)
point_y = round(point[1] / img_height, 6)
seg_label.append(point_x)
seg_label.append(point_y)
info = [str(i) for i in seg_label]
f.write(" ".join(info) + "\n")
def main():
label_json_path = r"./data/labels_json"
label_txt_path = r"./data/labels_yolo"
label_list = os.listdir(label_json_path)
label_list = [label for label in label_list if label.endswith('.json')]
for label_name in label_list:
label_name = label_name.split(".json")[0]
label_xml = os.path.join(label_json_path, label_name + ".json")
label_txt = os.path.join(label_txt_path, label_name + ".txt")
translate_info(label_xml, label_txt)
if __name__ == "__main__":
main()
3.3 mask 格式
为了支持 UNet 及其变体(如 UNet++、Attention-UNet 等) 等语义分割模型的训练,本文提供了将 LabelMe 格式的 JSON 标注文件转换为 mask 标签图 的方法。转换过程中,依据 JSON 文件中每个结节的多边形轮廓信息,在与原图尺寸一致的空白图像上绘制填充区域,生成对应的 mask 图像。
在生成的 mask 中,背景区域的像素值为 0,肺结节区域像素值为1,支持多实例分割任务的需求。所有 mask 标签与原始图像保持命名一致,便于在训练过程中进行自动匹配与加载。
import cv2
import json
import numpy as np
import os
class_dict = {
"pulmonary_nodule": 1
}
def json_to_mask(image_path, json_path, save_mask_path):
# 读取 JSON 文件
with open(json_path, mode='r', encoding="utf-8") as f:
configs = json.load(f)
# 获取图像尺寸
shapes = configs["shapes"]
image = cv2.imread(image_path)
imageHeight, imageWidth = image.shape[:2]
# 创建空白图像用于生成掩码
mask = np.zeros((imageHeight, imageWidth), np.uint8)
# 绘制轮廓,将所有有标注的区域填充为 对应的数值
for shape in shapes:
label_name = shape["label"]
points = np.array(shape["points"], dtype=np.int32)
cv2.drawContours(mask, [points], -1, class_dict[label_name], -1) # 255 表示白色,-1 表示填充
# 保存生成的掩码图像
cv2.imwrite(save_mask_path, mask)
return mask
if __name__ == "__main__":
save_mask_root = r'./labels_mask' # 保存mask图路径
json_root = r'./labels_json' # 读取json路径
image_root = r'./images' # 原始图像
# 确保保存目录存在
os.makedirs(save_mask_root, exist_ok=True)
# 遍历 JSON 文件并生成掩码
for file in os.listdir(json_root):
name, ext = os.path.splitext(file)
image_path = os.path.join(image_root, f"{name}.png")
save_mask_path = os.path.join(save_mask_root, f"{name}.png")
json_path = os.path.join(json_root, file)
# 检查图像和 JSON 文件是否存在
if os.path.exists(image_path) and os.path.exists(json_path):
json_to_mask(image_path, json_path, save_mask_path)
基于上述处理流程,LUNA16 分割数据集已完成图像和标签的标准化转换,将统一提供如下内容:
- 经过预处理并转换为
.png格式的 CT 图像; - 对应的 三种类型的标注文件,包括:
- YOLO 格式(用于yolo系列的实例分割);
- Mask 图像格式(用于 UNet 系列分割模型);
- LabelMe 原始 JSON 格式(便于可视化与进一步编辑)。
关于该系统涉及到的完整源码、UI界面代码、数据集、训练代码、训练好的模型、测试图片视频等相关文件,均已打包上传,感兴趣的小伙伴可以通过下载链接自行获取。
好了,这篇文章就介绍到这里,喜欢的小伙伴感谢给点个赞和关注,更多精彩内容持续更新~~
关于本篇文章大家有任何建议或意见,欢迎在评论区留言交流!
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐




所有评论(0)