%% Code Generation for Object Detection by Using YOLO v2
%
% This example shows how to generate CUDA(R) MEX for a you only look once
% (YOLO) v2 object detector. A YOLO v2 object detection network is composed 
% of two subnetworks. A feature extraction network followed by a detection 
% network. This example generates code for the network trained in the 
% _Object Detection Using YOLO v2 Deep Learning_ example from Computer Vision
% Toolbox(TM). For more information, see
% <docid:vision_examples#mw_2892cd93-fb99-46a8-a8f4-dda46aee6a88 Object Detection Using YOLO v2 Deep Learning>.
% You can modify this example to generate CUDA(R) MEX for the network imported in the
% _Import Pretrained ONNX YOLO v2 Object Detector_ example from Computer
% Vision Toolbox(TM). For more information, see
% <docid:vision_examples#mw_e73a738d-a5ce-4524-b00e-b4814458d217 Import Pretrained ONNX YOLO v2 Object Detector>. 
%
%   Copyright 2017-2018 The MathWorks, Inc.
%% Prerequisites
% * CUDA enabled NVIDIA(R) GPU with compute capability 3.2 or higher.
% * NVIDIA CUDA toolkit and driver.
% * NVIDIA cuDNN library.
% * Environment variables for the compilers and libraries. For information 
% on the supported versions of the compilers and libraries, see 
% <docid:gpucoder_gs#mw_aa8b0a39-45ea-4295-b244-52d6e6907bff
% Third-party Products>. For setting up the environment variables, see 
% <docid:gpucoder_gs#mw_453fbbd7-fd08-44a8-9113-a132ed383275
% Environment Variables>.
% * GPU Coder Interface for Deep Learning Libraries support package. To install
% this support package, use the <matlab:matlab.addons.supportpackage.internal.explorer.showSupportPackages('GPU_DEEPLEARNING_LIB','tripwire') Add-On Explorer>.

%% 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);

%% Get Pretrained DAGNetwork

net = getYOLOv2();

%%
% The DAG network contains 150 layers including convolution, ReLU, and 
% batch normalization layers and the YOLO v2 transform and 
% YOLO v2 output layers. To display an interactive visualization of the 
% deep learning network architecture, use the 
% <docid:nnet_ref#mw_8d52b67d-b6b3-4c62-b573-56fdf4dce6a0 analyzeNetwork> 
% function.
%
%   analyzeNetwork(net);

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

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


%% Run Generated MEX
% Set up the video file reader and read the input video. Create a video
% player to display the video and the output detections.
%
videoFile = 'highway_lanechange.mp4';
videoFreader = vision.VideoFileReader(videoFile,'VideoOutputDataType','uint8');
depVideoPlayer = vision.DeployableVideoPlayer('Size','Custom','CustomSize',[640 480]);
%%
% Read the video input frame-by-frame and detect the vehicles in the video 
% using the detector.
%
cont = ~isDone(videoFreader);
while cont
    I = step(videoFreader);
    in = imresize(I,[224,224]);
    out = yolov2_detect_mex(in);
    step(depVideoPlayer, out);
    cont = ~isDone(videoFreader) && isOpen(depVideoPlayer); % Exit the loop if the video player figure window is closed
end

%%
%
% <<../gpucoder_YOLOv2_output.png>>
%
%% References
% [1] Redmon, Joseph, and Ali Farhadi. "YOLO9000: Better, Faster,
% Stronger." 2017 IEEE Conference on Computer Vision and Pattern 
% Recognition (CVPR). IEEE, 2017.