主要内容

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

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

先决条件

  • 深度学习库的MATLAB编码器接口

  • ARM处理器,支持NEON扩展万博1manbetx

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

  • 编译器和库的环境变量

有关受支万博1manbetx持的库版本以及有关设置环境变量的信息,请参见用MATLAB编码器进行深度学习的先决条件(MATLAB编码器)

MATLAB流式演示

在特征提取管道和分类中使用相同的参数利用深度学习训练语音指令识别模型

定义与网络训练相同的采样率(16 kHz)。定义分类率和每帧输入音频样本的数量。网络的特征输入是一个Bark谱图,对应于1秒的音频数据。树皮谱图计算为25毫秒窗口和10毫秒跳。计算每个谱图中单个谱的数量。

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

创建一个audioFeatureExtractor对象提取50波段树皮光谱图没有窗口归一化。计算每个谱图中元素的数量。

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

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

负载(“commandNet.mat”)标签= trainedNet.Layers(end).Classes;NumLabels =数字(标签);BackGroundIdx = find(labels ==“背景”);

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

probBuffer = single(0 ([NumLabels,classificationRate/2]));YBuffer = single(NumLabels * ones(1, classificationRate/2));countThreshold = ceil(classificationRate*0.2);probThreshold = single(0.7);

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

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

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

