Main Content

徽标识别网络

此示例说明如何为使用深度学习的徽标分类应用程序生成代码。它使用名为 LogoNet 的预训练网络,并将一个输入图像分类为 32 个徽标类别。此示例还说明如何使用经过预处理的训练数据集来训练网络。最后,此示例使用 codegen 命令生成 MEX 函数并执行预测。

此示例说明了以下概念:

  • 通过提取徽标并将大小调整为 227×227×3 来预处理训练图像。随后,使用图像增强来增大训练数据大小。

  • 使用具有动量的随机梯度下降 (SGDM) 优化器来训练网络。

  • 生成 CUDA® MEX 并运行该 MEX。

第三方前提条件

必需

此示例生成 CUDA MEX,需要支持 CUDA 的 NVIDIA® GPU 和兼容的驱动程序。

可选

对于非 MEX 编译,如静态、动态库或可执行文件,此示例有以下附加要求。

验证 GPU 环境

使用 coder.checkGpuInstall (GPU Coder) 函数验证运行此示例的编译器和库是否已正确设置。

envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

徽标识别网络

徽标帮助用户进行品牌辨识和识别。许多公司在广告、文档材料和促销活动中使用其徽标。徽标识别网络是在 MATLAB® 中开发的,包含 22 个层。该网络包含四组卷积最大池化层、三个全连接层和降低计算成本的丢弃层。该网络接受大小为 227×227×3 的输入图像,并将其分类为 32 个徽标类别。由于该网络专注于识别,因此可以在不需要定位的应用中使用。通过使用 Flickr32Logos[1] 和 Flickr32 Plus[2] 训练数据集在 MATLAB 中训练该网络。这两个数据集包含每个徽标的大约 200 个图像。通过使用带动量的随机梯度下降 (SGDM) 优化器、0.0001 的学习率、40 轮训练和小批量大小为 45 来训练网络。默认情况下,该示例使用经过预训练的徽标识别网络。借助预训练网络,您无需等待训练完成即可运行整个示例。

要训练网络,请将以下代码中的 doTraining 变量设置为 true。您还必须从徽标识别深度学习下载 Logos-32plus 数据集,并将下载的 Logos-32plus_v1.0.1.zip 文件的位置提供给 logozipPath。Logos-32plus 数据集的大小为 1.95 GB。根据您的 Internet 连接,下载过程可能需要一些时间。该数据集有 32 个图像子文件夹,包含来自不同品牌的总共 7830 个徽标图像。真实值 MAT 文件提供每个图像中徽标的边界框信息。

preprocessLogoData 函数对数据进行预处理以用于网络训练。Logos-32plus 数据集中的图像大小不一。您必须将图像的大小调整为网络的输入层大小 (227×227×3)。图像还包含您必须删除的背景信息。preprocessLogoData.m 通过使用边界框信息提取徽标来执行这些步骤,并创建可用于网络训练的 imageDatastore 对象。trainLogonet 函数创建徽标识别层,并通过使用指定的训练选项来训练网络。使用至少包含每个徽标的 110 个图像的数据来训练该网络。

您还可以使用数据增强来增加训练样本的数量。数据增强有助于防止网络过拟合和记忆训练图像的具体细节。为了增加训练数据,系统提供了四种类型的数据增强:随机翻转、高斯模糊、剪切和对比度归一化。要使用数据增强,请将以下代码中的 doAugmentation 变量设置为 true

doTraining = false;

if ~doTraining
    getLogonet;
else
    logozipPath  = '';% provide path of the downloaded zip file
    zipData = fullfile(logozipPath,'Logos-32plus_v1.0.1.zip');
    unpackedData = fullfile(logozipPath,'Logos32plus');
    
    if ~exist(unpackedData,'dir')
        unzip(zipData,unpackedData);
    end

    doAugmentation = false;
    logoData = preprocessLogoData(unpackedData,doAugmentation);
    trainLogonet(logoData);
end

