Skip to content

Commit 5f1007f

Browse files
author
vijayi
committed
Initial commit
1 parent 6e10787 commit 5f1007f

File tree

6 files changed

+189
-7
lines changed

6 files changed

+189
-7
lines changed
853 KB
Binary file not shown.

LICENSE.md/LICENSE.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Copyright (c) 2020, The MathWorks, Inc.
2-
All rights reserved.
3-
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4-
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5-
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
6-
3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.
7-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1+
Copyright (c) 2020, The MathWorks, Inc.
2+
All rights reserved.
3+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
6+
3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.
7+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
# **Brain MRI Age Classification Using Deep Learning**
3+
4+
This example shows how to work with an MRI brain image dataset and how to use transfer learning to modify and retrain ResNet-18, a pretrained convolutional neural network, to perform image classification on that dataset.
5+
6+
The MRI scans used in this example were obtained during a study \[1\] of social brain development conducted by researchers at the Massachussets Institute of Technology (MIT), and are available for download via the OpenNEURO platform:
7+
https://openneuro.org/datasets/ds000228/versions/1.1.0
8+
9+
This example works with the horizontal midslice images from the brain MRI scan volumes and shows how these images can be classified into 3 categories according to the chronological age of the participant:
10+
1. Participants Aged 3-5
11+
2. Participants Aged 7-12
12+
3. Participants older than 18, classified as Adults
13+
14+
![](images/overview.png)
15+
16+
This example works though multiple steps of a deep learning workflow:
17+
- _Exploring_ a public brain MRI image dataset
18+
- _Preparing_ the dataset for deep learning
19+
- _Training_ a deep learning model to perform chronological age classification
20+
- _Evaluating_ the trained model
21+
22+
## **Getting the Data**
23+
24+
The dataset is available for download via the OpenNEURO data sharing platform.
25+
26+
Steps:
27+
1. Download OpenNeuro dataset: https://openneuro.org/datasets/ds000228/versions/1.1.0
28+
2. Copy dataset folder to the code root folder.
29+
30+
## **Running the Code**
31+
32+
To run:
33+
1. Open `BrainMRIAgeClassificationUsingDeepLearning.mlx`
34+
2. Run `BrainMRIAgeClassificationUsingDeepLearning.mlx`
35+
36+
Requires:
37+
- [MATLAB](https://www.mathworks.com/products/matlab.html)
38+
- [Deep Learning Toolbox](https://www.mathworks.com/products/deep-learning.html)
39+
- [Image Processing Toolbox](https://www.mathworks.com/products/image.html)
40+
41+
42+
## **References**
43+
\[1\] Richardson, H., Lisandrelli, G., Riobueno-Naylor, A., & Saxe, R. (2018). Development of the social brain from age three to twelve years. Nature Communications, 9(1), 1027. https://www.nature.com/articles/s41467-018-03399-2
44+

images/datasplit.png

52.6 KB
Loading

images/overview.png

155 KB
Loading

prepare2DImageDataset.m

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
function exemplars = prepare2DImageDataset(srcFolder,dstFolder,augmentDataset,applySkullStripping)
2+
%PREPAREMRIAGECLASSIFICATIONDATASET Prepare 2D midslice image dataset from 3D brain volume dataset
3+
% OUTPUTS
4+
% exemplars: cell array of exemplar 2D midslice images (without skull-stripping or augmentation operations) as a reference, one per age class
5+
6+
arguments
7+
srcFolder (1,:) char % source folder location of 3D brain volumes, organized by participant
8+
dstFolder (1,:) char = '' % destination folder for 2D horizontal midslice images, organized by age class
9+
augmentDataset (1,1) logical = false % specify whether to apply offline data augmentation (a copy of image flipped 180 degrees).
10+
applySkullStripping (1,1) logical = false % specify whether to apply skull-stripping
11+
end
12+
13+
% Create classification image set folders
14+
if ~isempty(dstFolder)
15+
assert(~exist(dstFolder,'dir'));
16+
mkdir(dstFolder);
17+
end
18+
19+
% Load 3D image volumes into MATLAB workspace
20+
allFiles = dir(strcat(srcFolder,'\*\*_anat.nii.gz'));
21+
22+
fileDir = fullfile({allFiles.folder},{allFiles.name});
23+
24+
srcDir_3to5 = fileDir(1:65);
25+
srcDir_7to12 = fileDir(66:122);
26+
srcDir_Adults = fileDir(123:155);
27+
28+
%Load brain volumes into MATLAB workspace
29+
brainVolumes_3to5 = cellfun(@niftiread,srcDir_3to5,'UniformOutput',false);
30+
brainVolumes_7to12 = cellfun(@niftiread,srcDir_7to12,'UniformOutput',false);
31+
brainVolumes_Adults = cellfun(@niftiread,srcDir_Adults,'UniformOutput',false);
32+
33+
% Load skull stripping masks into MATLAB workspace
34+
if applySkullStripping
35+
allFiles = dir(strcat(srcFolder,'\*\*_analysis_mask.nii.gz'));
36+
fileDir = fullfile({allFiles.folder},{allFiles.name});
37+
38+
skullMaskDir_3to5 = fileDir(1:65);
39+
skullMaskDir_7to12 = fileDir(66:122);
40+
skullMaskDir_Adults = fileDir(123:155);
41+
42+
skullMask_3to5 = cellfun(@niftiread,skullMaskDir_3to5,'UniformOutput',false);
43+
skullMask_7to12 = cellfun(@niftiread,skullMaskDir_7to12,'UniformOutput',false);
44+
skullMask_Adults = cellfun(@niftiread,skullMaskDir_Adults,'UniformOutput',false);
45+
else
46+
skullMask_3to5 = [];
47+
skullMask_7to12 = [];
48+
skullMask_Adults = [];
49+
end
50+
51+
% Extract, normalize, and augment 2D image sets. Return exemplar data i
52+
%fileRoot = 'MidSlice_ImageSet\Preprocessed';
53+
exemplars = cell(3,1);
54+
exemplars{1} = prepare2DImageDataset_(brainVolumes_3to5,fullfile_(dstFolder,'\Ages3-5\'),augmentDataset,applySkullStripping, skullMask_3to5);
55+
exemplars{2} = prepare2DImageDataset_(brainVolumes_7to12,fullfile_(dstFolder,'\Ages7-12\'),augmentDataset,applySkullStripping, skullMask_7to12);
56+
exemplars{3} = prepare2DImageDataset_(brainVolumes_Adults,fullfile_(dstFolder,'\Adults\'),augmentDataset,applySkullStripping, skullMask_Adults);
57+
58+
59+
end
60+
61+
62+
% prepare2DImageDataset is a function that takes in the MRI image volume data for each label. It extracts the horizontal midslice of each MRI scan volume, applies normalization and other optional processing (skull stripping, augmentation), and saves the reduced 2D image dataset to a specified folder tree organized by label for downstream training, validation, and testing.
63+
% The function's processing options can be used to:
64+
% strip the skull from the 2D images (imType set to 'strip')
65+
% augment the dataset by saving added copies of each 2D image flipped by 180 degrees (imModify set to true)
66+
function exemplar = prepare2DImageDataset_(srcData,dstFolder,applyAugmentation,applySkullStripping,skullStrippingMask)
67+
68+
if ~isempty(dstFolder)
69+
assert(~exist(dstFolder,'dir'));
70+
mkdir(dstFolder);
71+
end
72+
73+
[~, ~, k, ~] = size(srcData{1});
74+
75+
% Extract horizontal mid-slice from each image volume
76+
mid_slices = cellfun(@squeeze,cellfun(@double,cellfun(@(x)x(:,:,round(k/2),1),srcData,'un',0),'UniformOutput',false),'UniformOutput',false);
77+
78+
% Include data from the preprocessed image that does not include the skull
79+
% This section only runs if you wish to 'strip' away the skull
80+
if applySkullStripping
81+
nii_strip_read = skullStrippingMask;
82+
mid_slices_unstrip = cellfun(@squeeze,cellfun(@double,cellfun(@(x)x(:,:,round(k/2),1),srcData,'un',0),'UniformOutput',false),'UniformOutput',false);
83+
mid_slices_strip = cellfun(@squeeze,cellfun(@double,cellfun(@(x)x(:,:,round(k/2),1),nii_strip_read,'un',0),'UniformOutput',false),'UniformOutput',false);
84+
mid_slices = cellfun(@immultiply,mid_slices_strip,mid_slices_unstrip,'UniformOutput',false);
85+
end
86+
87+
% Normalize the intensity of the images, and save then in an RGB format
88+
high = cellfun(@max,(cellfun(@max,mid_slices,'UniformOutput',false)));
89+
low = cellfun(@min,(cellfun(@min,mid_slices,'UniformOutput',false)));
90+
range = abs(high-low)+1;
91+
temp = num2cell(low);
92+
mid_slices = cellfun(@minus,mid_slices,temp,'UniformOutput',false);
93+
94+
range = arrayfun(@linspace,zeros(size(range)),ones(size(range)),range,'UniformOutput',false);
95+
map = cellfun(@(x) repmat(x',1,3),range,'UniformOutput',false);
96+
convert2img = cellfun(@ind2rgb, mid_slices,map,'UniformOutput',false);
97+
98+
avg_intensity = mean(cell2mat(cellfun(@imhist,convert2img,'UniformOutput',false)),2);
99+
100+
% Create a copy if the image and rorate the image by 180 degrees
101+
if applyAugmentation
102+
convert2img_2 = cellfun(@ind2rgb, cellfun(@(x)rot90(x,2),mid_slices,'UniformOutput',false),map,'UniformOutput',false);
103+
avg_intensity_2 = mean(cell2mat(cellfun(@imhist,convert2img_2,'UniformOutput',false)),2);
104+
end
105+
106+
% Save images in folders sorted by age range
107+
for i = 1:numel(mid_slices)
108+
109+
fileName = sprintf('image_%03d.png', i);
110+
outImg = histeq(convert2img{i},avg_intensity);
111+
112+
if ~isempty(dstFolder)
113+
imwrite(outImg,strcat(dstFolder,fileName),'mode','lossless');
114+
end
115+
116+
if i == 1
117+
exemplar = outImg;
118+
end
119+
120+
if applyAugmentation
121+
fileName_2 = sprintf('image2_%03d.png', i);
122+
outImg_2 = histeq(convert2img_2{i},avg_intensity_2);
123+
124+
if ~isempty(dstFolder)
125+
imwrite(outImg_2, strcat(dstFolder,fileName_2),'mode','lossless');
126+
end
127+
end
128+
end
129+
130+
end
131+
132+
function fname = fullfile_(dstFolder,varargin)
133+
if isempty(dstFolder)
134+
fname = [];
135+
else
136+
fname = fullfile(dstFolder,varargin{:});
137+
end
138+
end

0 commit comments

Comments
 (0)