Main Content

生成代码并将 SqueezeNet 网络部署到 Raspberry Pi

此示例说明如何为预训练的 SqueezeNet 网络生成不依赖于任何第三方深度学习库的 C 代码。此示例使用处理器在环 (PIL) 工作流生成 MEX 函数,该函数又从 MATLAB® 调用在 Raspberry Pi™ 硬件中生成的可执行文件。

第三方前提条件

  • Raspberry Pi 硬件

MATLAB Online 不支持此示例。

squeezenet_predict 入口函数

此示例使用 dlnetwork 网络对象来显示图像分类。squeezenet_predict 函数使用 imagePretrainedNetwork 将预训练的 SqueezeNet 网络加载到一个持久性 dlnetwork 对象中。该函数在后续调用中将重用该对象。dlarray 对象是在入口函数中创建的,函数的输入和输出是单精度数据类型。有关详细信息,请参阅 Code Generation for dlarray (MATLAB Coder)

type squeezenet_predict
function out = squeezenet_predict(in) 
%#codegen
% Copyright 2018-2024 The MathWorks, Inc.

    dlIn = dlarray(in,'SSC');
    
    persistent dlnet;
    if isempty(dlnet)
           dlnet = imagePretrainedNetwork('squeezenet');
    end
    
    dlOut = predict(dlnet, dlIn);
        
    out = extractdata(dlOut);
end

创建与 Raspberry Pi 的连接

使用 MATLAB Support Package for Raspberry Pi Hardware 函数 raspi 创建与 Raspberry Pi 的连接。

r = raspi;

如果这是您第一次连接到 Raspberry Pi 板,或者您想连接到另一个不同的板,请使用以下代码行并进行替换:

  • raspiname 替换为您 Raspberry Pi 的主机名

  • username 替换为您的用户名

  • password 替换为您的密码

r = raspi('raspiname','username','password');

为 Raspberry Pi 配置代码生成硬件参数

创建一个 coder.EmbeddedCodeConfig 对象以生成静态库。将 VerificationMode 属性设置为 'PIL' 以启用基于 PIL 的执行。默认情况下,DeepLearningConfig 属性是一个 coder.DeepLearningCodeConfig (MATLAB Coder) 对象,并且目标库设置为 'none'.

cfg = coder.config('lib','ecoder',true);
cfg.VerificationMode = 'PIL';

创建一个 coder.Hardware 对象,并将目标硬件指定为 Raspberry Pi。将硬件对象分配给 cfgHardware 属性。

hw = coder.hardware('Raspberry Pi');
cfg.Hardware = hw;

在 Raspberry Pi 上指定一个编译文件夹。

buildDir = '/home/pi/squeezenet_predict';
cfg.Hardware.BuildDir = buildDir;

生成 PIL MEX 函数

运行 codegen 命令,指定输入大小为 227×227×3。该值对应于 SqueezeNet 网络的输入层大小。

codegen -config cfg squeezenet_predict -args {ones(227, 227, 3, 'single')}
### Connectivity configuration for function 'squeezenet_predict': 'Raspberry Pi'
Location of the generated elf : /home/pi/squeezenet_predict/MATLAB_ws/R2024a/C/EM_Path/ExampleManager/yangzhu.Bdoc.24b/deeplearning_shared-ex98393496/codegen/lib/squeezenet_predict/pil
Code generation successful.

对测试图像执行预测

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

I = imread('coffeemug.png');
I = imresize(I,[227,227]);
output = squeezenet_predict_pil(single(I));
### Starting application: 'codegen\lib\squeezenet_predict\pil\squeezenet_predict.elf'
    To terminate execution: clear squeezenet_predict_pil
### Launching application squeezenet_predict.elf...

将输出值乘以 100 以将分数转换为百分比。在图像上显示排名前五的分类标签。

[val,indx] = sort(output, 'descend');
scores = val(1:5)*100;
[~,classNames] = imagePretrainedNetwork('squeezenet');
top5labels = classNames(indx(1:5));

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

scol = 1;
srow = 20;

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

imshow(imresize(outputImage,[448,800]));

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

清除生成的 PIL 可执行文件

clear squeezenet_predict_pil
### Host application produced the following standard output (stdout) and standard error (stderr) messages: