文档

基于深度学习的三维脑肿瘤分割

这个例子展示了如何训练一个三维U-Net神经网络,并从三维医学图像中执行脑肿瘤的语义分割。

该示例展示了如何训练一个三维U-Net网络,并提供了一个预训练网络。如果您选择训练网络,强烈建议使用具有cuda功能、计算能力3.0或更高的NVIDIA™GPU(需要并行计算工具箱™)。

简介

语义分割涉及用类标记图像中的每个像素或三维体素。

这个例子说明了在磁共振成像(MRI)扫描中使用深度学习方法对脑肿瘤进行语义分割。它还展示了如何执行二进制分割,其中每个体素被标记为肿瘤或背景。

医学图像分割的一个挑战是数据中的类不平衡,这阻碍了训练时使用传统的交叉熵损失。这个例子通过使用加权多类Dice损失函数[4]来解决这个问题。对类进行加权有助于抵消较大区域对Dice分数的影响,使网络更容易学习如何分割较小的区域。

本例使用三维U-Net架构[1]进行脑肿瘤分割。U-Net是一种快速、高效、简单的网络,已成为语义分割领域的热点。

下载培训、验证和测试数据

本例使用BraTS数据集[2]。BraTS数据集包含脑肿瘤的MRI扫描,即胶质瘤,这是最常见的原发性脑恶性肿瘤。数据文件的大小为~7 GB。如果您不想下载BraTS数据集,请直接转到下载预训练的网络和样本测试集节。

创建一个目录来存储BraTS数据集。

