主要内容

树莓派语音指令识别代码的生成

这个例子展示了如何使用特征提取和卷积神经网络(CNN)对树莓派™进行语音命令识别。为了生成特征提取和网络代码,您使用MATLAB Coder, MATLAB支持包树莓派硬件,和ARM®计算库。金宝app在本例中,生成的代码是Raspberry Pi上的可执行文件,它由一个MATLAB脚本调用,该脚本显示预测的语音命令以及信号和听觉声谱图。MATLAB脚本和树莓派上的可执行文件之间的交互是使用用户数据报协议(UDP)处理的。关于音频预处理和网络培训的详细信息请参见基于深度学习的语音指令识别

先决条件

  • 支持NEON扩展的ARM处理器金宝app

  • ARM计算库版本19.05(在目标ARM硬件上)

  • 编译器和库的环境变量

有关库受金宝app支持的版本以及有关设置环境变量的信息,请参见深度学习与MATLAB编码器的先决条件(MATLAB编码器)

MATLAB中的流演示

使用相同的参数进行特征提取管道和分类基于深度学习的语音指令识别

定义与网络训练相同的采样率(16khz)。定义分类率和每帧输入音频样本的数量。输入到网络的特征是对应1秒音频数据的Bark声谱图。计算了25 ms窗口和10 ms跳数的Bark谱图。计算每个谱图中单个光谱的数量。

fs = 16000;classificationRate = 20;samplesPerCapture = fs / classificationRate;segmentDuration = 1;segmentSamples =圆(segmentDuration * fs);frameDuration = 0.025;frameSamples =圆(frameDuration * fs);hopDuration = 0.010;hopSamples =圆(hopDuration * fs);numSpectrumPerSpectrogram = floor((segmentsamples - framessamples)/hopSamples) + 1;

创建一个audioFeatureExtractor对象提取50波段Bark谱图,无需窗归一化。计算每个谱图中的元素数。

afe = audioFeatureExtractor (...“SampleRate”fs,...“FFTLength”, 512,...“窗口”损害(frameSamples“周期”),...“OverlapLength”frameSamples - hopSamples...“barkSpectrum”,真正的);numBands = 50;setExtractorParams (afe“barkSpectrum”“NumBands”numBands,“WindowNormalization”、假);numElementsPerSpectrogram = numSpectrumPerSpectrogram * numBands;

加载预先训练的CNN和标签。

负载(“commandNet.mat”)标签= trainedNet.Layers(end).Classes;NumLabels =元素个数(标签);backgrounddidx = find(标签==“背景”);

定义缓冲区和决策阈值,用于后期处理网络预测。

probBuffer =单(0 ([NumLabels classificationRate / 2]));YBuffer = single(NumLabels * ones(1, classificationRate/2));countThreshold =装天花板(classificationRate * 0.2);probThreshold =单(0.7);

创建一个audioDeviceReader对象从设备中读取音频。创建一个dsp。AsyncBuffer对象以将音频缓冲为块。

adr = audioDeviceReader (“SampleRate”fs,“SamplesPerFrame”samplesPerCapture,“OutputDataType”“单一”);audioBuffer = dsp.AsyncBuffer (fs);

创建一个dsp。MatrixViewer对象和一个timescope对象以显示结果。

matrixViewer = dsp。MatrixViewer (“ColorBarLabel”“频带功率(dB/频带)”...“包含”“帧”...“YLabel”“汪汪”乐队...“位置”,[400 100 600 250],...“ColorLimits”2.6445 [4],...“AxisOrigin”“左下角”...“名称”基于深度学习的语音指令识别);timeScope = timeScope (“SampleRate”fs,...“YLimits”[1],...“位置”,[400 380 600 250],...“名称”“基于深度学习的语音指令识别”...“TimeSpanSource”“财产”...“时间间隔”,1,...“BufferLength”fs,...“YLabel”“振幅”...“ShowGrid”,真正的);

显示时间范围和矩阵查看器。只要时间范围和矩阵查看器都是打开的,或者直到达到时间限制,就可以检测命令。若要在达到时间限制前停止实时检测,请关闭时间范围窗口或矩阵查看器窗口。