matrixViewer = dsp。MatrixViewer (“ColorBarLabel”每波段功率(dB/ band)...“包含”“帧”...“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) timeLimit = 10;抽搐isVisible(timeScope) && isVisible(matrixViewer) && toc < timeLimit捕获音频X = adr();写(audioBuffer x);y = read(audioBuffer,fs,fs- samplespercapture);%计算听觉特征特征=提取(afe,y);auditoryFeatures = log10(features + 1e-6);%执行预测probs = predict(trainedNet, auditoryFeatures);[~, ypredict] = max(probs);进行统计后处理YBuffer = [YBuffer(2:end), yexpected];probBuffer = [probBuffer(:,2:end),probs(:)];[YModeIdx, count] = mode(YBuffer);maxProb = max(probBuffer(YModeIdx,:));如果YModeIdx == single(BackGroundIdx) || single(count) < countThreshold || maxProb < probThreshold speechCommandIdx = BackGroundIdx;其他的speechCommandIdx = YModeIdx;结束%更新图matrixViewer (auditoryFeatures ');timeScope (x);如果(speechCommandIdx == BackGroundIdx) timeScope。Title =' '其他的timeScope。Title =char(labels(speechCommandIdx));结束drawnowlimitrate结束

把瞄准镜藏起来。

隐藏(matrixViewer)隐藏(timeScope)

准备MATLAB代码部署

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

generateMATLABFunction (afe“extractSpeechFeatures”

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

在树莓派上生成可执行文件

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

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

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

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

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

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

使用树莓派支持包功能,万博1manbetxraspi,以创建与树莓派的连接。在下面的代码中,替换:

  • raspiname树莓派的名字

  • 输入用户名

  • 密码用你的密码

R =树皮(“raspiname”“π”“密码”);

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

Hw = code .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 / R2022a / W /交货/ ExampleManager / sporwal.Bdoc22a。W:\Ex\ExampleManager\ sporwall . bdoc22 .j1844576\ deeplearning_共享-ex00376115\codegen\exe\HelperSpeechCommandRecognitionRasPi\HelperSpeechCommandRecognitionRasPi_rtw。###构建“HelperSpeechCommandRecognitionRasPi”:make -j$(($(nproc)+1)) -Otarget -f HelperSpeechCommandRecognitionRasPi_rtw。可所有的  ------------------------------------------------------------------------ ### 生成编译报告……警告:函数“HelperSpeechCommandRecognitionRasPi”不会因为无限循环而终止。警告在==> HelperSpeechCommandRecognitionRasPi行:86列:1代码生成成功(有警告):查看报告

在树莓派上初始化应用程序

创建一个命令来打开HelperSpeechCommandRasPi应用在树莓派上.使用系统将命令发送到树莓派。

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

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

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

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

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

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

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(end);提取听觉谱图spec =重塑(udpRec(1:numElementsPerSpectrogram), [numBands, numSpectrumPerSpectrogram]);显示时域信号和听觉谱图timeScope (x) matrixViewer(规范)如果speechCommandIdx == BackGroundIdx timeScope。Title =' '其他的timeScope。Title =char(labels(speechCommandIdx));结束drawnowlimitrate结束结束隐藏(matrixViewer)隐藏(timeScope)

stopLiveDetectionRaspi.png

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

stopExecutable(codertarget.raspi.raspberrypi,exeName) release(UDPSend) release(UDPReceive)

使用PIL工作流配置文件

您可以使用Embedded Coder®的处理器在循环(PIL)工作流来测量树莓派上的执行时间。的ProfileSpeechCommandRecognitionRaspi万博1manbetx支撑函数相当于HelperSpeechCommandRecognitionRaspi前者返回语音命令索引和听觉谱图,后者使用UDP发送相同的参数。UDP调用所花费的时间小于1ms,相对于总体执行时间来说是相对较小的。

创建PIL配置对象。

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

设置ARM计算库和架构。

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

设置与目标硬件的连接。

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

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

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

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

cfg。CodeExecutionProfiling = true;codegen配置cfgProfileSpeechCommandRecognitionRaspiarg游戏{rand(samplesPerCapture, 1, 'single')}报告- v
部署代码。这可能需要几分钟。编译函数ProfileSpeechCommandRecognitionRaspi…W:\Ex\ExampleManager\ sporwall . bdoc22a .j1844576\deeplearning_share -ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\coderassumptions\lib\ProfileSpeechCommandRecognitionRaspi_ca。可”……###构建'ProfileSpeechCommandRecognitionRaspi_ca': make -j$(($(nproc)+1)) -Otarget -f ProfileSpeechCommandRecognitionRaspi_ca。W:\Ex\ExampleManager\ sporwall . bdoc22a .j1844576\deeplearning_share -ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\pil\ProfileSpeechCommandRecognitionRaspi_rtw。可”……###构建ProfileSpeechCommandRecognitionRaspi: make -j$(($(nproc)+1)) -Otarget -f ProfileSpeechCommandRecognitionRaspi_rtw。生成elf的位置:/home/pi/ remotebuilddir /MATLAB_ws/R2022a/W/Ex/ExampleManager/ sporwall . bdoc22a . mkallW:\Ex\ExampleManager\ sporwall . bdoc22 .j1844576\ deeplearning_共享-ex00376115\codegen\lib\ ProfileSpeechCommandRecognitionRaspi_rtw. j1844576\ deeplearning_共享-ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\ProfileSpeechCommandRecognitionRaspi_rtw。###构建“ProfileSpeechCommandRecognitionRaspi”:make -j$(($(nproc)+1)) -Otarget -f ProfileSpeechCommandRecognitionRaspi_rtw。可所有的  ------------------------------------------------------------------------ ### 生成编译报告……代码生成成功:查看报告

评估树莓派的执行时间

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

testDur = 50e-3;numCalls = 100;k = 1:numCalls x = pinknoise(fs*testDur,“单一”);[speechCommandIdx, auditoryFeatures] = ProfileSpeechCommandRecognitionRaspi_pil(x);结束
codegen\lib\ProfileSpeechCommandRecognitionRaspi\pil\ProfileSpeechCommandRecognitionRaspi终止执行:clear ProfileSpeechCommandRecognitionRaspi_pil ###启动应用程序profilespeechcommandrecognitionraspi_elf…可以查看执行概要数据。打开模拟数据检查器。终止后可用的执行概要报告。

终止PIL执行。

清晰的ProfileSpeechCommandRecognitionRaspi_pil
###主机应用程序产生以下标准输出(stdout)和标准错误(stderr)消息:执行概要报告:报告(getCoderExecutionProfile('ProfileSpeechCommandRecognitionRaspi')

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

executionProfile = getCoderExecutionProfile(“ProfileSpeechCommandRecognitionRaspi”);报告(executionProfile,...“单位”“秒”...“ScaleFactor”“1 e 03”...“NumericFormat”' % 0.4 f '
ans = 'W:\Ex\ExampleManager\ sporwall . bdoc22 .j1844576\deeplearning_share -ex00376115\codegen\lib\ProfileSpeechCommandRecognitionRaspi\html\ orph\ ExecutionProfiling_d82c7024f87064b9.html'

profiler.png

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

timing.png