%% Code Generation for Deep Learning Networks
% 
% This example shows how to perform code generation for an image 
% classification application that uses deep learning. It uses the |codegen| 
% command to generate a MEX function that runs prediction by using image 
% classification networks such as MobileNet-v2, ResNet, and GoogLeNet.
%
%   Copyright 2017-2020 The MathWorks, Inc.
%% Third-Party Prerequisites
% *Required*
%
% This example generates CUDA MEX and has the following third-party
% requirements.
%
% * CUDA(R) enabled NVIDIA(R) GPU and compatible driver.
%
% *Optional*
%
% For non-MEX builds such as static, dynamic libraries or executables,
% this example has the following additional requirements.
%
% * NVIDIA toolkit.
% * NVIDIA cuDNN library.
% * Environment variables for the compilers and libraries. For more
% information, see
% <docid:gpucoder_gs#mw_aa8b0a39-45ea-4295-b244-52d6e6907bff Third-party
% Products> and <docid:gpucoder_gs#mw_453fbbd7-fd08-44a8-9113-a132ed383275
% Environment Variables>.
%% Verify GPU Environment
% Use the <docid:gpucoder_ref#mw_0957d820-192f-400a-8045-0bb746a75278 coder.checkGpuInstall> function
% to verify that the compilers and libraries necessary for running this example
% are set up correctly.
envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);
%% |mobilenetv2_predict| Entry-Point Function
% 
% MobileNet-v2 is a convolutional neural network that is trained on more 
% than a million images from the ImageNet database. The network is 155 
% layers deep and can classify images into 1000 object categories, such as 
% keyboard, mouse, pencil, and many animals. The network has an image 
% input size of 224-by-224. Use the <docid:nnet_ref#mw_8d52b67d-b6b3-4c62-b573-56fdf4dce6a0 analyzeNetwork> 
% function to display an interactive visualization of the deep learning 
% network architecture.
net = mobilenetv2();
analyzeNetwork(net);

%%
% The <matlab:edit(fullfile(matlabroot,'examples','deeplearning_shared','main','mobilenetv2_predict.m'))
% mobilenetv2_predict.m> entry-point function takes an image input and 
% runs prediction on the image using the pretrained MobileNet-v2 
% convolutional neural network. The function uses a persistent object 
% _mynet_ to load the series network object and reuses the persistent 
% object for prediction on subsequent calls.
%
type('mobilenetv2_predict.m')

%% Run MEX Code Generation
%
% To generate CUDA code for the |mobilenetv2_predict| entry-point function,
% create a GPU code configuration object for a MEX target and set the target 
% language to C++. Use the
% <docid:gpucoder_ref#mw_e8e85f8e-8dde-45b6-9ec5-f121a79dc48f coder.DeepLearningConfig>
% function to create a |CuDNN| deep learning configuration object and
% assign it to the |DeepLearningConfig| property of the GPU code
% configuration object. Run the |codegen| command and specify an input size
% of [224,224,3]. This value corresponds to the input layer size of 
% the MobileNet-v2 network.
cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg mobilenetv2_predict -args {ones(224,224,3)} -report
%% Generated Code Description
%
% The series network is generated as a C++ class containing an array of 155 layer
% classes and functions to set up, call predict, and clean up the network.
%
%   class b_mobilenetv2_0
%   {
%      .... 
%      public:
%        b_mobilenetv2_0();
%        void setup();
%        void predict();
%        void cleanup();
%        ~b_mobilenetv2_0();
%   };
%
% The |setup()| method of the class sets up handles and allocates memory for
% each layer of the network object. The |predict()| method performs prediction
% for each of the 155 layers in the network.
%% 
%
% The entry-point function |mobilenetv2_predict()| in the generated code file
% |mobilenetv2_predict.cu| constructs a static object of _b_mobilenetv2_ class type and 
% invokes setup and predict on this network object.  
%% 
%
%   static b_mobilenetv2_0 mynet;
%   static boolean_T mynet_not_empty;
% 
%   /* Function Definitions */
%   void mobilenetv2_predict(const real_T in[150528], real32_T out[1000])
%   {
%     if (!mynet_not_empty) {
%       DeepLearningNetwork_setup(&mynet);
%       mynet_not_empty = true;
%     }
% 
%     /*  pass in input    */
%     DeepLearningNetwork_predict(&mynet, in, out);
%   }
%%
% Binary files are exported for layers with parameters such as 
% fully connected and convolution layers in the network. For instance,
% files cnn_mobilenetv2_conv*_w and cnn_mobilenetv2_conv*_b correspond to weights and 
% bias parameters for the convolution layers in the network. To see a 
% list of the generated files, use:
%
%   dir(fullfile(pwd, 'codegen', 'mex', 'mobilenetv2_predict'))
%% Run Generated MEX 
%
% Load an input image.
im = imread('peppers.png');
imshow(im);
%% 
% Call |mobilenetv2_predict_mex| on the input image.
im = imresize(im, [224,224]);
predict_scores = mobilenetv2_predict_mex(double(im));
%% 
% Get the top five prediction scores and their labels.
[scores,indx] = sort(predict_scores, 'descend');
classNames = net.Layers(end).ClassNames;
classNamesTop = classNames(indx(1:5));