show(timeScope) show(matrixViewer) timlimit = 10;抽搐isVisible(timeScope) && isVisible(matrixViewer) && toc < timeLimit%捕捉音频x = adr ();写(audioBuffer x);fs, y =阅读(audioBuffer fs-samplesPerCapture);计算听觉特征=特征提取(afe y);auditoryFeatures = log10(features + 1e-6);%进行预测probs =预测(trainedNet, auditoryFeatures);[~, YPredicted] = max(probs);%进行统计后处理YBuffer = [YBuffer(2:结束),YPredicted);probBuffer = [probBuffer(:, 2:结束)、聚合氯化铝(:));[YModeIdx, count] = mode(YBuffer);maxProb = max (probBuffer (YModeIdx:));如果YModeIdx == single(BackGroundIdx) || single(count) < countThreshold || maxprobx < probThreshold其他的speechCommandIdx = YModeIdx;结束%更新图matrixViewer (auditoryFeatures ');timeScope (x);如果(spehcommandidx == backgrounddidx)Title =' '其他的timeScope。Title =char(labels(speechCommandIdx));结束drawnowlimitrate结束

隐藏的范围。

隐藏(matrixViewer)隐藏(timeScope)

为部署准备MATLAB代码

要创建一个函数来执行与代码生成兼容的特征提取,调用generateMATLABFunctionaudioFeatureExtractor对象。的generateMATLABFunction对象函数创建一个独立的函数,执行等价的特征提取,并与代码生成兼容。

generateMATLABFunction (afe“extractSpeechFeatures”

HelperSpeechCommandRecognitionRasPi金宝app支持函数封装了前面演示的特征提取和网络预测过程。为了使特征提取与代码生成兼容,特征提取由生成的代码处理extractSpeechFeatures函数。使网络兼容代码生成,支持功能使用金宝appcoder.loadDeepLearningNetwork(MATLAB编码器)命令功能,加载网络。支持函数金宝app使用adsp。UDPReceiver系统对象将树莓派的听觉谱图和预测语音命令对应的索引发送到MATLAB。支持函数金宝app使用dsp。UDPReceiver在MATLAB中接收麦克风捕获的音频的系统对象。

生成可执行文件在树莓派

取代hostIPAddress你的机器地址。你的树莓派发送听觉光谱图和预测语音命令到这个IP地址。

hostIPAddress =编码器。常数(“172.18.230.30”);

创建代码生成配置对象以生成可执行程序。指定目标语言为c++。

cfg = coder.config (exe”);cfg。TargetLang =“c++”

使用Raspberry Pi上的ARM计算库创建一个用于深度学习代码生成的配置对象。指定树莓派的架构,并将深度学习配置对象附加到代码生成配置对象。

dlcfg =编码器。DeepLearningConfig (“arm-compute”);dlcfg。ArmArchitecture =v7的;dlcfg。ArmComputeVersion =“19.05”;cfg。DeepLearningConfig = dlcfg;

使用树莓派支持包功能,金宝appraspi,创建连接到你的树莓派。在以下代码中,替换:

  • raspiname你的树莓派的名字

  • PI与您的用户名

  • 密码用你的密码

r = raspi (“raspiname”“π”“密码”);

创建一个coder.hardware(MATLAB编码器)对象,并将其附加到代码生成配置对象。

hw = coder.hardware (“树莓π”);cfg。硬件= hw;

在树莓派上指定构建文件夹。

buildDir =“~ / remoteBuildDir”;cfg.Hardware.BuildDir = buildDir;

使用自动生成的c++主文件来生成独立的可执行文件。

cfg。GenerateExampleMain =“GenerateCodeAndCompile”

调用codegen(MATLAB编码器)在树莓派上生成c++代码和可执行文件。默认情况下,树莓派应用程序的名称与MATLAB函数相同。

codegen配置cfgHelperSpeechCommandRecognitionRasPiarg游戏{hostIPAddress}报告- v
部署代码。这可能需要几分钟。###编译函数HelperSpeechCommandRecognitionRasPi…------------------------------------------------------------------------ 生成的精灵的位置:/home/pi/remoteBuildDir / MATLAB_ws / R2021b / C / ExampleMatlab / ExampleManager / sporwal.Bdoc21b。### #使用工具链:GNU GCC嵌入式Linux ### # 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\exe\HelperSpeechCommandRecognitionRasPi\HelperSpeechCommandRecognitionRasPi_rtw。### build 'HelperSpeechCommandRecognitionRasPi': make -f HelperSpeechCommandRecognitionRasPi_rtw. ##创建helperspeech commands可所有的  ------------------------------------------------------------------------ ### 生成编译报告……警告:函数“HelperSpeechCommandRecognitionRasPi”不会因为无限循环而终止。Warning in ==> HelperSpeechCommandRecognitionRasPi Line: 86 Column: 1代码生成成功(with warnings):查看报告

初始化应用树莓派

创建一个命令来打开HelperSpeechCommandRasPi覆盆子派的应用.使用系统发送命令给你的树莓派

applicationName =“HelperSpeechCommandRecognitionRasPi”;applicationDirPaths = raspi.utils.getRemoteBuildDirectory (“applicationName”applicationName);targetDirPath = applicationDirPaths {1} .directory;exeName = strcat (applicationName,“.elf”);命令= [“cd”targetDirPath”;。/”exeName' &> 1 &'];系统(r,命令);

创建一个dsp。UDPReceiver系统对象发送音频捕获在MATLAB到您的树莓派。更新targetIPAddress你的树莓派。树莓派接收捕获的音频从同一端口使用dsp。UDPReceiver系统对象。

targetIPAddress =“172.18.228.24”;UDPSend = dsp。UDPSender (“RemoteIPPort”, 26000,“RemoteIPAddress”, targetIPAddress);

创建一个dsp。UDPReceiver系统对象从树莓派接收听觉特征和预测的语音命令索引。从树莓派接收到的每个UDP报文由列主顺序的听觉特征和预测的语音命令索引组成。的最大消息长度dsp。UDPReceiver对象是65507字节。计算缓冲区大小以容纳UDP报文的最大数目。

sizeOfFloatInBytes = 4;maxUDPMessageLength =地板(65507 / sizeOfFloatInBytes);samplesPerPacket = 1 + numElementsPerSpectrogram;numPackets =地板(maxUDPMessageLength / samplesPerPacket);bufferSize = numPackets * samplesPerPacket * sizeOfFloatInBytes;UDPReceive = dsp。UDPReceiver (“LocalIPPort”, 21000,...“MessageDataType”“单身”...“MaximumMessageLength”samplesPerPacket,...“下面的”bufferSize);

通过向运行在树莓派上的可执行文件发送一帧0来减少初始化开销。

UDPSend (0 (samplesPerCapture 1“单身”));

使用部署代码进行语音命令识别

只要时间范围和矩阵查看器都是打开的,或者直到达到时间限制,就可以检测命令。要在达到时间限制之前停止实时检测,请关闭时间范围或矩阵查看窗口。

show(timeScope) show(matrixViewer) timeLimit = 20;抽搐isVisible(timeScope) && isVisible(matrixViewer) && toc < timeLimit%捕获音频并发送到RasPix = adr ();UDPSend (x);%接收来自RasPi的数据包udpRec = UDPReceive ();如果~ isempty (udpRec)%提取预测索引,接收到的UDP报文的最后一个样本speechCommandIdx = udpRec(结束);%提取听觉谱图spec =整形(udpRec(1:numElementsPerSpectrogram), [numBands, numSpectrumPerSpectrogram]);%显示时域信号和听觉谱图timeScope (x) matrixViewer(规范)如果spehcommandidx == backgrounddidx timeScope。Title =' '其他的timeScope。Title =char(labels(speechCommandIdx));结束drawnowlimitrate结束结束隐藏(matrixViewer)隐藏(timeScope)

要停止树莓派上的可执行文件,请使用stopExecutable.释放UDP对象。

stopExecutable (codertarget.raspi.raspberrypi exeName)发布(UDPSend)发布(UDPReceive)

使用PIL工作流配置文件

您可以使用PIL(处理器在循环)工作流来度量Raspberry Pi的执行时间。的ProfileSpeechCommandRecognitionRaspi金宝app支持函数是等价的HelperSpeechCommandRecognitionRaspi函数,只是前者返回语音命令索引和听觉谱图,后者使用UDP发送相同的参数。UDP调用所花费的时间小于1毫秒,与总体执行时间相比相对较小。

创建一个PIL配置对象。

cfg = coder.config (“自由”“是”,真正的);cfg。VerificationMode =“公益诉讼”

设置ARM计算库和架构。

dlcfg =编码器。DeepLearningConfig (“arm-compute”);cfg。DeepLearningConfig = dlcfg;cfg.DeepLearningConfig.ArmArchitecture =v7的;cfg.DeepLearningConfig.ArmComputeVersion =“19.05”

建立与目标硬件的连接。

如果(~ (“r”“var”) r =“raspiname”“π”“密码”);结束hw = coder.hardware (“树莓π”);cfg。硬件= hw;

设置构建目录和目标语言。

buildDir =“~ / remoteBuildDir”;cfg.Hardware.BuildDir = buildDir;cfg。TargetLang =“c++”

启用分析,然后生成PIL代码。一个名为ProfileSpeechCommandRecognition_pil在当前文件夹中生成。

cfg。CodeExecutionProfiling = true;codegen配置cfgProfileSpeechCommandRecognitionRaspiarg游戏{兰德(samplesPerCapture 1 '单')}报告- v
部署代码。这可能需要几分钟。###编译函数ProfileSpeechCommandRecognitionRaspi…### # profile espeechcommandrecogntionraspi函数的连通性配置:###创建'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\ coder假设\lib\ProfileSpeechCommandRecognitionRaspi_ca。可”……### build 'ProfileSpeechCommandRecognitionRaspi_ca': make -f ProfileSpeechCommandRecognitionRaspi_ca. ### # build 'ProfileSpeechCommandRecognitionRaspi_ca':### # create 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\pil\ProfileSpeechCommandRecognitionRaspi_rtw. mk# ###使用工具链:GNU GCC嵌入式Linux可”……### build ' profilespeechcommandrecogntionraspi ': make -f profilespeechcommandrecogntionraspi_rtw . ### # build ' profilespeechcommandrecogntionraspi ': make -f profilespeechcommandrecogntionraspi_rtw . ###/home/pi/ remotebuilddir /MATLAB_ws/R2021b/C/ExampleMatlab/ExampleManager/ sporwall . bdoc21b . mk所有生成elf的位置:j1648568 / deeplearning_shared-ex00376115 codegen / lib / ProfileSpeechCommandRecognitionRaspi /公益诉讼  ------------------------------------------------------------------------ ### 使用工具链: GNU GCC Embedded Linux ### 'C:\ExampleMatlab\ExampleManager\sporwal.Bdoc21b.j1648568\deeplearning_shared-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\ProfileSpeechCommandRecognitionRaspi_rtw.mk' is up to date ### Building 'ProfileSpeechCommandRecognitionRaspi': make -f ProfileSpeechCommandRecognitionRaspi_rtw.mk all ------------------------------------------------------------------------ ### Generating compilation report ... Code generation successful: View report

评估树莓派的执行时间

多次调用生成的PIL函数以获得平均执行时间。

testDur = 50 e - 3;我会= 100;k = 1:numCalls x = pinknoise(fs*testDur,“单一”);[speechCommandIdx, auditoryFeatures] = ProfileSpeechCommandRecognitionRaspi_pil(x);结束
###启动应用程序:'codegen\lib\ProfileSpeechCommandRecognitionRaspi\pil\ProfileSpeechCommandRecognitionRaspi。###启动应用程序profilespeechcommandrecognitionraspii .elf…可以查看执行分析数据。打开仿真数据检查器。终止后可用的执行分析报告。

终止公益诉讼执行。

清晰的ProfileSpeechCommandRecognitionRaspi_pil
###主机应用程序产生以下标准输出(stdout)和标准错误(stderr)消息:

生成执行概要报告以评估执行时间。

executionProfile = getCoderExecutionProfile (“ProfileSpeechCommandRecognitionRaspi”);报告(executionProfile,...“单位”“秒”...“ScaleFactor”“1 e 03”...“NumericFormat”' % 0.4 f '
ans = ' C: \ ExampleMatlab \ ExampleManager \ sporwal.Bdoc21b.j1648568 \ deeplearning_shared-ex00376115 \ codegen \ lib \ ProfileSpeechCommandRecognitionRaspi \ html \ \ ExecutionProfiling_4f9ceee464b795df.html孤儿”

的最大执行时间ProfileSpeechCommandRecognitionRaspi函数几乎是平均执行时间的两倍。您可以注意到执行时间是PIL函数的第一次调用的最大时间,这是由于在第一次调用中发生了初始化。平均执行时间大约为20毫秒,低于50毫秒的预算(音频捕获时间)。性能是在树莓Pi 4模型B Rev 1.1上测量的。