Augment Pixel Labels for Semantic Segmentation
This example shows how to perform common kinds of image and pixel label augmentation as part of semantic segmentation workflows.
Semantic segmentation training data consists of images represented by numeric matrices and pixel label images represented by categorical matrices. When you augment training data, you must apply identical transformations to the image and associated pixel labels. This example demonstrates three common types of transformations:
The example then shows how to apply augmentation to semantic segmentation training data in datastores using a combination of multiple types of transformations.
You can use augmented training data to train a network. For an example showing how to train a semantic segmentation network, see Semantic Segmentation Using Deep Learning.
To demonstrate the effects of the different types of augmentation, each transformation in this example uses the same input image and pixel label image.
Read a sample image.
filenameImage = 'kobi.png';
I = imread(filenameImage);
Read the pixel label image. The image has two classes.
filenameLabels = 'kobiPixelLabeled.png'; L = imread(filenameLabels); classes = ["floor","dog"]; ids = [1 2];
Convert the pixel label image to the categorical data type.
C = categorical(L,ids,classes);
Display the labels over the image by using the labeloverlay
function. Pixels with the label "floor" have a blue tint and pixels with the label "dog" have a cyan tint.
B = labeloverlay(I,C);
imshow(B)
title('Original Image and Pixel Labels')
Resize Image and Pixel Labels
You can resize numeric and categorical images by using the imresize
function. Resize the image and the pixel label image to the same size, and display the labels over the image.
targetSize = [300 300]; resizedI = imresize(I,targetSize); resizedC = imresize(C,targetSize);
Display the resized labels over the resized image.
B = labeloverlay(resizedI,resizedC);
imshow(B)
title('Resized Image and Pixel Labels')
Crop Image and Pixel Labels
Cropping is a common preprocessing step to make the data match the input size of the network. To create output images of a desired size, first specify the size and position of the crop window by using the randomWindow2d
and centerCropWindow2d
functions. Make sure you select a cropping window that includes the desired content in the image. Then, crop the image and pixel label image to the same window by using imcrop
.
Specify the desired size of the cropped region as a two-element vector of the form [height, width].
targetSize = [300 300];
Crop the image to the target size from the center of the image.
win = centerCropWindow2d(size(I),targetSize); croppedI = imcrop(I,win); croppedC = imcrop(C,win);
Display the cropped labels over the cropped image.
B = labeloverlay(croppedI,croppedC);
imshow(B)
title('Center Cropped Image and Pixel Labels')
Crop the image to the target size from a random position in the image.
win = randomWindow2d(size(I),targetSize); croppedI = imcrop(I,win); croppedC = imcrop(C,win);
Display the cropped labels over the cropped image.
B = labeloverlay(croppedI,croppedC);
imshow(B)
title('Random Cropped Image and Pixel Labels')
Warp Image and Pixel Labels
The randomAffine2d
function creates a randomized 2-D affine transformation from a combination of rotation, translation, scaling (resizing), reflection, and shearing. Apply the transformation to images and pixel label images by using imwarp
. Control the spatial bounds and resolution of the warped output by using the affineOutputView
function.
Rotate the input image and pixel label image by an angle selected randomly from the range [-50,50] degrees.
tform = randomAffine2d("Rotation",[-50 50]);
Create an output view for the warped image and pixel label image.
rout = affineOutputView(size(I),tform);
Use imwarp
to rotate the image and pixel label image.
rotatedI = imwarp(I,tform,'OutputView',rout); rotatedC = imwarp(C,tform,'OutputView',rout);
Display the rotated labels over the rotated image.
B = labeloverlay(rotatedI,rotatedC);
imshow(B)
title('Rotated Image and Pixel Labels')
Apply Augmentation to Semantic Segmentation Training Data in Datastores
Datastores are a convenient way to read and augment collections of images. Create a datastore that stores image and pixel label image data, and augment the data with a series of multiple operations.
Create Datastores Containing Image and Pixel Label Image Data
To increase the size of the sample datastores, replicate the filenames of the image and pixel label image.
numObservations = 4; trainImages = repelem({filenameImage},numObservations,1); trainLabels = repelem({filenameLabels},numObservations,1);
Create an imageDatastore
from the training image files. Create a pixelLabelDatastore
from the training pixel label files. The datastores contain multiple copies of the same data.
imds = imageDatastore(trainImages); pxds = pixelLabelDatastore(trainLabels,classes,ids);
Associate the image and pixel label pairs by combining the image datastore and pixel label datastore.
trainingData = combine(imds,pxds);
Read the first image and its associated pixel label image from the combined datastore.
data = read(trainingData); I = data{1}; C = data{2};
Display the image and pixel label data.
B = labeloverlay(I,C); imshow(B)
Apply Data Augmentation
Apply data augmentation to the training data by using the transform
function. This example performs two separate augmentations to the training data.
The first augmentation jitters the color of the image and then performs identical random scaling, horizontal reflection, and rotation on the image and pixel label image pairs. These operations are defined in the jitterImageColorAndWarp
helper function at the end of this example.
augmentedTrainingData = transform(trainingData,@jitterImageColorAndWarp);
Read all the augmented data.
data = readall(augmentedTrainingData);
Display the augmented image and pixel label data.
rgb = cell(numObservations,1); for k = 1:numObservations I = data{k,1}; C = data{k,2}; rgb{k} = labeloverlay(I,C); end montage(rgb)
The second augmentation center crops the image and pixel label image to a target size. These operations are defined in the centerCropImageAndLabel
helper function at the end of this example.
targetSize = [800 800];
preprocessedTrainingData = transform(augmentedTrainingData,...
@(data)centerCropImageAndLabel(data,targetSize));
Read all of the preprocessed data.
data = readall(preprocessedTrainingData);
Display the preprocessed image and pixel label data.
rgb = cell(numObservations,1); for k = 1:numObservations I = data{k,1}; C = data{k,2}; rgb{k} = labeloverlay(I,C); end montage(rgb)
Helper Functions for Augmentation
The jitterImageColorAndWarp
helper function applies random color jitter to the image data, then applies an identical affine transformation to the image and pixel label image data. The transformation consists of a random combination of scaling by a scale factor in the range [0.8 1.5], horizontal reflection, and rotation in the range [-30, 30] degrees. The input data
and output out
are two-element cell arrays, where the first element is the image data and the second element is the pixel label image data.
function out = jitterImageColorAndWarp(data) % Unpack original data. I = data{1}; C = data{2}; % Apply random color jitter. I = jitterColorHSV(I,"Brightness",0.3,"Contrast",0.4,"Saturation",0.2); % Define random affine transform. tform = randomAffine2d("Scale",[0.8 1.5],"XReflection",true,'Rotation',[-30 30]); rout = affineOutputView(size(I),tform); % Transform image and bounding box labels. augmentedImage = imwarp(I,tform,"OutputView",rout); augmentedLabel = imwarp(C,tform,"OutputView",rout); % Return augmented data. out = {augmentedImage,augmentedLabel}; end
The centerCropImageAndLabel
helper function creates a crop window centered on the image, then crops both the image and the pixel label image using the crop window. The input data
and output out
are two-element cell arrays, where the first element is the image data and the second element is the pixel label image data.
function out = centerCropImageAndLabel(data,targetSize) win = centerCropWindow2d(size(data{1}),targetSize); out{1} = imcrop(data{1},win); out{2} = imcrop(data{2},win); end
See Also
pixelLabelDatastore
| randomAffine2d
| centerCropWindow2d
| randomWindow2d