imageDir = fullfile(tempdir,“小鬼”);如果~存在(imageDir“dir”mkdir (imageDir);结束

要下载BraTS数据,请转到医学细分十项全能网页,并按“下载资料”连结。下载“task01_braintumor .tar”文件[3]。方法指定的目录中解压缩TAR文件imageDir变量。当成功拉开拉链时,imageDir将包含一个名为Task01_BrainTumour它有三个子目录:imagesTrimagesTs,labelsTr

该数据集包含750个4-D卷,每个卷代表一组3-D图像。每个4-D体的大小为240 × 240 × 155 × 4,其中前三个维度对应3-D体图像的高度、宽度和深度。第四个维度对应不同的扫描方式。每个图像卷都有一个对应的像素标签。数据集分为484个训练卷和286个测试卷。

预处理训练和验证数据

为了更有效地训练三维U-Net网络,使用helper函数对MRI数据进行预处理preprocessBraTSdataset.该函数作为支持文件附加到示例中。万博1manbetx

helper函数执行以下操作:

  • 将数据裁剪到主要包含大脑和肿瘤的区域。裁剪数据可以减少数据的大小,同时保留每个MRI体积的最关键部分及其相应的标签。

  • 通过减去平均值并除以裁剪的大脑区域的标准偏差,将每个体积的每个模态独立归一化。

  • 将数据集分成训练集、验证集和测试集。

数据预处理大约需要30分钟才能完成。

sourceDataLoc = [imageDir filesep .“Task01_BrainTumour”];preprocessDataLoc = fullfile(tempdir,“小鬼”“preprocessedDataset”);preprocessBraTSdataset (preprocessDataLoc sourceDataLoc);

为训练和验证创建随机补丁提取数据存储

使用随机补丁提取数据存储将训练数据输入网络并验证训练进度。该数据存储从真实图像和相应的像素标签数据中提取随机补丁。补丁是一种常见的技术,用于在训练任意大的容量时防止内存耗尽

首先,将训练图像存储在imageDatastore.因为mat -文件格式是非标准图像格式,所以必须使用mat -文件读取器来读取图像数据。你可以使用辅助mat文件阅读器,matRead.该函数作为支持文件附加到示例中。万博1manbetx

volReader = @(x) matRead(x);volLoc = fullfile(preprocessDataLoc,“imagesTr”);volds = imageDatastore(volLoc,...“FileExtensions”“.mat”“ReadFcn”, volReader);

创建一个pixelLabelDatastore用于存储标签。

labelReader = @(x) matRead(x)lblLoc = fullfile(preprocessDataLoc,“labelsTr”);classNames = [“背景”“肿瘤”];pixelLabelID = [0 1];pxds = pixelLabelDatastore(lblLoc,classNames,pixelLabelID,...“FileExtensions”“.mat”“ReadFcn”, labelReader);

预览一个图像卷和标签。控件显示已标记的卷labelvolshow函数。通过设置背景标签的可见性使背景完全透明(1)0

Volume =预览(volds);标签=预览(pxds);图h = labelvolshow(label,volume(:,:,:,1));h.LabelVisibility(1) = 0;

创建一个randomPatchExtractionDatastore从图像数据存储和像素标签数据存储。指定64 × 64 × 64体素的补丁大小。指定“PatchesPerImage”在训练过程中,从每对卷和标签中抽取16个随机定位的补丁。指定一个小批大小为8。

patchSize = [64 64 64];patchPerImage = 16;miniBatchSize = 8;patchds = randompatchextracactiondatastore (volds,pxds,patchSize,...“PatchesPerImage”, patchPerImage);patchds。MiniBatchSize = MiniBatchSize;

扩充训练数据变换函数使用helper函数指定的自定义预处理操作augment3dPatch.的augment3dPatch函数随机旋转,反映训练数据,使训练更健壮。该函数作为支持文件附加到示例中。万博1manbetx

dsTrain = transform(patchds,@augment3dPatch);

创建一个randomPatchExtrationDatastore其中包含验证数据。您可以使用验证数据来评估网络是否随着时间的推移不断学习、欠拟合或过拟合。

volLocVal = fullfile(preprocessDataLoc,“imagesVal”);voldsVal = imageDatastore(volLocVal,...“FileExtensions”“.mat”“ReadFcn”, volReader);lblLocVal = fullfile(preprocessDataLoc,“labelsVal”);pxdsVal = pixelLabelDatastore(lblLocVal,classNames,pixelLabelID,...“FileExtensions”“.mat”“ReadFcn”, labelReader);dsVal = randompatchextracactiondatastore (voldsVal,pxdsVal,patchSize,...“PatchesPerImage”, patchPerImage);dsVal。MiniBatchSize = MiniBatchSize;

设置3-D U-Net图层

本例使用了3d U-Net网络[1]的变体。在U-Net中,在初始的卷积层序列中穿插最大池化层,依次降低输入图像的分辨率。这些层之后是一系列卷积层,其中点缀着上采样算子,依次增加输入图像的分辨率。U-Net的名字来源于这样一个事实,即网络可以画出一个像字母u一样的对称形状。这个例子修改了U-Net,在卷积中使用零填充,这样卷积的输入和输出就具有相同的大小。

这个例子使用来自深度学习工具箱™的层定义了3d U-Net,包括:

这个例子还定义了一个自定义的Dice损失层,命名为dicePixelClassification3dLayer,解决数据[4]中类不平衡的问题。该层作为支持文件附加到示例中。万博1manbetx有关更多信息,请参见定义自定义像素分类层与骰子损失

第一层,imageInput3dLayer,操作在大小为64 × 64 × 64体素的图像补丁上。

inputSize = [64 64 64 4];inputLayer = image3dInputLayer(inputSize,“归一化”“没有”“名字”“输入”);

图像输入层之后是三维U-Net收缩路径。压缩路径由三个编码器模块组成。每个编码器包含两个带有3 × 3 × 3滤波器的卷积层,将特征映射的数量增加一倍,然后使用reLu层进行非线性激活。第一个卷积之后是一个批处理归一化层。每个编码器以最大池化层结束,该层将每个维度的图像分辨率减半。

给所有层赋予唯一的名称。编码器中的层的名称以“en”开头,后面跟着编码器模块的索引。例如,“en1”表示第一个编码器模块。

numFiltersEncoder = [32 64;64 128;128 256);layers = [inputLayer];模块= 1:3 modtag = num2str(模块);encoderModule =[卷积3dlayer (3,numFiltersEncoder(模块,1),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”,[“en”modtag,“_conv1”]);batchNormalizationLayer (“名字”,[“en”modtag,“_bn”]);reluLayer (“名字”,[“en”modtag,“_relu1”]);convolution3dLayer (numFiltersEncoder(模块,2),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”,[“en”modtag,“_conv2”]);reluLayer (“名字”,[“en”modtag,“_relu2”]);maxPooling3dLayer (2“步”2,“填充”“相同”...“名字”,[“en”modtag,“_maxpool”]);];图层=[图层;encoderModule];结束

创建三维U-Net的扩展路径。扩展路径由四个解码器模块组成。所有解码器都包含两个带有3 × 3 × 3滤波器的卷积层,将特征映射的数量减少一半,然后使用reLu层进行非线性激活。前三个解码器以转置卷积层结束,该层将图像上采样2倍。最终的解码器包括一个卷积层,将每个体素的特征向量映射到类。

给所有层赋予唯一的名称。解码器中的层的名称以“de”开头,后面跟着解码器模块的索引。例如,“de4”表示第四个解码器模块。

numFiltersDecoder = [256 512;256 256;128 128;64 64);decoderModule4 = [convolution3dLayer(3,numFiltersDecoder(1,1),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de4_conv1”);reluLayer (“名字”“de4_relu1”);convolution3dLayer (numFiltersDecoder(1、2),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de4_conv2”);reluLayer (“名字”“de4_relu2”);transposedConv3dLayer (numFiltersDecoder(1、2),“步”2,...“名字”“de4_transconv”);];decoderModule3 = [convolution3dLayer(3,numFiltersDecoder(2,1),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de3_conv1”);reluLayer (“名字”“de3_relu1”);convolution3dLayer (numFiltersDecoder (2, 2),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de3_conv2”);reluLayer (“名字”“de3_relu2”);transposedConv3dLayer (numFiltersDecoder (2, 2),“步”2,...“名字”“de3_transconv”);];decoderModule2 = [convolution3dLayer(3,numFiltersDecoder(3,1),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de2_conv1”);reluLayer (“名字”“de2_relu1”);convolution3dLayer (numFiltersDecoder (3, 2),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de2_conv2”);reluLayer (“名字”“de2_relu2”);transposedConv3dLayer (numFiltersDecoder (3, 2),“步”2,...“名字”“de2_transconv”);];

最终的解码器包括一个卷积层,该层将每个体素的特征向量映射到两个类别(肿瘤和背景)中的每一个。自定义Dice像素分类层对损失函数进行加权,以增加小肿瘤区域对Dice评分的影响。

numLabels = 2;decoderModuleFinal = [convolution3dLayer(3,numFiltersDecoder(4,1),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de1_conv1”);reluLayer (“名字”“de1_relu1”);convolution3dLayer (numFiltersDecoder (4,2),...“填充”“相同”“WeightsInitializer”“narrow-normal”...“名字”“de1_conv2”);reluLayer (“名字”“de1_relu2”);numLabels convolution3dLayer (1,“名字”“convLast”);softmaxLayer (“名字”“softmax”);dicePixelClassification3dLayer (“输出”);];

将输入层和编码器模块与第四个解码器模块连接起来。将其他解码器模块作为单独的分支添加到图层图中。

图层=[图层;decoderModule4];lgraph = layerGraph(图层);lgraph = addLayers(lgraph,decoderModule3);lgraph = addLayers(lgraph,decoderModule2);lgraph = addLayers(lgraph,decoderModuleFinal);

使用连接层将每个编码器模块的第二层reLu层与解码器模块中大小相等的转置卷积层连接起来。将每个连接层的输出连接到解码器模块的第一个卷积层。

concat1 = concatenationLayer(4,2,“名字”“concat1”);lgraph = addLayers(lgraph,concat1);lgraph = connectLayers(“en1_relu2”“concat1 /三机一体”);lgraph = connectLayers(“de2_transconv”“concat1 / in2”);lgraph = connectLayers(“concat1 /出”“de1_conv1”);concat2 = concatenationLayer(4,2,“名字”“concat2”);lgraph = addLayers(lgraph,concat2);lgraph = connectLayers(“en2_relu2”“concat2 /三机一体”);lgraph = connectLayers(“de3_transconv”“concat2 / in2”);lgraph = connectLayers(“concat2 /出”“de2_conv1”);concat3 = concatenationLayer(4,2,“名字”“concat3”);lgraph = addLayers(lgraph,concat3);lgraph = connectLayers(“en3_relu2”“concat3 /三机一体”);lgraph = connectLayers(“de4_transconv”“concat3 / in2”);lgraph = connectLayers(“concat3 /出”“de3_conv1”);

或者,您可以使用createUnet3dhelper函数创建3-D U-Net层。该函数作为支持文件附加到示例中。万博1manbetx

lgraph = createUnet3d(inputSize);

绘制层图。

analyzeNetwork (lgraph)

指定培训项目

使用“adam”优化求解器训练网络。属性指定超参数设置trainingOptions函数。初始学习率设置为5e-4,并在训练期间逐渐降低。

选项= trainingOptions(“亚当”...“MaxEpochs”, 100,...“InitialLearnRate”5的军医,...“LearnRateSchedule”“分段”...“LearnRateDropPeriod”5,...“LearnRateDropFactor”, 0.95,...“ValidationData”dsVal,...“ValidationFrequency”, 400,...“阴谋”“训练进步”...“详细”假的,...“MiniBatchSize”, miniBatchSize);

下载预训练的网络和样本测试集

可选地,从BraTS数据集[3]下载预训练的3- d U-Net版本和五个样本测试卷及其对应的标签。预训练的模型和样本数据使您能够在测试数据上执行分割,而无需下载完整的数据集或等待网络训练。

trained3DUnet_url =“//www.tianjin-qmedu.com/万博1manbetxsupportfiles/vision/data/brainTumor3DUNet.mat”;sampleData_url =“//www.tianjin-qmedu.com/万博1manbetxsupportfiles/vision/data/sampleBraTSTestSet.tar.gz”;imageDir = fullfile(tempdir,“小鬼”);如果~存在(imageDir“dir”mkdir (imageDir);结束downloadTrained3DUnetSampleData (trained3DUnet_url sampleData_url imageDir);

培训网络

培训项和数据源配置完成后,您可以使用工具对3d U-Net网络进行培训trainNetwork函数。为了训练网络,设置doTraining参数真正的.强烈建议使用具有cuda功能、计算能力3.0或更高版本的NVIDIA™GPU进行培训。

如果你留着doTraining参数在下面的代码中为,则示例返回预训练的3d U-Net网络。

注意:在NVIDIA™Titan X上进行培训大约需要60个小时,根据GPU硬件的不同,培训时间可能会更长。

doTraining = false;如果doTraining modelDateTime = datestr(现在,“dd-mmm-yyyy-HH-MM-SS”);[net,info] = trainNetwork(dsTrain,lgraph,options);保存([“trained3DUNet -”modelDateTime的时代,num2str (maxEpochs)“.mat”),“净”);其他的负载(fullfile (imageDir“trained3DUNet”“brainTumor3DUNet.mat”));结束

你现在可以使用U-Net从语义上分割脑瘤。

对测试数据进行分割

选择包含实际数据量和标签的测试数据源。如果你留着useFullTestSet参数在下面的代码中为,则该示例使用5个卷进行测试。如果你设置useFullTestSet参数真正的,则该示例使用从完整数据集中选择的55个测试图像。

useFullTestSet = false;如果useFullTestSet volLocTest = fullfile(preprocessDataLoc,“imagesTest”);lblLocTest = fullfile(preprocessDataLoc,“labelsTest”);其他的volLocTest = fullfile(imageDir,“sampleBraTSTestSet”“imagesTest”);lblLocTest = fullfile(imageDir,“sampleBraTSTestSet”“labelsTest”);classNames = [“背景”“肿瘤”];pixelLabelID = [0 1];结束

使用helper函数将图像和标签的中心部分裁剪为128 × 128 × 128的体素大小centerCropMatReader.该函数作为支持文件附加到示例中。万博1manbetx的voldsTest变量存储地面真值测试图像。的pxdsTest变量存储基本真值标签。

windowSize = [128 128 128];volReader = @(x) centerCropMatReader(x,windowSize);labelReader = @(x) centerCropMatReader(x,windowSize);voldsTest = imageDatastore(volLocTest,...“FileExtensions”“.mat”“ReadFcn”, volReader);pxdsTest = pixelLabelDatastore(lblLocTest,classNames,pixelLabelID,...“FileExtensions”“.mat”“ReadFcn”, labelReader);

对于每个测试图像,将ground truth图像卷和标签添加到单元格数组中。使用训练过的网络semanticseg函数预测每个测试卷的标签。

在执行分割后,对预测的标签进行后处理,将非大脑体素标记为1,对应于背景。使用测试图像来确定哪些体素不属于大脑。属性删除岛和填充孔,也可以清除预测标签medfilt3函数。medfilt3不支持分类数据,因万博1manbetx此将像素标签id转换为uint8在计算之前。然后,将过滤后的标签转换回类别数据类型,指定原始像素标签id和类名。

id = 1;hasdata (voldsTest) disp ([“处理测试量”num2str(id)]) groundTruthLabels{id} = read(pxdsTest);vol{id} = read(voldsTest);tempSeg = semanticseg(vol{id},net);从测试图像中获取非大脑区域掩码。volMask = vol{id}(:,:,:,1)==0;%将预测标签的非脑区设置为背景。tempSeg(volMask) = classNames(1);对预测的标签进行中值过滤。tempSeg = medfilt3(uint8(tempSeg)-1);将过滤后的标签转换为类别。tempSeg = categorical(tempSeg,pixelLabelID,classNames);predictedLabels{id} = tempSeg;id = id + 1;结束
处理测试卷1处理测试卷2处理测试卷3处理测试卷4处理测试卷5

比较实际情况和网络预测

选择一个测试图像来评估语义分割的准确性。从4-D体积数据中提取第一个模态,并将该3-D体积存储在变量中vol3d

volId = 2;vol3d = vol{volId}(:,:,:,1);

以蒙太奇的方式显示地面真相的中心切片和沿深度方向预测的标签。

zID = size(vol3d,3)/2;zSliceGT = labeloverlay(vol3d(:,:,zID),groundTruthLabels{volId}(:,:,zID));zSlicePred = labeloverlay(vol3d(:,:,zID),predictedLabels{volId}(:,:,zID));图的标题(“标记地面真相(左)vs网络预测(右)”)蒙太奇({zSliceGT; zSlicePred},“大小”(1 - 2),“BorderSize”5)

控件显示地面真值标记的音量labelvolshow函数。通过设置背景标签的可见性使背景完全透明(1)0.因为肿瘤在脑组织内,所以要使部分大脑体素透明,这样肿瘤就可见了。要使某些大脑体素透明,请将容量阈值指定为范围[0,1]中的数字。所有低于此阈值的标准化体积强度都是完全透明的。本例将容量阈值设置为小于1,以便一些大脑像素仍然可见,从而为大脑内肿瘤的空间位置提供上下文。

figure h1 = labelvolshow(groundTruthLabels{volId},vol3d);h1.LabelVisibility(1) = 0;h1。VolumeThreshold = 0.68;

对于相同的音量,显示预测标签。

图h2 = labelvolshow(predictedLabels{volId},vol3d);h2.LabelVisibility(1) = 0;h2。VolumeThreshold = 0.68;

此图像显示了在整个卷中按顺序显示切片的结果。

量化分割精度

测量分割精度使用骰子函数。该函数计算预测和实际真相分割之间的Dice相似系数。

diceResult = 0(长度(voldsTest.Files),2);j = 1:长度(vol) diceResult(j,:) =骰子(groundTruthLabels{j},predictedLabels{j});结束

计算整个测试卷集的平均Dice分数。

meanDiceBackground = mean(diceResult(:,1));disp ([“背景的平均骰子分数”num2str (j),...' test volumes = 'num2str (meanDiceBackground)])
5个测试卷的背景平均Dice分数= 0.99341
meandictumor = mean(diceResult(:,2));disp ([“肿瘤的平均Dice分数”num2str (j),...' test volumes = 'num2str (meanDiceTumor)])
5个试验体积肿瘤的平均Dice评分= 0.85204

该图显示了箱线图它可以在五个样本测试卷的集合中可视化骰子分数的统计数据。图中的红线显示了类的中位数Dice值。蓝色框的上界和下界分别表示第25百分位和第75百分位。黑须延伸到不被认为是异常值的最极端数据点。

如果您有统计和机器学习工具箱™,那么您可以使用箱线图函数可以可视化所有测试卷上的骰子分数的统计信息。要创建箱线图,设置createBoxplot参数真正的

createBoxplot = false;如果createBoxplot figure boxplot(diceResult)“测试集骰子精度”xticklabels(classNames)“骰子系数”结束

总结

这个例子展示了如何创建和训练一个3-D U-Net网络来使用BraTS数据集执行3-D脑肿瘤分割。训练网络的步骤包括:

在训练3-D U-Net网络或加载预训练的3-D U-Net网络后,该示例执行测试数据集的语义分割。该示例通过与地面真相分割的可视化比较以及测量预测和地面真相分割之间的Dice相似系数来评估预测分割。

参考文献

[1] Çiçek, Ö。,A. Abdulkadir, S. S. Lienkamp, T. Brox, and O. Ronneberger. "3D U-Net: Learning Dense Volumetric Segmentation from Sparse Annotation." In医学图像计算与计算机辅助干预国际会议论文集.希腊雅典,2016年10月,第424-432页。

Isensee, F., P. Kickingereder, W. Wick, M. Bendszus和K. H. Maier-Hein。“脑肿瘤分割和放射组学生存预测:对BRATS 2017挑战的贡献。”在国际MICCAI脑损伤研讨会论文集.加拿大魁北克市,2017年9月,第287-297页。

[3]“脑瘤”。医学细分十项全能。http://medicaldecathlon.com/

BraTS数据集由医疗十项全能提供CC-BY-SA 4.0许可证。所有保证和陈述均被放弃;详细信息请参见license。中链接的数据集下载预训练的网络和样本测试集部分的示例。将修改后的样本数据集裁剪为主要包含大脑和肿瘤的区域,通过减去裁剪后的大脑区域的平均值并除以其标准差,将每个通道独立归一化。

[4]苏德,C. H.,李伟文,T.韦考特伦,S.乌尔瑟林和M. J.卡多佐。“广义骰子重叠作为高度不平衡分割的深度学习损失函数。”医学图像分析中的深度学习和临床决策支持的多模态学习:第三届国际研讨会万博1manbetx.加拿大魁北克市,2017年9月,第240-248页。

另请参阅

||||||

相关的例子

更多关于