%% Deep Learning Prediction with Intel MKL-DNN
% 
% This example shows how to use |codegen| to generate code for an image classification application 
% that uses deep learning on Intel&reg; processors. The generated code
% takes advantage of the Intel Math Kernel Library for Deep Neural 
% Networks (MKL-DNN). First, the example generates a MEX function that runs
% prediction by using the ResNet-50 image classification network. Then, the
% example builds a static library and compiles it with a main file that runs  
% prediction using the ResNet-50 image classification network.
%
% Copyright 2018 The MathWorks, Inc.
%% Prerequisites
% * Xeon processor with support for Intel Advanced Vector Extensions 2
% (Intel AVX2) instructions
% * Intel Math Kernel Library for Deep Neural Networks (MKL-DNN)
% * Open Source Computer Vision Library (OpenCV) v3.1
% * Environment variables for Intel MKL-DNN and OpenCV 
% * MATLAB&reg; Coder&trade;, for C++ code generation.
% * The support package MATLAB Coder Interface for Deep Learning.
% * Deep Learning Toolbox&trade;, for using the |DAGNetwork| object
% * The Support package Deep Learning Toolbox Model for ResNet-50 Network support package, for
% using the pretrained ResNet network. 
%
% For more information, 
% see <docid:coder_ug#mw_99a4acec-aced-453c-aadd-a18e83133574>.
%
% This example is supported on Linux(R) and Windows(R) platforms and not
% supported for MATLAB Online.
%% |resnet_predict| Function
% 
% This example uses the DAG network ResNet-50 to show image classification
% with MKL-DNN. A pretrained ResNet-50 model for MATLAB is available in the
% support package Deep Learning Toolbox Model for ResNet-50 Network. 
% To download and install the support package, use the Add-On Explorer. 
% See <docid:matlab_env#buytlwx>.
% 
% The |resnet_predict| function loads the ResNet-50 network into a persistent
% network object. On subsequent calls to the function, the persistent
% object is reused.
%
type resnet_predict
%% Generate MEX Code for the |resnet_predict| Function
%
% To generate a MEX function from the |resnet_predict.m| function, use
% |codegen| with a deep learning configuration object created
% for the MKL-DNN library.
% Attach the deep learning configuration object to the MEX code
% generation configuration object that you pass to |codegen|.
%
 cfg = coder.config('mex');
 cfg.TargetLang = 'C++';
 cfg.DeepLearningConfig = coder.DeepLearningConfig('mkldnn');
 codegen -config cfg resnet_predict -args {ones(224,224,3,'single')} -report
%% Call |predict| on a Test Image
im = imread('peppers.png');
im = imresize(im, [224,224]);
imshow(im);
predict_scores = resnet_predict_mex(single(im));
%%
% Map the top five prediction scores to words in the synset dictionary.
fid = fopen('synsetWords.txt');
synsetOut = textscan(fid,'%s', 'delimiter', '\n');
synsetOut = synsetOut{1};
fclose(fid);
[val,indx] = sort(predict_scores, 'descend');
scores = val(1:5)*100;
top5labels = synsetOut(indx(1:5)); 
%%
% Display the top five classification labels on the image.
outputImage = zeros(224,400,3, 'uint8');
for k = 1:3
    outputImage(:,177:end,k) = im(:,:,k);
end
 
scol = 1;
srow = 1;
outputImage = insertText(outputImage, [scol, srow], 'Classification with ResNet-50', 'TextColor', 'w','FontSize',20, 'BoxColor', 'black');
srow = srow + 30;
for k = 1:5
    outputImage = insertText(outputImage, [scol, srow], [top5labels{k},' ',num2str(scores(k), '%2.2f'),'%'], 'TextColor', 'w','FontSize',15, 'BoxColor', 'black');
    srow = srow + 25;
end
 
imshow(outputImage);

%%
% Clear the static network object from memory.
clear mex;
%% Generate a Static Library for the |resnet_predict| Function
%
% To generate a static library from the |resnet_predict.m| function, use
% |codegen| with a deep learning configuration object created
% for the MKL-DNN library.
% Attach the deep learning configuration object to the code generation 
% configuration object that you pass to |codegen|.
cfg = coder.config('lib');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('mkldnn');
codegen -config cfg resnet_predict -args {ones(224,224,3,'single')} -report
%  
codegendir = fullfile(pwd, 'codegen', 'lib', 'resnet_predict');
%% |main_resnet.cpp| File
% The main file is used to generate an executable from the static library created
% by the |codegen| command. The main file reads the input image, runs
% prediction on the image, and displays the classification labels on the image.
type main_resnet.cpp

%% Build and Run the Executable
% Build the executable based on the target platform. On a Windows platform,
% this example uses Microsoft&reg; Visual Studio&reg; 2017 for C++.
%
%  if ispc
%      setenv('MATLAB_ROOT', matlabroot);
%      system('make_mkldnn_win17.bat');
%      system('resnet.exe peppers.png');
%  else
%      setenv('MATLAB_ROOT', matlabroot);
%      system('make -f Makefile_mkldnn_linux.mk');
%      system('./resnet_exe peppers.png');
%  end
%
%%
% 
% <<../peppers_mkldnnex_output_c.png>>
%
% The results from the MEX function might not match the results from the 
% generated static library function due to differences in the version of the 
% library that is used to read the input image file. The image that is passed to the MEX 
% function is read using the version that MATLAB ships. The image that is passed
% to the static library function is read using the version that OpenCV uses.
