Skip to content

Commit

Permalink
Merge pull request #4 from davehoadley/R2024b
Browse files Browse the repository at this point in the history
R2024b support
  • Loading branch information
davehoadley authored Sep 16, 2024
2 parents 8b27779 + 5204e75 commit 9e08053
Show file tree
Hide file tree
Showing 22 changed files with 210 additions and 86 deletions.
29 changes: 20 additions & 9 deletions .github/workflows/run-matlab-tests.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
name: MATLAB matrix tests
name: Generate Test and Coverage Artifacts on GitHub-Hosted Runner
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: '24 16 * * 2' # schedule a weekly build to keep caches warm
jobs:
test-job:
my-job:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-13, macos-14]
name: Run MATLAB Tests and Generate Artifacts
name: Build Toolbox
runs-on: ${{ matrix.os }}
steps:
- name: Support long paths
Expand All @@ -24,6 +24,7 @@ jobs:
uses: matlab-actions/setup-matlab@v2
with:
cache: true
release: R2024b
products: |
Deep_Learning_Toolbox
Computer_Vision_Toolbox
Expand All @@ -38,13 +39,23 @@ jobs:
Deep_Learning_Toolbox_Model_for_ResNet-50_Network
Deep_Learning_Toolbox_Model_for_VGG-16_Network
Deep_Learning_Toolbox_Model_for_VGG-19_Network
- name: Run tests and generate artifacts
uses: matlab-actions/run-tests@v2
with:
test-results-junit: test-results/results.xml
logging-level: detailed
- name: Upload Test Results for ${{ matrix.os }}
- name: Run MATLAB build
uses: matlab-actions/run-build@v2
- name: Upload Test and Coverage Results
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }} Results
path: test-results
- name: Upload Code Analysis Results
if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@v4
with:
name: Results
path: analysis-results
- name: Upload Toolbox (mltbx)
if: ${{ matrix.os == 'ubuntu-latest' }}
uses: actions/upload-artifact@v4
with:
name: Tool Validation Kit
path: release/Tool Validation Kit.mltbx

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
# List of untracked files to ignore
derived/
12 changes: 6 additions & 6 deletions UnitTestFolder/ComputerVisionToolbox/DeepLabV3PlusTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
'xception','block14_sepconv2_act');

ExpAdditionalLayer = struct(...
'resnet18', 33, ...
'inceptionresnetv2', 33, ...
'mobilenetv2', 39', ...
'resnet50', 33, ...
'xception', 39);
'resnet18', 32, ...
'inceptionresnetv2', 32, ...
'mobilenetv2', 38', ...
'resnet50', 32, ...
'xception', 38);
end