h = figure;
h.Position(3) = 2*h.Position(3);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);

image(ax1,im);
barh(ax2,scores(5:-1:1))
xlabel(ax2,'Probability')
yticklabels(ax2,classNamesTop(5:-1:1))
ax2.YAxisLocation = 'right';
sgtitle('Top Five Predictions That Use MobileNet-v2')

%% Classification of Video
%
% The included helper function 
% <matlab:edit(fullfile(matlabroot,'examples','deeplearning_shared','main','mobilenet_live.m'))
% mobilenet_live.m> grabs frames from a webcam, performs prediction, and 
% displays the classification results on each of the captured video frames.
% This example uses the 
% <docid:usbwebcams_ug#buerllq-1 webcam>
% function that is supported by the MATLAB(R) Support Package for USB 
% Webcams(TM). You can download and install the support package through the
% <matlab:supportPackageInstaller Support Package Installer>.
%
type('mobilenet_live.m')
%%  
%
% Clear the static network object that was loaded in memory. 
clear mex;
%% Classification of Images by Using ResNet-50 network
% 
% You can also use the DAG network ResNet-50 for image classification.
% A pretrained ResNet-50 model for MATLAB is available in the 
% ResNet-50 support package of Deep Learning Toolbox. To download and 
% install the support package, use the Add-On Explorer. To learn more about 
% finding and installing add-ons, see 
% <matlab:web(fullfile(docroot,'matlab/matlab_env/get-add-ons.html')) Get Add-Ons (MATLAB)>.
%
%%
%
net = resnet50;
disp(net)
%% Run MEX Code Generation
%
% To generate CUDA code for the 
% <matlab:edit(fullfile(matlabroot,'examples','deeplearning_shared','main','resnet_predict.m'))
% resnet_predict.m> entry-point function,create a GPU code configuration 
% object for a MEX target and set the target language to C++. This 
% entry-point function calls the |resnet50| function to load the network and 
% perform prediction on the input image. 
%
cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg resnet_predict -args {ones(224,224,3)} -report
%% 
%
% Call |resnet_predict_mex| on the input image.
predict_scores = resnet_predict_mex(double(im));
%% 
% Get the top five prediction scores and their labels.
[scores,indx] = sort(predict_scores, 'descend');
classNames = net.Layers(end).ClassNames;
classNamesTop = classNames(indx(1:5));

h = figure;
h.Position(3) = 2*h.Position(3);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);

image(ax1,im);
barh(ax2,scores(5:-1:1))
xlabel(ax2,'Probability')
yticklabels(ax2,classNamesTop(5:-1:1))
ax2.YAxisLocation = 'right';
sgtitle('Top Five Predictions That Use ResNet-50')
%%
%
% Clear the static network object that was loaded in memory. 
clear mex;
%% Classification of Images by Using GoogLeNet (Inception) network
% 
% A pretrained GoogLeNet model for MATLAB is available in the GoogLeNet
% support package of Deep Learning Toolbox. To download and install the 
% support package, use the Add-On Explorer. To learn more about finding 
% and installing add-ons, see 
% <matlab:web(fullfile(docroot,'matlab/matlab_env/get-add-ons.html')) Get Add-Ons (MATLAB)>.
%
%% 
% 
net = googlenet;
disp(net)
%% Run MEX Code Generation 
%
% Generate CUDA code for the
% <matlab:edit(fullfile(matlabroot,'examples','deeplearning_shared','main','googlenet_predict.m')) googlenet_predict.m>
%  entry-point function. This entry-point function calls the |googlenet|
% function to load the network and perform prediction on the input image.
% To generate code for this entry-point function, create a GPU 
% configuration object for MEX target. 
%
cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg googlenet_predict -args {ones(224,224,3)} -report
%%
%
% Call |googlenet_predict_mex| on the input image.
im = imresize(im, [224,224]);
predict_scores = googlenet_predict_mex(double(im));
%% 
% Get the top five prediction scores and their labels.
[scores,indx] = sort(predict_scores, 'descend');
classNames = net.Layers(end).ClassNames;
classNamesTop = classNames(indx(1:5));

h = figure;
h.Position(3) = 2*h.Position(3);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);

image(ax1,im);
barh(ax2,scores(5:-1:1))
xlabel(ax2,'Probability')
yticklabels(ax2,classNamesTop(5:-1:1))
ax2.YAxisLocation = 'right';
sgtitle('Top Five Predictions That Use GoogLeNet')
%%
%
% Clear the static network object that was loaded in memory. 
clear mex;