load('LogoNet.mat');
convnet
convnet = 
  SeriesNetwork with properties:

         Layers: [22×1 nnet.cnn.layer.Layer]
     InputNames: {'imageinput'}
    OutputNames: {'classoutput'}

SeriesNetwork 网络对象转换为 dlnetwork 对象,并将网络保存到 MAT 文件中。

dlconvnet = dag2dlnetwork(convnet);
save dlLogoNet.mat dlconvnet

要查看网络架构,请使用 analyzeNetwork 函数。

analyzeNetwork(dlconvnet)

logonet_predict 入口函数

logonet_predict.m 入口函数以图像作为输入,并使用保存在 dlLogoNet.mat 文件中的深度学习网络对图像执行预测。该函数将 dlLogoNet.mat 中的网络对象加载到持久变量 dlLogonet 中,并在后续的预测调用中重用该持久变量。dlarray 对象是在函数中创建的,函数的输入和输出属于原始数据类型。有关详细信息,请参阅 Code Generation for dlarray (GPU Coder)

type('logonet_predict.m')
function out = logonet_predict(in)
%#codegen

% Copyright 2017-2023 The MathWorks, Inc.

% A persistent object dlLogonet is used to load the network object. At the
% first call to this function, the persistent object is constructed and
% setup. When the function is called subsequent times, the same object is
% reused to call predict on inputs, thus avoiding reconstructing and
% reloading the network object.

dlIn = dlarray(in, 'SSC');

persistent dlLogonet;

if isempty(dlLogonet)
   
    dlLogonet = coder.loadDeepLearningNetwork('dlLogoNet.mat','dlLogonet');

end

dlOut = predict(dlLogonet, dlIn);

out = extractdata(dlOut);

end

logonet_predict 函数生成 CUDA MEX

为 MEX 目标创建一个 GPU 配置对象,并将目标语言设置为 C++。使用 coder.DeepLearningConfig (GPU Coder) 函数创建 CuDNN 深度学习配置对象。将其分配给 GPU 代码配置对象的 DeepLearningConfig 属性。要生成 CUDA MEX,请使用 codegen 命令并指定输入大小为 [227,227,3]。该值对应于 logonet 网络的输入层大小。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
codegen -config cfg logonet_predict -args {ones(227,227,3,'single')} -report
Code generation successful: View report

运行生成的 MEX

加载输入图像。对输入图像调用 logonet_predict_mex

im = imread('test.png');
imshow(im);

Figure contains an axes object. The axes object contains an object of type image.

im = imresize(im, [227,227]);
predict_scores = logonet_predict_mex(single(im));

将排名前五的预测分数映射到 Wordnet 字典 synset 中的单词(徽标)。

synsetOut = convnet.Layers(end).Classes;

[val,indx] = sort(predict_scores, 'descend');
scores = val(1:5)*100;
top5labels = synsetOut(indx(1:5));

显示排名前五的分类标签。

outputImage = zeros(227,400,3, 'uint8');
for k = 1:3
    outputImage(:,174:end,k) = im(:,:,k);
end

scol = 1;
srow = 20;

for k = 1:5
    outputImage = insertText(outputImage, [scol, srow],...
        [char(top5labels(k)),' ',num2str(scores(k),'%2.2f'),'%'],...
        'TextColor', 'w','FontSize',15, 'BoxColor', 'black');
    srow = srow + 20;
end

 imshow(outputImage);

Figure contains an axes object. The axes object contains an object of type image.

清除内存中已加载的静态网络对象。

clear logonet_predict_mex;

参考资料

[1] Romberg, Stefan, Lluis Garcia Pueyo, Rainer Lienhart, and Roelof van Zwol."Scalable Logo Recognition in Real-World Images." ACM International Conference on Multimedia Retrieval 2011 (ICMR11):1-8. https://doi.org/10.1145/1991996.1992021

[2] Bianco, Simone, Marco Buzzelli, Davide Mazzini, and Raimondo Schettini."Deep Learning for Logo Recognition."Neurocomputing 245 (2017):23-30. https://doi.org/10.1016/j.neucom.2017.03.051.

相关主题