%% Test Methods
Expand All @@ -36,7 +36,7 @@ function checkDeepLabv3PlusLayersTest(test, SpPkgName, LayerMatch, ExpAdditional
% Check the layer is created/replaced properly
imageSize = [512 512];
numClasses = 21;
lgraph = deeplabv3plusLayers(imageSize, numClasses, SpPkgName, "Downsampling", 8);
lgraph = deeplabv3plus(imageSize, numClasses, SpPkgName, "Downsampling", 8);

% Verify default values
dlayerNames = {lgraph.Layers.Name};
Expand Down
31 changes: 14 additions & 17 deletions UnitTestFolder/ComputerVisionToolbox/UnetTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,19 @@ function testDefaultValues(test)
for i=1:length(idxConvLayer)
paddingModes{i} = unet1.Layers(idxConvLayer(i)).PaddingMode;
end
if strcmp(padding, "valid")
test.verifyEqual(paddingModes,repmat({'manual'},[1,i]));
else
test.verifyEqual(paddingModes,repmat({padding},[1,i]));
end

test.verifyEqual(paddingModes,repmat({padding},[1,i]));
end

function verifyEncoderAndDecoderSections(test)
% Testpoint to verify that there are only EncoderDepth number
% of Encoder and Decoder sections.

encoderDepth = 4;
unet = unetLayers([96 96], 2, 'EncoderDepth', encoderDepth);
unet1 = unetLayers([96 96], 2, 'EncoderDepth', encoderDepth);

% Get the names of the layers.
layerNames = {unet.Layers(:).Name};
layerNames = {unet1.Layers(:).Name};

encDecFlag = false([1 encoderDepth]);

Expand Down Expand Up @@ -143,7 +140,7 @@ function verifyNumChannelsInEncoderAndDecoderSections(test)
% Testpoint to verify same number of channels for last
% convolution layer of each encoder and decoder section.
numFirstEncoderFilters = 128;
unet = unetLayers([96 96], 2, 'NumFirstEncoderFilters', ...
unet1 = unetLayers([96 96], 2, 'NumFirstEncoderFilters', ...
numFirstEncoderFilters);

encoderLevel = 1;
Expand All @@ -152,19 +149,19 @@ function verifyNumChannelsInEncoderAndDecoderSections(test)
encoderChannel = [];
decoderChannel = [];

for i = 1:length(unet.Layers)
for i = 1:length(unet1.Layers)

if contains(unet.Layers(i).Name, ['Encoder-Stage-' ...
if contains(unet1.Layers(i).Name, ['Encoder-Stage-' ...
num2str(encoderLevel) '-Conv-2'])
encoderChannel = [encoderChannel ...
unet.Layers(i).NumChannels];
unet1.Layers(i).NumChannels];

encoderLevel = encoderLevel+1;
end

if contains(unet.Layers(i).Name, ['Decoder-Stage-' ...
if contains(unet1.Layers(i).Name, ['Decoder-Stage-' ...
num2str(decoderLevel) '-Conv-2'])
decoderChannel = [unet.Layers(i).NumChannels...
decoderChannel = [unet1.Layers(i).NumChannels...
decoderChannel];

decoderLevel = decoderLevel+1;
Expand All @@ -180,14 +177,14 @@ function verifyValidConvolutionPadding(test)
encoderDepth = 1;
numFirstEncoderFilters = 32;
padding = 'valid';
unet = unetLayers([100 100 3], 3, 'EncoderDepth', ...
unet1 = unetLayers([100 100 3], 3, 'EncoderDepth', ...
encoderDepth, 'FilterSize', filterSize, ...
'NumFirstEncoderFilters', numFirstEncoderFilters, ...
'ConvolutionPadding', padding);
decoderLevel = 1;
numCrop2dLayers = 0;
for i = 1:length(unet.Layers)
if contains(unet.Layers(i).Name, ...
for i = 1:length(unet1.Layers)
if contains(unet1.Layers(i).Name, ...
['Crop2d-' num2str(decoderLevel)])
decoderLevel = decoderLevel+1;
numCrop2dLayers = numCrop2dLayers + 1;
Expand All @@ -201,7 +198,7 @@ function testDifferentParameters(test, InputSize, EncoderDepth, ...

flag = true;
try
unet = unetLayers(InputSize, 4,...
unet1 = unetLayers(InputSize, 4,...
'EncoderDepth', EncoderDepth, ...
'NumFirstEncoderFilters', ...
NumFirstEncoderFilters, 'FilterSize', FilterSize); %#ok<NASGU>
Expand Down
92 changes: 61 additions & 31 deletions UnitTestFolder/DeepLearningToolbox/ImageDataAugmenterTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@ function testDefaultValues(testcase)

function basicBehaviorRGB(testcase)

augmenter = imageDataAugmenter('RandRotation',[-20 20]);
augmenter = instrumentedImageDataAugmenter('RandRotation',[-20 20]);
A = testcase.peppersImage;
out = augment(augmenter,testcase.peppersImage);

exp = imwarp(A,affine2d(augmenter.AffineTransforms),'OutputView',imref2d(size(A)));
exp = imwarp(A,affine2d(augmenter.getAffineTransform),'OutputView',imref2d(size(A)));

% Use SSIM to give us some wiggle room re: resizing algorithm,
% intermediate datatype, etc. We just want to know if the same
Expand All @@ -60,25 +59,16 @@ function basicBehaviorRGB(testcase)

function basicBehaviorGrayscale(testcase)

augmenter = imageDataAugmenter('RandRotation',[-20 20],'RandXTranslation',[0 10]);
augmenter = instrumentedImageDataAugmenter('RandRotation',[-20 20],'RandXTranslation',[0 10]);

A = testcase.cameramanImage;
out = augment(augmenter,A);

rot = augmenter.Rotation;
xtrans = augmenter.XTranslation;

testcase.verifyGreaterThanOrEqual(rot,-20);
testcase.verifyLessThanOrEqual(rot,20);
testcase.verifyGreaterThanOrEqual(xtrans,0);
testcase.verifyLessThanOrEqual(xtrans,10);

exp = imwarp(A,affine2d(augmenter.AffineTransforms),'OutputView',imref2d(size(A)));
exp = imwarp(A,affine2d(augmenter.getAffineTransform()),'OutputView',imref2d(size(A)));

ssimObserved = ssim(out,exp);

testcase.verifyGreaterThan(ssimObserved,0.9,'Incorrect augmentation for RGB rotation.');

testcase.verifyGreaterThan(ssimObserved,0.9,'Incorrect augmentation for RGB rotation.');
end

function testRotation(testcase)
Expand Down Expand Up @@ -152,27 +142,67 @@ function testScale(testcase)

end

function testReflection(testcase)

function testXReflection(testcase)

import matlab.unittest.constraints.IsEqualTo;

A = testcase.cameramanImage;
augmenter = imageDataAugmenter('RandXReflection',true);

rng(1);
act = augmenter.augment(A);
exp = fliplr(A);

testcase.verifyTrue(isequal(act,exp),'Incorrect augmentation for X reflection.');


% Every result should be either flipped or not.
Aflipped = fliplr(A);
con = IsEqualTo(A) | IsEqualTo(Aflipped);

% Use a fixed random sequence to ensure test repeatability.
orig = rng(1);
testcase.addTeardown(@rng, orig)

flipped = false(1,100);
for n = 1:100
act = augmenter.augment(A);
testcase.verifyThat(act, con, 'Incorrect augmentation for X reflection.');

flipped(n) = all(act==Aflipped, 'all');
end

% The number flipped ought to be close to the expected mean, 50. The exact
% number is repeatable in this test due to the fixed seed, but may alter if
% the imageDataAugmenter changes how it samples from the random stream. To
% allow for this we test that the flipping happens within the 2 sigma
% level.
testcase.verifyLessThanOrEqual(abs(sum(flipped)-50), 10, 'Incorrect augmentation for X reflection.');
end

function testYReflection(testcase)

import matlab.unittest.constraints.IsEqualTo;

A = testcase.cameramanImage;
augmenter = imageDataAugmenter('RandYReflection',true);

rng(1);
act = augmenter.augment(A);
exp = flipud(A);

testcase.verifyTrue(isequal(act,exp),'Incorrect augmentation for Y reflection.');

Aflipped = flipud(A);
con = IsEqualTo(A) | IsEqualTo(Aflipped);

% Use a fixed random sequence to ensure test repeatability.
orig = rng(1);
testcase.addTeardown(@rng, orig)

flipped = false(1,100);
for n = 1:100
act = augmenter.augment(A);
testcase.verifyThat(act, con, 'Incorrect augmentation for Y reflection.');

flipped(n) = all(act==Aflipped, 'all');
end

% The number flipped ought to be close to the expected mean, 50. The exact
% number is repeatable in this test due to the fixed seed, but may alter if
% the imageDataAugmenter changes how it samples from the random stream. To
% allow for this we test that the flipping happens within the 2 sigma
% level.
testcase.verifyLessThanOrEqual(abs(sum(flipped)-50), 10, 'Incorrect augmentation for Y reflection.');
end

function testShear(testcase)

A = testcase.peppersImage;
Expand Down
2 changes: 1 addition & 1 deletion UnitTestFolder/DeepLearningToolbox/TrainingOptionsTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function passingInvalidSolverNameThrowsError(test)
% be thrown.

invalidSolverName = 'NotARealSolverName';
errorID = 'nnet_cnn:trainingOptions:InvalidSolverName';
errorID = 'nnet_cnn:trainingOptions:InvalidTrainingOptions';

try
trainingOptions(invalidSolverName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
classdef instrumentedImageDataAugmenter < imageDataAugmenter
% imageDataAugmenter subclass which provides access to intermediate
% transform values for testing.

% Copyright 2024 The MathWorks, Inc.

methods
function obj = instrumentedImageDataAugmenter(varargin)
obj@imageDataAugmenter(varargin{:});
end

function T = getAffineTransform(obj, varargin)
%getAffineTransform Return the affine transform matrix
%
% getAffineTransform(obj) returns the full 3x3 matrix that the
% imageDataAugmenter used for the most recent augment() call.
%
% getAffineTransform(obj, rowidx, colidx, pageidx) indexes the above
% matrix and returns only the requested elements.

T = obj.AffineTransforms;
if nargin>1
T = T(varargin{:});
end
end
end
end
Git LFS file not shown
Git LFS file not shown
11 changes: 5 additions & 6 deletions app/Tool Validation Kit App.prj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<deployment-project plugin="plugin.apptool" plugin-version="1.0">
<configuration build-checksum="3995440563" file="C:\projects\tool-validation-kit\app\Tool Validation Kit App.prj" location="C:\projects\tool-validation-kit\app" name="Tool Validation Kit App" target="target.mlapps" target-name="Package App">
<configuration build-checksum="2546190291" file="C:\projects\tool-validation-kit\app\Tool Validation Kit App.prj" location="C:\projects\tool-validation-kit\app" name="Tool Validation Kit App" target="target.mlapps" target-name="Package App">
<param.appname>Tool Validation Kit App</param.appname>
<param.authnamewatermark>MathWorks Consulting</param.authnamewatermark>
<param.email />
Expand All @@ -13,12 +13,12 @@
<param.summary />
<param.description />
<param.screenshot />
<param.version>4.2.1</param.version>
<param.version>4.2.2</param.version>
<param.products.name />
<param.products.id />
<param.products.version />
<param.platforms />
<param.output>${PROJECT_ROOT}</param.output>
<param.output>C:\projects\tool-validation-kit\release</param.output>
<param.guid>22279144-5ed8-4032-b62b-bf792b595b21</param.guid>
<unset>
<param.email />
Expand All @@ -29,7 +29,6 @@
<param.products.id />
<param.products.version />
<param.platforms />
<param.output />
</unset>
<fileset.main>
<file>${PROJECT_ROOT}\runToolValidationKitApp.m</file>
Expand All @@ -54,11 +53,11 @@
</fileset.resources>
<fileset.package />
<build-deliverables>
<file location="C:\projects\tool-validation-kit" name="app" optional="false">C:\projects\tool-validation-kit\app</file>
<file location="C:\projects\tool-validation-kit" name="release" optional="false">C:\projects\tool-validation-kit\release</file>
</build-deliverables>
<workflow />
<matlab>
<root>C:\Program Files\MATLAB\R2023b</root>
<root>C:\Program Files\MATLAB\R2024b</root>
<toolboxes>
<toolbox name="matlabcoder" />
<toolbox name="embeddedcoder" />
Expand Down
Loading

0 comments on commit 9e08053

Please sign in to comment.