Main Content

Convert Ultrasound Image Series into Training Data for 2-D Semantic Segmentation Network

This example shows how to create training data for a 2-D semantic segmentation network using a groundTruthMedical object that contains a multiframe ultrasound image series. To train a semantic segmentation network, you must have pairs of data source images and label images, stored in an imageDatastore object and pixelLabelDatastore object, respectively. To train a 2-D network using data from a multiframe image series, you must convert the series into individual frames stored in separate files.

Create Ground Truth Object

You can export a groundTruthMedical object from the Medical Image Labeler app or create one programmatically. For illustrative purposes, this example creates a groundTruthMedical object by using the createGroundTruthMed2D helper function. The helper function is attached to this example as a supporting file. The groundTruthMedical object references a multiframe echocardiogram data source and its corresponding label image series. The data source and label images are stored as a single DICOM file and MAT file, respectively.

gTruthMed = createGroundTruthMed2D;

Extract Data from Ground Truth Object

Extract the data source and label image filenames from the groundTruthMedical object.

dataSource = gTruthMed.DataSource.Source;
labelData = gTruthMed.LabelData;

Remove any data sources that are missing label images, if present.

labelsIdx = labelData ~= "";
dataSource = dataSource(labelsIdx);
labelData = labelData(labelsIdx);

Extract the label definitions from the groundTruthMedical object. Add a label definition for the background region, corresponding to a pixel value of 0.

labelDefs = gTruthMed.LabelDefinitions;
labelDefs(2,:) = {"background",[0 1 0],0};

Convert Multiframe Series into 2-D Frames

The data source is a multiframe ultrasound image series stored in a single DICOM file. Convert the DICOM file into individual 2-D images, stored as MAT files, by using the convertImageSeriesToFrames supporting function. The supporting function is defined at the end of this example.

newDataSource = convertImageSeriesToFrames(dataSource);
newDataSource = string(newDataSource);

The label data is a multiframe image series stored in a single MAT file. Convert each frame of the image series into an individual MAT file by using the convertLabelSeriesToFrames supporting function. The supporting function is defined at the end of this example.

newLabelData = convertLabelSeriesToFrames(labelData);

Create Datastores

Load the individual MAT file data sources into an imageDatastore object.

imds = imageDatastore(newDataSource, ...
       ReadFcn=@readFramesLabels, ...
       FileExtensions=[".mat",".dcm"]);

Load the individual MAT file label images into a pixelLabelDatastore (Computer Vision Toolbox) object. Use the label definitions from the groundTruthMedical object to map pixel values to categorical labels in the datastore.

pxds = pixelLabelDatastore(cellstr(newLabelData),labelDefs.Name,labelDefs.PixelLabelID, ...
       ReadFcn=@readFramesLabels, ...
       FileExtensions=".mat");

Preview one image and its corresponding label. Display the labeled image by using the labeloverlay function.

im = preview(imds);
label = preview(pxds);
imOverlay = labeloverlay(im,label);
imshow(imOverlay)

Figure contains an axes object. The axes object contains an object of type image.

Create a CombinedDatastore object that pairs each data source image with its corresponding label image.

trainingData = combine(imds,pxds);

Supporting Functions

The convertImageSeriesToSlices function converts a multiframe DICOM image series, such as ultrasound data, into individual 2-D frames stored in separate MAT files. The function returns a cell array of the new MAT filenames.

function newDataSource = convertImageSeriesToFrames(labelDataSource)
% Create a data directory to store MAT files
dataFileDir = fullfile(pwd,"GroundTruthData");

if ~isfolder(dataFileDir)
    mkdir(dataFileDir)
end

image = medicalImage(labelDataSource);
data3d = image.Pixels;

% Assumption that time is the third dimension
numFrames =  size(data3d,3);
newDataSource = cell(numFrames,1);

for frame = 1:numFrames
    data = squeeze(data3d(:,:,frame,:));
    [~,name,~] = fileparts(labelDataSource);
    matFileName = strcat(fullfile(dataFileDir,name),"_",num2str(frame),".mat");
    save(matFileName,"data");
    newDataSource{frame} = string(matFileName);
end

end

The convertLabelSeriesToFrames function converts a multiframe image series stored in a single file into individual frames stored as separate MAT files. The function returns a cell array of the new MAT filenames.

function newlabelData = convertLabelSeriesToFrames(labelSource)
% Create a label directory to store MAT files
labelFileDir = fullfile(pwd,"GroundTruthLabel");

if ~isfolder(labelFileDir)
    mkdir(labelFileDir)
end

labelData = load(labelSource);

% Assume that the third dimension contains frames taken at different times
numFrames =  size(labelData.labels,3);
newlabelData = cell(numFrames,1);

[~,name,~] = fileparts(labelSource);
for frame = 1:numFrames
    data = squeeze(labelData.labels(:,:,frame,:));
    matFileName = strcat(fullfile(labelFileDir,name),"_",num2str(frame),".mat");
    save(matFileName,"data");
    newlabelData{frame} = string(matFileName);
end

end

The readFramesLabels function reads data from the data variable of a MAT file.

function data = readFramesLabels(filename)
d = load(filename);
data = d.data;
end

See Also

| | (Computer Vision Toolbox) | |

Related Topics