function net = squeezenet(varargin)
% SQUEEZENET SqueezeNet convolutional neural network
%
% net = SQUEEZENET() returns a pretrained SqueezeNet model that has been trained
% on the ImageNet data set. The output net is a DAGNetwork object.
%
% net = SQUEEZENET('Weights', 'imagenet') returns a pretrained SqueezeNet model 
% that has been trained on the ImageNet data set. The output net is a 
% DAGNetwork object.
%
% lgraph = SQUEEZENET('Weights', 'none') returns the untrained architecture 
% for SqueezeNet model. The output lgraph is a LayerGraph object.
%
% For more pretrained networks, see <a href="matlab:helpview('deeplearning','pretrained_networks')">Pretrained Deep Neural Networks</a>.
%
% References
% ----------
% - Iandola, Forrest, Song Han, Matthew W. Moskewicz, Khalid Ashraf, William J. Dally and Kurt Keutzer.
%   "SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size."
%   In arXiv:1602.07360, 2016.
%
% Example - Use SqueezeNet to classify an image
% ------------------------------------------
% % Load a pretrained SqueezeNet CNN
% net = SQUEEZENET()
% net.Layers
% plot(net)
%
% % Read the image to classify
% I = imread('peppers.png');
%
% % Resize image to the input size of the network
% sz = net.Layers(1).InputSize
% I = imresize(I, sz(1:2));
%
% % Classify the image using SqueezeNet
% label = classify(net, I)
%
% % Show the image and classification result
% figure
% imshow(I)
% text(10, 20, char(label), 'Color', 'white' )
%
% See also DAGNetwork, trainNetwork, trainingOptions, alexnet, vgg16,
% vgg19, googlenet, resnet50, inceptionv3, resnet101, inceptionresnetv2,
% importKerasLayers, importKerasNetwork

%   Copyright 2018-2021 The MathWorks, Inc.

%#codegen

% Parse input arguments
inputArguments = iParseInputArguments(varargin);

if coder.target('MATLAB')
    if strcmp(inputArguments.Weights, 'imagenet')
        % Use tripwire to load ImageNet weights
        net = iTripwireImageNetModel();
    else
        % Use tripwire to load untrained weights
        net = iTripwireUntrainedModel();
    end
else
    % Load squeezenet for code generation
    fnstr = nnet.internal.cnn.coder.getDeepLearningNetworkStr('squeezenet', inputArguments.Weights);
    net = coder.loadDeepLearningNetwork(fnstr, 'squeezenet');
end
end

% Function to load ImageNet model
function net = iTripwireImageNetModel()
matfile = fullfile(fileparts(mfilename("fullpath")), "squeezenet", "data", "squeezenet.mat");
data    = load(matfile);
net     = data.squeezenet;
end

% Function to load untrained model
function net = iTripwireUntrainedModel()
nnet.internal.untrained.squeezenet.assembleSqueezeNetLgraph;
net = lgraph;
end

% Parse input arguments
function inputArguments = iParseInputArguments(varargin)
inputArgs = varargin{:};
if coder.target('MATLAB')
    parser = iCreateParser();
    parser.parse(inputArgs{:});
    % Extract weights
    inputArguments.Weights = validatestring(parser.Results.Weights, ...
        {'imagenet', 'none'});
else
    pnames = {'weights'};
    poptions = struct('CaseSensitivity', false);
    pstruct = coder.internal.parseParameterInputs(pnames, poptions, inputArgs{:});
    defaultWeights = 'imagenet';
    inputArguments.Weights = coder.internal.getParameterValue(pstruct.weights, defaultWeights, inputArgs{:});
    coder.internal.errorIf(~any(strcmpi(inputArguments.Weights, {'imagenet'})), 'nnet_cnn:coder:InvalidArg', 'Weights', 'imagenet');
end
end

% Create parser
function p = iCreateParser()
p = inputParser();
addParameter(p, 'Weights', 'imagenet', @iValidateWeights);
end

% Validate weights
function iValidateWeights(value)
validatestring(value, {'imagenet', 'none'}, mfilename, 'Weights');
end
