Skip to content

Commit ea79d5f

Browse files
authored
Updated to R2024b
1 parent 5064396 commit ea79d5f

5 files changed

+215
-0
lines changed
1.44 MB
Binary file not shown.

LICENSE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Copyright (c) 2025, The MathWorks, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
2+
3+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
4+
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.
5+
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. 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: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[![Open in MATLAB Online](https://www.mathworks.com/images/responsive/global/open-in-matlab-online.svg)](https://matlab.mathworks.com/open/github/v1?repo=MathWorks-Teaching-Resources/Brain-MRI-Age-Classification-using-Deep-Learning)
2+
3+
# **Brain MRI Age Classification using Deep Learning (Course Integration Version)**
4+
5+
This exercise has been modified from the [original example](https://www.mathworks.com/matlabcentral/fileexchange/74941-brain-mri-age-classification-using-deep-learning) in order to be able to integrate it into course/s at higher education institutions.
6+
7+
It 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. The MRI scans used in this example were obtained during a study [1] of social brain development conducted by researchers at the Massachusetts Institute of Technology (MIT), and are available for download via the OpenNEURO platform: https://openneuro.org/datasets/ds000228/versions/1.1.0
8+
9+
10+
## Concept covered
11+
- Teaching end-to-end AI workflow for image classification
12+
- Applying transfer learning to a real-world data
13+
- Modifying a pre-trained network interactively and programmatically
14+
- Training the modified network to classify MRI images
15+
- Evaluating the model
16+
- Understanding network predictions using occlusion sensitivity maps
17+
18+
## Suggested Audience
19+
Instructors teaching any course in neuroscience and/or bio-medical disciplines which uses MRI data. The exercises can be used with students who have very little programming knowledge (use DND version) or with students who are familiar with programming (use non-DND version).
20+
21+
## Time
22+
The exercise can be run within 30-45 minutes.
23+
24+
## How to Use
25+
The package contains an interactive, app-based exercise (using Deep Network Designer=DND). it consist of a working exercise where parts of the code have to be filled by students. The exercise is self-explanatory and contain all information required to execute it.
26+
the app-based workflowis suitable even if students have very little programming knowledge. The programmatic workflow is also included for ease of understanding.
27+
28+
The exercise can be used as part of a course/module/lecture or as self-directed and self-paced exercise/homework/assignment.
29+
30+
The package contains a small subset of the original dataset. Using the original dataset (20+GB) would result in longer run times.
31+
32+
The solution files are available upon instructor request. If you would like to request solutions or have a question, contact the <a href="mailto:[email protected]">MathWorks online teaching team.</a>
33+
34+
35+
## Products:
36+
- [MATLAB®](https://www.mathworks.com/products/matlab.html)
37+
- [Deep Learning Toolbox™](https://www.mathworks.com/products/deep-learning.html)
38+
- [Image Processing Toolbox™](https://www.mathworks.com/products/image.html)
39+
40+
## Release last tested
41+
R2024b
42+
43+
## References
44+
\[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://doi.org/10.1038/s41467-018-03399-2
45+
46+
Copyright 2025 The MathWorks, Inc.
47+
48+

SECURITY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Reporting Security Vulnerabilities
2+
3+
If you believe you have discovered a security vulnerability, please report it to
4+
[[email protected]](mailto:[email protected]). Please see
5+
[MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html)
6+
for additional information.

prepare2DImageDataset.m

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
function [exemplars, dstPath] = prepare2DImageDataset(srcPath,dstPath,augmentDataset,applySkullStripping)
2+
%PREPARE2DIMAGEDATASET Prepare 2D midslice image dataset folders from 3D brain volume dataset folders
3+
%
4+
% OUTPUTS
5+
% exemplars: cell array of exemplar 2D midslice images (without skull-stripping or augmentation operations) as a reference, one per age class
6+
%
7+
% USAGE
8+
% exemplars = prepare2DImageDataset(srcPath): returns exemplar images for each class without preparing 2D image dataset folder
9+
% prepare2DImageDataset(srcPath,dstPath, ...): creates 2D midslice image dataset folder in specified dstPath
10+
%
11+
12+
arguments
13+
srcPath (1,:) char % source folder location of 3D brain volumes, organized by participant folders
14+
dstPath (1,:) char = '' % destination folder for 2D axial midslice images, organized by age class folders
15+
augmentDataset (1,1) logical = false % specify whether to apply offline data augmentation (a copy of image flipped 180 degrees).
16+
applySkullStripping (1,1) logical = false % specify whether to apply skull-stripping
17+
end
18+
19+
% Create classification image set folders
20+
if ~isempty(dstPath)
21+
i = 1;
22+
t = dstPath;
23+
while exist(t,'dir')
24+
t = dstPath+"_"+i;
25+
i = i+1;
26+
end
27+
dstPath = i;
28+
assert(~exist(dstPath,'dir'));
29+
mkdir(dstPath);
30+
end
31+
32+
% Load 3D image volumes into MATLAB workspace
33+
allFiles = dir(fullfile(srcPath,'*','*_anat.nii.gz'));
34+
35+
fileDir = fullfile({allFiles.folder},{allFiles.name});
36+
37+
srcDir_3to5 = fileDir(1:65);
38+
srcDir_7to12 = fileDir(66:122);
39+
srcDir_Adults = fileDir(123:155);
40+
41+
% Load brain volumes into MATLAB workspace
42+
brainVolumes_3to5 = cellfun(@niftiread,srcDir_3to5,'UniformOutput',false);
43+
brainVolumes_7to12 = cellfun(@niftiread,srcDir_7to12,'UniformOutput',false);
44+
brainVolumes_Adults = cellfun(@niftiread,srcDir_Adults,'UniformOutput',false);
45+
46+
% Load skull stripping masks into MATLAB workspace
47+
if applySkullStripping
48+
allFiles = dir(fullfile(srcPath,'*','*_analysis_mask.nii.gz'));
49+
fileDir = fullfile({allFiles.folder},{allFiles.name});
50+
51+
skullMaskDir_3to5 = fileDir(1:65);
52+
skullMaskDir_7to12 = fileDir(66:122);
53+
skullMaskDir_Adults = fileDir(123:155);
54+
55+
skullMask_3to5 = cellfun(@niftiread,skullMaskDir_3to5,'UniformOutput',false);
56+
skullMask_7to12 = cellfun(@niftiread,skullMaskDir_7to12,'UniformOutput',false);
57+
skullMask_Adults = cellfun(@niftiread,skullMaskDir_Adults,'UniformOutput',false);
58+
else
59+
skullMask_3to5 = [];
60+
skullMask_7to12 = [];
61+
skullMask_Adults = [];
62+
end
63+
64+
% Call the helper function prepare2DImageDataset_ for the set of
65+
% participant folders in each age group. Obtain an exemplar image for each
66+
% age group. If a destination folder is supplied, this helper extracts and
67+
% normalizes 2D image sets, with skull-stripping and augmentation
68+
% optionally applied.
69+
exemplars = cell(3,1);
70+
exemplars{1} = prepare2DImageDataset_(brainVolumes_3to5,fullfile_(dstPath,'Ages3-5'),augmentDataset,applySkullStripping, skullMask_3to5);
71+
exemplars{2} = prepare2DImageDataset_(brainVolumes_7to12,fullfile_(dstPath,'Ages7-12'),augmentDataset,applySkullStripping, skullMask_7to12);
72+
exemplars{3} = prepare2DImageDataset_(brainVolumes_Adults,fullfile_(dstPath,'Adults'),augmentDataset,applySkullStripping, skullMask_Adults);
73+
74+
75+
end
76+
77+
% Helper function prepare2DImageDataset_ reads from a set (cell array) of
78+
% source folders containing participant 3D volume data. It computes 2D
79+
% image extraction, normalization, and optional processing as described
80+
% above. It returns a single 2D image exemplar and writes the computed 2D
81+
% image files to a destination folder (if specified).
82+
function exemplar = prepare2DImageDataset_(srcFolders,dstFolder,applyAugmentation,applySkullStripping,skullStrippingMask)
83+
84+
if ~isempty(dstFolder)
85+
assert(~exist(dstFolder,'dir'));
86+
mkdir(dstFolder);
87+
end
88+
89+
[~, ~, k, ~] = size(srcFolders{1});
90+
91+
% Extract axial mid-slice from each image volume
92+
mid_slices = cellfun(@squeeze,cellfun(@double,cellfun(@(x)x(:,:,round(k/2),1),srcFolders,'un',0),'UniformOutput',false),'UniformOutput',false);
93+
94+
% Include data from the preprocessed image that does not include the skull
95+
% This section only runs if you wish to 'strip' away the skull
96+
if applySkullStripping
97+
nii_strip_read = skullStrippingMask;
98+
mid_slices_unstrip = cellfun(@squeeze,cellfun(@double,cellfun(@(x)x(:,:,round(k/2),1),srcFolders,'un',0),'UniformOutput',false),'UniformOutput',false);
99+
mid_slices_strip = cellfun(@squeeze,cellfun(@double,cellfun(@(x)x(:,:,round(k/2),1),nii_strip_read,'un',0),'UniformOutput',false),'UniformOutput',false);
100+
mid_slices = cellfun(@immultiply,mid_slices_strip,mid_slices_unstrip,'UniformOutput',false);
101+
end
102+
103+
% Normalize the intensity of the images, and save then in an RGB format
104+
high = cellfun(@max,(cellfun(@max,mid_slices,'UniformOutput',false)));
105+
low = cellfun(@min,(cellfun(@min,mid_slices,'UniformOutput',false)));
106+
range = abs(high-low)+1;
107+
temp = num2cell(low);
108+
mid_slices = cellfun(@minus,mid_slices,temp,'UniformOutput',false);
109+
110+
range = arrayfun(@linspace,zeros(size(range)),ones(size(range)),range,'UniformOutput',false);
111+
map = cellfun(@(x) repmat(x',1,3),range,'UniformOutput',false);
112+
convert2img = cellfun(@ind2rgb, mid_slices,map,'UniformOutput',false);
113+
114+
avg_intensity = mean(cell2mat(cellfun(@imhist,convert2img,'UniformOutput',false)),2);
115+
116+
% Create a copy of the image and rotate it by 180 degrees
117+
if applyAugmentation
118+
convert2img_2 = cellfun(@ind2rgb, cellfun(@(x)rot90(x,2),mid_slices,'UniformOutput',false),map,'UniformOutput',false);
119+
avg_intensity_2 = mean(cell2mat(cellfun(@imhist,convert2img_2,'UniformOutput',false)),2);
120+
end
121+
122+
% Save images in folders sorted by age range
123+
for i = 1:numel(mid_slices)
124+
125+
fileName = sprintf('image_%03d.png', i);
126+
outImg = histeq(convert2img{i},avg_intensity);
127+
128+
if ~isempty(dstFolder) %
129+
imwrite(outImg,fullfile(dstFolder,fileName),'mode','lossless');
130+
end
131+
132+
if i == 1
133+
exemplar = outImg;
134+
end
135+
136+
if applyAugmentation
137+
fileName_2 = sprintf('image2_%03d.png', i);
138+
outImg_2 = histeq(convert2img_2{i},avg_intensity_2);
139+
140+
if ~isempty(dstFolder)
141+
imwrite(outImg_2, fullfile(dstFolder,fileName_2),'mode','lossless');
142+
end
143+
end
144+
end
145+
146+
end
147+
148+
function fname = fullfile_(dstFolder,varargin)
149+
if isempty(dstFolder)
150+
fname = [];
151+
else
152+
fname = fullfile(dstFolder,varargin{:});
153+
end
154+
end
155+
156+
% Copyright 2020-2021 The MathWorks, Inc.

0 commit comments

Comments
 (0)