%% Transform Batch of Volumetric Data in Image Datastore
% This example shows how to transform volumetric data in an image datastore using a sample image preprocessing pipeline.
% Specify a set of volumetric images saved at MAT files.

filepath = fullfile(matlabroot,"toolbox","images","imdata","mristack.mat");
files = [filepath; filepath; filepath];

% Create an image datastore that stores multiple volumetric images. Specify that the ReadSize of the datastore is greater than 1. Specify a custom read function, matRead. This function is defined in the Supporting Functions section of this example.

volDS = imageDatastore(files,"FileExtensions",".mat", ...
    "ReadSize",3,"ReadFcn",@(x) matRead(x));

% Specify the input size of the network.

inputSize = [128 128];

% Preprocess the volumetric images in volDS using the custom preprocessing pipeline defined in the preprocessVolumetricIMDS supporting function.

dsTrain = transform(volDS,@(x) preprocessVolumetricIMDS(x,inputSize));

% Read a batch of data.

minibatch = read(dsTrain)

%
%% Supporting Functions
% The matRead function loads volume data from the first variable of a MAT file.

function data = matRead(filename)
    inp = load(filename);
    f = fields(inp);
    data = inp.(f{1});
end

% The preprocessVolumetricIMDS function performs the desired transformations of data read from an underlying image datastore. Because the read size of the image datastore is greater than 1, the function must accept a cell array of image data. The function loops through each read image and transforms the data according to this preprocessing pipeline:
% Randomly rotate the image about the z-axis.
% Resize the volume to the size expected by the network.
% Create a noisy version of the image with Gaussian noise.
% Return the image in a cell array.

function batchOut = preprocessVolumetricIMDS(batchIn,inputSize)
 
numRows = size(batchIn,1);
batchOut = cell(numRows,1);
 
for idx = 1:numRows
    
    % Perform randomized 90 degree rotation about the z-axis
    imRotated = imrotate3(batchIn{idx,1},90*(randi(4)-1),[0 0 1]);

    % Resize the volume to the size expected by the network
    imResized = imresize(imRotated,inputSize);
    
    % Add zero-mean Gaussian noise with a normalized variance of 0.01
    imNoisy = imnoise(imResized,'gaussian',0.01);

    % Return the preprocessed data
    batchOut(idx) = {imNoisy};
    
end
end

% Copyright 2020 The MathWorks, Inc.