%% Code Generation for Semantic Segmentation Network
% 
% This example shows code generation for an image segmentation application 
% that uses deep learning. It uses the |codegen| command to generate a MEX 
% function that performs prediction on a DAG Network object
% for SegNet [1], a deep learning network for image segmentation.
%
%   Copyright 2016-2019 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);
%% Segmentation Network
% SegNet [1] is a type of convolutional neural network (CNN) designed
% for semantic image segmentation. It is a deep encoder-decoder multi-class
% pixel-wise segmentation network trained on the CamVid [2] dataset and imported into
% MATLAB(R) for inference. The SegNet [1] is trained to segment pixels belonging
% to 11 classes that include Sky, Building, Pole, Road, Pavement, Tree,
% SignSymbol, Fence, Car, Pedestrian, and Bicyclist.
%
% For information regarding training a semantic segmentation network in 
% MATLAB by using the CamVid [2] dataset, see
% <matlab:web(fullfile(docroot,'vision/ug/semantic-segmentation-using-deep-learning.html')) Semantic Segmentation Using Deep Learning>.

%% The |segnet_predict| Entry-Point Function
% 
% The <matlab:edit(fullfile(matlabroot,'examples','deeplearning_shared','main','segnet_predict.m')) segnet_predict.m>
% entry-point function takes an image input and performs prediction on the 
% image by using the deep learning network saved in the |SegNet.mat| file.
% The function loads the network object from the |SegNet.mat| file into a persistent
% variable _mynet_ and reuses the persistent variable on subsequent prediction calls.  
%
type('segnet_predict.m')

%% Get Pretrained SegNet DAG Network Object
%
net = getSegNet();

%%
%
% The DAG network contains 91 layers including convolution, batch 
% normalization, pooling, unpooling, and the pixel classification output 
% layers. Use the <docid:nnet_ref#mw_8d52b67d-b6b3-4c62-b573-56fdf4dce6a0 analyzeNetwork> 
% function to display an interactive visualization of the deep learning 
% network architecture.
analyzeNetwork(net);

%% Run MEX Code Generation 
%
% To generate CUDA code for the <matlab:edit(fullfile(matlabroot,'examples','deeplearning_shared','main','segnet_predict.m'))
% segnet_predict.m> 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 specifying an input size
% of [360,480,3]. This value corresponds to the input layer size of |SegNet|.
cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg segnet_predict -args {ones(360,480,3,'uint8')} -report

%% Run Generated MEX 
%
% Load and display an input image. Call |segnet_predict_mex| on the input image.
im = imread('gpucoder_segnet_image.png');
imshow(im);
predict_scores = segnet_predict_mex(im);
%% 
% The _predict_scores_ variable is a three-dimensional matrix that has 11 
% channels corresponding to the pixel-wise prediction scores for every 
% class. Compute the channel by using the maximum prediction score to get 
% pixel-wise labels.
[~,argmax] = max(predict_scores,[],3);

%%
% Overlay the segmented labels on the input image and display the
% segmented region.

classes = [
    "Sky"
    "Building"
    "Pole"
    "Road"
    "Pavement"
    "Tree"
    "SignSymbol"
    "Fence"
    "Car"
    "Pedestrian"
    "Bicyclist"
    ];

cmap = camvidColorMap();
SegmentedImage = labeloverlay(im,argmax,'ColorMap',cmap);
figure
imshow(SegmentedImage);
pixelLabelColorbar(cmap,classes);

%% References
% [1] Badrinarayanan, Vijay, Alex Kendall, and Roberto Cipolla. "SegNet: A
% Deep Convolutional Encoder-Decoder Architecture for Image Segmentation."
% _arXiv preprint arXiv:1511.00561,_ 2015.
%
% [2] Brostow, Gabriel J., Julien Fauqueur, and Roberto Cipolla. "Semantic
% object classes in video: A high-definition ground truth database."
% _Pattern Recognition Letters_ Vol 30, Issue 2, 2009, pp 88-97.
