嵌入式linux物联网毕业设计项目智能语音识别基于stm32mp157开发板
stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux+单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2个Cortex-A7核和1个Cortex-M4 核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统。开发板搭配仿真器、显示屏、摄像头、资源扩展板等丰富的扩展模块,可拓展物联网、人工智能等相关技术学习,还可以拓展丰富的项目实战,非常贴合企业当下开发需求,是一款嵌入式Linux入门进阶必备开发板!
可学习技术:嵌入式Linux应用/系统/驱动开发、ARM裸机开发、Qt界面编程、STM32单片机、FreeRTOS、人工智能机器视觉等。其中ARM Cortex-A7裸机开发课程是华清远见独有特色课程,可关注:https://www.bilibili.com/video/BV1Xe4y1i7vm/,持续更新中。
14个Linux+Qt综合项目案例,6个MP1A物联网拓展项目
关注公众号“华清远见在线实验室”,回复“mp157项目”,即可领取项目配套文档及源码。
Linux+Qt综合项目案例:华清远见stm32mp157开发板优势特色部分,包括音乐播放器、智慧家庭、智能工业电表、智能出行助手、智能猫眼、环境监测、智能安防、智能语音识别等10余个项目案例,涉及家居、医疗、农业多种应用方向,在案例中使用了多种物联网和嵌入式技术,包括OT开发、linux应用开发、linux驱动开发、物联网云端接入、MQTT协议、json字符串等知识点。
基于Linux+Qt的智能语音识别项目
项目简介:
语言是人与人之间最重要的交流方式、能与机器进行自然的人机交流,是人类一直期待的事情。随着人工智能快速发展。语音识别技术作为人机交流接口的关键技术、发展迅速。本项目调用百度 AI 开发平台 API 进行语音识别,进行语音控制传感器的联动。
开发平台:
华清远见stm32mp157开发板豪华套餐(开发板+仿真器+五寸屏+摄像头+资源扩展板+tf卡+读卡器)
项目实战:
Qt 开发环境搭建
主机开发环境说明
1) 本文档主要介绍 linux 环境下的 Qt 程序开发;
2) 主机 Qt 版本为 5.14.1;
主机 Qt 环境搭建及使用
Qt Creator 安装
将 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 实验源码\工具软件) 复制到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp方式将文 件存入家目录下的 Downloads 目录。我们需要在终端中赋予安装程序可执行的权限
我们可以使用图形化的文件管理器来查看
双击“qt-creator-opensource-linux-x86_64-4.10.1.run”图标运行安装程序。出现如下界面:
等待程序验证完成后点击“Next”
这里我们需要登录或者注册一个账号,如果我们之前已经注册过直接登录就可以。如果没有注册过则需要新注册有一个账号后登录。这里笔者已经注册过账号,所以直接登录。 登录成功后出现如下界面,点击 Next
这里选择安装路径
可以直接默认,Next
这路选择安装的组件,直接默认即可
这里我们需要同意用户协议
这个界面告诉我们安装完成后需要占用的空间。点击”Install”按钮后开始安装。
安装完成后出现如下界面
点击“Finish”按钮后将弹出 Qt Creator 主界面
点击“Cancel”按钮后即可正常使用
Qt5.14.1 安装
复制到 qt-opensource-linux-x64-5.14.1.run(Qt 实验源码\工具软件)到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp 方式将文件存入家目录下的 Downloads 目录。进入所在文件夹,先给执行权限
输入命令
chmod +x ./qt-opensource-linux-x64-5.14.1.run
安装在命令行输入
./qt-opensource-linux-x64-5.14.1.run
会有可视化引导安装,一直 next 就行了
在选择安装组件的时候要是不知道选择那些就全选了 大概有 4 个 G 左右
下载 gcc 和 g++
sudo apt-get install gcc g++
下载 cmake
sudo apt-get install cmake
下载链接库
sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev
Qt Creator 配置
1)配置 GCC
运行 QtCreator 后,依次点击"Tool"->"Options",出现选项对话框,在左侧点击"Kits",右 边选择"Compilers"标签。 检查有没有下图标注的 C++和 C ,般按上面步骤执行后都会有
点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C"
填写信息如下,"Name"为"Auto-GCC","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是 “/usr/bin/gcc”
2)配置 G++
点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C++",下面的文本框填写"Name" 为"Auto-G++","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是" /usr/bin/g++"。
填写完成后,点击"Apply"。
3)配置 qmake
选择"Qt Versions"标签,如果有下面红框中的文本,可以跳过下面步骤
如果没有,在右侧点击"Add..."
会弹出 qmake 路径选择对话框,这里以"/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"为例子。 选择”qmake”文件后,点击"Open"按钮
"Version name"改为" Qt %{Qt:Version} GCC"。然后点击"Apply"按钮。
4)配置 Kits
点击左侧"Kits",右侧选择"Kits"标签。检查有没有下图红框选中的文本,如果有可以跳过下面步骤
然后没有,点击 Add:
在弹出的对话框中"Name"为"Desktop","Device Type"选择"Desktop"选项, "Sysroot"选择目标设备的系统目录,"Compiler"选择之前配置的名称"Auto-GCC"和"Auto-G++","Qt version"选择之前配 置的名称"Qt 5.14.1GCC",其它默认即可,最后点击"Apply"和"OK"按钮。
Qt Creator 新建工程
注意:工程路径最好不要包含中文、特殊字符、空格等。
我们可以新建一个“qt”文件夹,该文件夹用作我们以后存放源代码。
打开 Qt Creator,在欢迎页面点击 “New”按钮,来新建一个工程。
在出现的新建项目窗口中,我们选则“Application”->“Qt WidgetsApplication”,然后点击右下方“Choose…”按钮,来创建一个桌面 Qt 应用。
我们在这里设置项目介绍和源码位置,我们这里创建一个名为“HelloWorld”的示例项目,设置完成之后点击 next
直接点击 next
随后进行细节设置,主要设置要创建的源码文件的基本类信息,包括类名等。这里我们可以根据自己的项目特点进行设置。需要说明的一点就是基类的选择,这里基类有 QMainWindow、QWidget、QDialog 三种,它们的不同之处如下:
QMainWindow 类提供一个带有菜单条,工具条和一个状态条的主应用程序窗口。主窗口通常提供一个大的中央窗口部件,以及周围菜单,工具条,和一个状态栏。QMainWindow 窗口经常被继承,使得封装中央部件,菜单,工具条,状态栏等都变得很容易,当用户点击它的时候,相应的槽就会被调用;
QWidget 类是所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。一个窗口部件可以被他的父窗口或者是其他窗口挡住一部分;
QDialog 类是对话框窗口的基类,对话框窗口主要用于短期任务和用户进行短期通讯的顶级窗口,QDialog 可以是模态对话框或者是非模态对话框。QDialog 支持扩展并带有返回值,他们可以带有默认值;我们在这里选择 QDialog 类即可,点击 next 完成类信息设置。
直接点击 next 按钮即可。
然后进行工具选择,该页面可以选择我们创建的工程可以使用的工具,选择想要使用的编译器模块,例如下图 。点击 next
最后我们设置汇总信息,如果不需要版本控制等功能,直接点击完成finish 即可。
随后我们就进入到了主界面,这时候 Qt 已经帮我们做好了一些准备工作,包括创建了一些文件,写好了一些前置代码等等。
我们可以点击左边 protect 栏,来查看我们的编译选项。
我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。
左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来。
点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。
Qt Creator导入工程
我们可以将已存在的 Qt 程序项目直接打开,这里以上一章节的HelloWorld 程序为例。首先我们确定源码存在的位置,如 HelloWorld 程序源码在 /home/linux/qt/helloworld 路径下
点击欢迎页面的“Open” 按钮可以打开已有的工程
找到我们刚才解压好的源码,选择“helloworld.pro”文件并点击打开
接下来我们就可以进入到代码编辑界面了。
左上角是项目栏,点击项目名称左边的小箭头可以展开项目目录
我们可以点击左边项目栏,来查看我们的编译选项。需注意的是构建设置中的路径应与工程路径处于同级目录下。
我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。
左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来
点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。
文件说明
通过上面两个章节,我们学习到了 Qt 程序的新建与导入的方法,也知道了Qt 会帮我们做一些基础工作,比如帮我们建立了一些文件,那么这些文件都是干什么用的呢?我们以 HelloWorld 程序来说明一下。
以“.pro”为后缀名的文件,为 Qt 的项目管理文件,存储项目设置的文件;
“Qt += core gui”表示项目中加入 core gui 模块。core gui 是 Qt 用于GUI 设计的类库模块,如果创建的是控制台(console)应用程序,就不需要添加 core gui。
Qt 类库以模块的形式组织各种功能的类,根据项目涉及的功能需求,在项目中添加适当的类库模块支持。例如,如果项目中使用到了涉及数据库操作的类就需要用到 sql(数据库)模块,在 pro 文件中需要在后面加上 sql:
1 Qt += core gui sql
“greaterThan(QT_MAJOR_VERSION, 4): QT += widgets”,这是个条件执行语句,表示当 Qt 主版本大于 4 时,才加入 widgets 模块。“TARGET = HelloWorld”表示生成的目标可执行文件的名称,即编译后生成的可执行文件是 HelloWorld.exe。
“TEMPLATE = app”表示项目使用的模板是 app,是一般的应用程序。
后面的 SOURCES、HEADERS、FORMS 记录了项目中包含的源程序文件、头文件和窗体文件(.ui 文件)的名称。这些文件列表是 Qt Creator 自动添加到项目管理文件里面的,用户不需要手动修改。当添加一个文件到项目,或从项目里删除一个文件时,项目管理文件里的条目会自动修改。
文件夹“Header”中,存放的是所设计的窗体类的头文件;
文件夹“Sources”中,存放着源码文件。main.cpp 是实现 main()函数的程序文件,HelloWorld.cpp 是 widget.h 里定义类的实现文件。C++中,任何窗体或界面组件都是用类封装的,一个类一般有一个头文件(.h 文件)和一个源程序文件(.cpp 文件);
文件夹“Forms”中,存放着界面设计文件,“.ui”文件是一个 XML 格式存储的窗体上的元件及其布局的文件,双击项目文件目录树中的文件 ui,会打开一个集成在 Qt Creator 中的 Qt Designer 对窗体进行可视化设计;
UI 设计器有以下一些功能区域:
组件面板:窗口左侧是界面设计组件面板,分为多个组,如 Layouts、Buttons、Display Widgets 等,界面设计的常见组件都可以在组件面板里找到。
中间主要区域是待设计的窗体。如果要将某个组件放置到窗体上时,从组件面板上拖放一个组件到窗体上即可。
Signals 和 Slots 编辑器与 Action 编辑器是位于待设计窗体下方的两个编辑器。Signals 和 Slots 编辑器用于可视化地进行信号与槽的关联,Action 编辑器用于可视化设计 Action。
布局和界面设计工具栏:窗口上方的一个工具栏,工具栏上的按钮主要实现布局和界面设计。
对象浏览器(Object Inspector):窗口右上方是 Object Inspector,用树状视图显示窗体上各组件之间的布局包含关系,视图有两列,显示每个组件的对象名称(ObjectName)和类名称。
属性编辑器(Property Editor):窗口右下方是属性编辑器,是界面设计时最常用到的编辑器。属性编辑器显示某个选中的组件或窗体的各种属性及其取值,可以在属性编辑器里修改这些属性的值。属性编辑器的内容分为两列,左侧为属性的名称,右侧为属性的值。属性又分为多个组,实际上表示了类的继承关系,位于下方的类属性组继承自位于上方的类属性组;
如果我们需要新建资源文件、源码文件等,可以在项目文件夹出点击鼠标右键,选择 Add New;如果我们有新的文件需要添加,可以在项目文件夹出点击鼠标右键,选择 Add Existing Files。
帮助文档
Qt 的帮助文档是伴随我们学习 Qt 开发的好伙伴。在 Qt 开发过程中,我们会面临图形接口使用的问题,它不像 C 语言那样就那么几个函数接口,图形接口的接口数量可以用海量来形容,常用的我们可能能记住,其它的就没有必要去记了,用到什么就去帮助文档查看用法是比较方便的。我们可以按 F1 按键,或通过上方导航栏的“help->contects”来进入帮助文档。
上方的前进后退按钮方便我们查看文档,如返回到上一步,返回到下一步。
我们可以通过帮助文档来查看以下几个部分:
类使用的相关介绍;
查看相关类的使用介绍,我们可以先进入到帮助文档,然后在左上角选择“Search”。笔者这里以 QWidget 类为例,输入我们想要查找的类的名字,然后双击查找结果来查看说明。
也可以先将鼠标移动到想要查询的类的位置,如图所示,将鼠标移动至“QWidget”处,然后按“F1”键,即可跳转到相应的帮助文档。
我们可以通过再按一次“F1”键来全窗口查看帮助文档,按“Esc”键可以退出。
部分常用的成员元素包括以下几项:
公有成员函数:操作部件属性的相关函数;
公有槽函数:Qt 类中已经定义好的槽函数,直接可与信号相连接;
信号:软中断,如按下按钮触发 pressed() 信号等;
保护成员函数:通常事件所对应的虚函数放在此处;
事件:常用事件,如操作鼠标触发的鼠标事件;
滚动鼠标滚轮,向下即可看到“Qwdget Class”类的相关说明了。
部分常用的成员元素包括以下几项:
公有成员函数:操作部件属性的相关函数;
公有槽函数:Qt 类中已经定义好的槽函数,直接可与信号相连接;
信号:软中断,如按下按钮触发 pressed() 信号等;
保护成员函数:通常事件所对应的虚函数放在此处;
事件:常用事件,如操作鼠标触发的鼠标事件;
滚动鼠标滚轮,向下即可看到“Qwdget Class”类的相关说明了。
1) 查看所用的部件的相应成员函数。
我们可以查找到该类所用部件的相应成员函数的使用方法、功能、参数、返回值等等,我们以“按钮”控件,即“QPushButton Class”类为例,我们通过索引搜索的方式,来找到这个类
我们可以通过点击“Public Functions” 来查看“QPushButton”这个类中的成员函数。
这里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”为例,我们点击函数名字可以进入到函数详情中。我们可以看到相应的描述为:以“text”为显示内容,以“parent”为父对象,构造一个push 按钮。“text”“parent”为函数参数,由于是构造函数,所以此函数没有返回值。
还有一些函数是继承自其它类的,例如“Public Functions”中有 21 个继承自“QAbstractButton”类的函数,我们点击“QAbstractButton”即可查看。击“QAbstractButton”即可查看
同样我们可以点击相应的函数进入查看详情。如查看“voidsetText(const QString &text)”。
2) 查看所用的部件的信号。
我们这里还是以“PushButton”为例,我们点击“Public Slots”。
可以看到“PushButton”本身有一个“void showMenu()”的信号,并且有很多继承自其他类的信号。
一般来说我们用的“PushButton”的信号,最多的是用到其继承自基类“QAbstractButton”中的几个信号,分别是点击(按下后抬起)、按压(单按下)、释放(单抬起)等
我们可以点击相应信号查看详情
3) 查看所用的部件的事件(所对应的虚函数如何编写)。部件常用事件主要在 “QWidget”中声明,选择“Events”即可查看相关说明。
每个事件都对应着事件函数。
点击事件函数可查看详情
UI 界面设计
Ui 界面设计如下:
由于我们配置的七寸屏幕是 1024*768 分辨率的,所以我们的 MainWindow主界面的尺寸设置为 1024*768。共使用如下几个控件,使用 QTextEdit 控件textEdit 来显示语音识别后返回的最佳匹配语音。使用 QPushButton 控件pushButton_video 点击录音和释放识别,使用 pushButton_clear 来清空 QtextEdit的内容,使用 textEdit_2 来显示传感器的反馈。
录音
在 pro 文件添加
QT += network
QT += multimedia
在 mainwindow.h 头文件添加下面定义
void RecorderStart(QString fileName);//开始录音
void RecorderEnd();//结束录音并转换格式
QFile *outFile;//录音时的变量
QAudioInput *my_audio;//录音时的变量
QAudioFormat audioFormat;//录音时的变量
Mainwindow.cpp 录音函数实现:
void MainWindow::RecorderStart(QString fileName)
{
QAudioDeviceInfo device = QAudioDeviceInfo::defaultInputDevice();
if(device.isNull())
{
QMessageBox::warning(NULL,"QAudioDeviceInfo","录音设备不存
在");
return;
}
// 设置通道数
audioFormat.setChannelCount(1);
// 设置编码
audioFormat.setCodec("audio/pcm");
// 设置采样频率
audioFormat.setSampleRate(16000);
// 设置位深
audioFormat.setSampleSize(16);
// 判断设备是否支持该格式
if(!device.isFormatSupported(audioFormat)){ //当前使用设备是否支持
audioFormat = device.nearestFormat(audioFormat); //转换为最接近格
式
}
// 创建录音对象
my_audio = new QAudioInput(audioFormat,this);
outFile = new QFile;
outFile->setFileName(fileName); //语音原始文件
outFile->open(QIODevice::WriteOnly);
// 开始录音
my_audio->start(outFile);
}
结束录音函数实现
/**********************
* 结束录音并转换格式
**********************/
void MainWindow::RecorderEnd()
{
// 结束录音
my_audio->stop();
outFile->close();
delete outFile;
outFile =NULL;
delete my_audio;
my_audio = NULL;
}
点击释放按钮槽函数
右键按钮,转到槽,选择 pressed 和 released 点击 ok。会在 mainwindow.cpp
生成 on_pushButton_video_pressed()和 on_pushButton_video_released()槽函数。
在两个槽函数分别实现如上图所示
申请百度 AI 开发平台语音识别应用
语音识别是利用百度的 API 在线识别。所以需要申请项目 ID。
进入百度的 API 平台:https://ai.baidu.com/
在产品服务下选择语音识别:
点击立即使用:
申请账号点击登录:
点击创建应用:
输入应用名称、应用描述,点击立即创建:
点击返回应用列表:
获取 AppID、API Key 和 Secret Key:
我们记住其中的 API Key 和 Secret Key,下面会用到。
HTTP 请求类实现
我们录好的音频文件需要通过 HTTPS 协议上传到百度 AI 开发平台进行语音识别,之后 AI 平台会返回给我们识别的结果。
http 类只需要封装一个方法
bool post_sync(QString url,QMap<QString,QString>header,QByteArray
requestData,QByteArray &replyData);
使用这个方法去 URL 发送请求会收到 URL 的返回值。
http.h
#ifndef HTTP_H
#define HTTP_H
#include <QObject>
#include <QMap>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QEventLoop>
#include <QDebug>
class Http : public QObject
{
Q_OBJECT
public:
explicit Http(QObject *parent = nullptr);
bool post_sync(QString url,QMap<QString,QString>header,QByteArray
requestData,QByteArray &replyData);
};
#endif // HTTP_H
http.cpp
这个方法的第一个参数是 post 方法发送请求的 URL,第二个参数是请求的方法头,第三个参数是请求的数据,第四个参数是返回的数据。
这里要说的是必须要设置 openssl 签名配置,否则在 ARM 上会报错。
bool Http::post_sync(QString url,QMap<QString,QString>header,QByteArray
requestData,QByteArray &replyData)
{
// 发送请求的对象
QNetworkAccessManager manager;
// 请求 对象
QNetworkRequest request;
request.setUrl(url);
QMapIterator<QString,QString> it(header);
while (it.hasNext()) {
it.next();
request.setRawHeader(it.key().toLatin1() ,it.value().toLatin1());
}
//设置 openssl 签名配置,否则在 ARM 上会报错
QSslConfiguration conf = request.sslConfiguration();
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
conf.setProtocol(QSsl::TlsV1_0);
#else
conf.setProtocol(QSsl::TlsV1);
#endif
request.setSslConfiguration(conf);
QNetworkReply *reply = manager.post(request,requestData);
QEventLoop l;
//一旦服务器返回,reply 会发出信号
connect(reply,&QNetworkReply::finished,&l,&QEventLoop::quit);
l.exec();
if(reply != nullptr && reply->error() == QNetworkReply::NoError)
{
replyData = reply->readAll();
return true;
}
else
{
qDebug()<<"request error!";
return false;
}
}
发送请求
这里需要向两个 URL 发送两个请求,第一个请求是把我们 4.2.3 创建应用得到的 API Key 和 Secret Key 组合成一个 URL 获取 access_token,第二个请求是把音频文件发送请求到语音识别的 URL 才能返回语音识别的结果。
我们新建一个类 Speech
Speech.h
这里我们把 API Key 和 Secret Key 作为参数传到 const QString
baiduTokenUrl 里面去。把主机名和获取的 access_token 做为参数传入 const
QString baiduSpeechUrl。
#include <QObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QFile>
#include "http.h"
#include <QHostInfo>
// 获取 Access Token
const QString baiduTokenUrl =
"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=
%1&client_secret=%2&";
const QString client_id = "我们创建应用的 API Key";
const QString client_secret = "我们创建应用的 Secret Key";
// 语音识别 url
const QString baiduSpeechUrl =
"https://vop.baidu.com/server_api?dev_pid=1537&cuid=%1&token=%2";
class Speech:public QObject
{
Q_OBJECT
public:
Speech();
QString speechIdentify(QString fileName);
private:
QString getJsonValue(QByteArray ba,QString key);
};
#endif // SPEECH_H
Speech.cpp
QString Speech::speechIdentify(QString fileName)
{
// 获取 Access Token
QString tokenUrl =QString(baiduTokenUrl).arg(client_id).arg(client_secret);
Http my_http;
QMap<QString,QString>header;
header.insert(QString("Content-Type"),QString("audio/pcm;rate=16000"));
QByteArray requestData;//请求内容
QByteArray replyData;//url 返回内容
qDebug()<<tokenUrl;
bool result = my_http.post_sync(tokenUrl,header,requestData,replyData);
if(result) {
QString key = "access_token";
QString accessToken =getJsonValue(replyData,key);
qDebug()<<accessToken;
// 语音识别
QString speechUrl =
QString(baiduSpeechUrl).arg(QHostInfo::localHostName()).arg(accessToken);
QFile file;
file.setFileName(fileName);
file.open(QIODevice::ReadOnly);
requestData = file.readAll();
file.close();
replyData.clear();
// 再次发起请求
result = my_http.post_sync(speechUrl,header,requestData,replyData);
if(result) {
QString key = "result";
QString retText =getJsonValue(replyData,key);
qDebug()<<retText;
return retText;
}
else{
return NULL;
}
}
else {
return "error";
}
}
解析返回的数据
返回的数据是这种 Json 类型的,我们只需要获取里边 result 的值就能得到我们想要的结果了。
{"err_no":0,"err_msg":"success.","corpus_no":"15984125203285346378","sn":"
481D633F-73BA-726F-49EF-8659ACCC2F3D","result":["北京天气"]}
QString Speech::getJsonValue(QByteArray ba,QString key)
{
QJsonParseError parseError;
QJsonDocument jsondocument =
QJsonDocument::fromJson(ba,&parseError);
if(parseError.error ==QJsonParseError::NoError)
{
if(jsondocument.isObject())
{
QJsonObject jsonObject = jsondocument.object();
if(jsonObject.contains(key)){
QJsonValue jsonvalue = jsonObject.value(key);
if(jsonvalue.isString())
return jsonvalue.toString();
else if(jsonvalue.isArray()){
QJsonArray arr = jsonvalue.toArray();
QJsonValue val =arr.at(0);
return val.toString();
}
}
}
}
return "";
}
MainWindow 类调用函数
我们在释放按钮的槽函数里添加以下代码。
void MainWindow::on_pushButton_video_released()
{
ui->pushButton_video->setText("按住说话");
RecorderEnd();
Speech my_speech;
QString text =my_speech.speechIdentify("./1.pcm");
ui->textEdit->append(text);
audioCtrl(text);
}
语音控制设备联动
代码如下
void MainWindow::audioCtrl(QString text)
{
if(text == "开灯。")
{
system("echo 1 >/sys/class/leds/user1/brightness");
system("echo 1 >/sys/class/leds/user2/brightness");
system("echo 1 >/sys/class/leds/user3/brightness");
ui->textEdit_2->setText("灯已打开");
}
else if(text == "关灯。")
{
system("echo 0 >/sys/class/leds/user1/brightness");
system("echo 0 >/sys/class/leds/user2/brightness");
system("echo 0 >/sys/class/leds/user3/brightness");
ui->textEdit_2->setText("灯已关闭");
}
else if(text == "报警。")
{
int fd;
struct input_event event;
struct timeval time;
fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);
event.type = EV_SND;
event.code = SND_TONE;
event.value = 1000;
time.tv_sec = 1;
time.tv_usec = 0;
event.time = time;
write(fd, &event, sizeof(struct input_event));
ui->textEdit_2->setText("蜂鸣器已报警");
}
else if(text == "关闭。")
{
int fd;
struct input_event event;
struct timeval time;
fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);
event.type = EV_SND;
event.code = SND_TONE;
event.value = 0;
time.tv_sec = 0;
time.tv_usec = 0;
event.time = time;
write(fd, &event, sizeof(struct input_event));
ui->textEdit_2->setText("蜂鸣器报警已关闭");
}
else if(text == "关风扇。")
{
unsigned char arg;
Ioctl(EXIT_FAN,&arg);
ui->textEdit_2->setText("风扇已关闭");
}
else if(text == "开风扇。")
{
unsigned char arg;
Ioctl(EXIT_FAN,&arg);
Ioctl(INIT_FAN,&arg);
Ioctl(FAN_UP,&arg);
ui->textEdit_2->setText("风扇已打开");
}
else if(text == "温度。")
{
QString tem = temCollect();
ui->textEdit_2->setText(QString(" 此 时 温 度
为:").append(tem).append("'C"));
}
else if(text == "湿度。")
{
QString hum = humCollect();
ui->textEdit_2->setText(QString(" 此时湿度
为:").append(hum).append("%"));
}
}
实验源码
源码路径【10_智能语音识别\实验源码\04-Aivideo】
注意事项
1.在开发板运行时,需要导入中文字库,否则会因为识别不了中文。
将【10_智能语音识别\工具软件\wqy-zenhei-0.9.47-
nightlybuild.tar.gz 或 wqy-zenhei-0.8.38-1.tar.gz】复制到 ubuntu 下。并使用 scp 命令将文件拷贝到开发板的 usr/share/fonts 目录下,使用 tar 命令解压后即可。
linux@ubuntu:~$ scp wqy-zenhei-0.8.38-1.tar.gz
root@192.168.10.128:/usr/share/fonts/
2.如果使用 mipi 五寸屏运行此项目,需要进行屏幕旋转以适应屏幕,具体步骤如下:
在/etc/profile.d/qt-eglfs.sh 添加环境变量如下
下面变量的 event0 设备需要填实际的触摸屏设备
这里即填 event0
export QT_QPA_EGLFS_ROTATION=90
export QT_QPA_EGLFS_NO_LIBINPUT=1
export
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=90
相关文章:
嵌入式linux物联网毕业设计项目智能语音识别基于stm32mp157开发板
stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2个Cortex-A7核和1个Cortex-M4 核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRT…...
【黄河流域公安院校网络空间安全技能挑战赛】部分wp
文章目录webbabyPHPfunnyPHPEzphp**遍历文件目录的类**1、DirectoryIterator:2、FilesystemIterator:3、**Globlterator**读取文件内容的类:SplFileObjectMisc套娃web babyPHP <?php highlight_file(__FILE__); error_reporting(0);$num $_GET[nu…...
五点CRM系统核心功能是什么
很多企业已经把CRM客户管理系统纳入信息化建设首选,用于提升核心竞争力,改善企业市场、销售、服务、渠道和客户管理等几个方面,并进行创新或转型。CRM系统战略的五个关键要点是:挖掘潜在客户、评估和培育、跟进并成交、分析并提高…...
window.print() 前端实现网页打印详解
目录 前言 一、print()方法 二、打印样式 2.1使用打印样式表 2.2使用媒介查询 2.3内联样式使用media属性 2.4在css中使用import引入打印样式表 三、打印指定区域部分内容 3.1方法一 3.2方法二 3.3方法三 四、强制插入分页 4.1page-break-before(指定元素前…...
php程序员应具有的7种能力
php程序员应具有什么样的能力,才能更好的完成工作,才会有更好的发展方向呢?在中国我想您不会写一辈子代码的,那样不可能,过了黄金期,您又怎么办呢?看了本文后,希望对您有所帮助。 一…...
quarkus 生产环境与k8s集成总结
quarkus 生产环境与k8s集成总结 大纲 基础准备quarkus2.13.7脚手架工程配置GraalVM-java11 安装配置配置maven3.8.7linux环境下云原生二进制文件打包环境搭建编译运行quarkus二进制文件quarkus二进制文件制作为docker镜像并运行使用k8s部署quarkus二进制文件 基础准备 生产…...
蓝桥杯训练day2
day21.二分(1)789. 数的范围(2)四平方和(1)哈希表做法(2)二分做法(3)1227. 分巧克力(4)113. 特殊排序(5)1460. 我在哪?2.双指针(1)1238. 日志统计(2)1240. 完全二叉树的权值(3&#…...
为什么99%的程序员都做不好SQL优化?
连接层 最上层是一些客户端和链接服务,包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于 TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程 池的概念,为通过认证安全接入的客户端提供线程。同样…...
Jenkins最新版安装调试
清理旧的jenkins: find / -name jenkins* 一项一项的清理:rm -rf /var/log/jenkins* 下载最新版jenkins镜像:jenkins-redhat-stable安装包下载_开源镜像站-阿里云 上传到服务器: 安装命令: yum install -y jenkins…...
简略说一下go的sync.RWMutex锁
在简略的说之前,首先要对RW锁的结构有一个大致的了解 type RWMutex struct {w Mutex // 写锁互斥锁,只锁写锁,和读锁无关writerSem uint32 // sema锁--用于“写协程”排队等待readerSem uint32 // sema锁--用于“读协程”排队…...
软考马上要报名了,出现这些问题怎么办?
目前,四川、山东、山西、辽宁、河北等地已经率先发布了2023年上半年软考报名通知。 四川:2023年3月13日-4月4日 山东:2023年3月17日9:00-4月3日16:00 山西:2023年3月14日9:00-3月28日11:00 辽宁:2023年3月14日8:30…...
单链表(增删查改)
目录一、什么是单链表?二、单链表的增删查改2.1 结构体变量的声明2.2 申请新结点2.2 链表的头插2.3 链表的尾插2.4 链表的头删2.5 链表的尾删2.6 链表的查找2.7 链表的任意位置后面插入2.8 链表的任意位置后面删除2.9 链表的销毁2.10 链表的打印三、代码汇总3.1 SLi…...
端口复用(bind error: Address already in use 问题)
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 端口复用专栏:《Linux从小白到大神》《网络编程》 在前面讲解TCP状态转换中提到过一个2MSL…...
数字化引领乡村振兴,VR全景助力数字乡村建设
一、数字乡村建设加速经济发展随着数字化建设的推进,数字化农业产业正在成为农业产业发展的主导力量,因此数字化技术赋予农业产业竞争力的能力不可小觑。数字化乡村建设背景下,数字化信息技术将全面改造升级农村产业,从农业、养殖…...
【数据结构入门】-链表之双向循环链表
个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【数据结构初阶(C实现)】 文章目录链表初始化打印链表尾插尾删新建一个节点头插头删查找在pos之前插入*删除pos位…...
Jenkins自动化部署入门
Jenkins自动化部署入门 一、简介 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。 Jenkins自动化部署实现原理 二、Jenkins部…...
Springboot 读取模板excel信息内容并发送邮件, 并不是你想想中的那么简单
Springboot 读取模板excel信息内容并发送邮件 背景技术选型搭建过程数据加密隐藏问题暴露背景追溯解决背景 在我们日常开发中, 会遇到这样一种场景, 就是读取表格中的数据, 并将数据以附件的形式通过邮箱发送到表格中的每个人 即: excel 读取 excel 写入 发送邮件(携带附件), 例…...
蓝桥杯真题31日冲刺 |第一天
蓝桥杯真题31日冲刺 |第一天 一:完全平方数 题目:[链接](完全平方数 - 蓝桥云课 (lanqiao.cn)) 思路: 将 每个 完全平方数都 消掉,剩下的就是 不能构成平方的数 以12 为例: 所以 12 只要再 乘个三 即可满足 代…...
STM32开发(18)----CubeMX配置RTC
CubeMX配置RTC前言一、什么是RTC?RTC时钟源RTC备份域二、实验过程1.CubeMX配置2.代码实现3.实验结果总结前言 本章介绍使用STM32CubeMX对RTC进行配置的方法,RTC的原理、概念和特点,配置各个步骤的功能,并通过实验方式验证。 一、…...
Qt 单例模式第一次尝试
文章目录摘要单例模式如何使用Qt 的属性系统总结关键字: Qt、 单例、 的、 Q_GLOBAL_STATIC、 女神节摘要 世界上第一位电脑程序设计师是名女性:Ada Lovelace (1815-1852)是一位英国数学家兼作家,她是第一位主张计算机不只可以用来算数的人…...
C语言--一维数组
数组概念 数组:是一种构造数据类型,用以处理批量的同种类型的数据。 主要特点:数据量大 ,类型相同 一维数组的定义 语法: 类型说明符 数组名[整型常量表达式]; 注意: 方括号里面的内容用于指…...
DataGear 4.5.1 发布,数据可视化分析平台
DataGear 4.5.1 发布,严重 BUG 修复,具体更新内容如下: 修复:修复SQL数据集对于DB2、SQLite等数据源预览时会报错的BUG;修复:修复系统对于MySQL、MariaDB等数据源中无符号数值类型有时报错的BUG࿱…...
Springboot——@valid 做字段校验和自定义注解
文章目录前言注意实现测试环境验证自带的注解自定义valid注解自定义注解和处理类创建参数接收类,并增加字段注解接口中使用自测环节正常测试异常测试自定义全局异常监听扩展递归参数下valid不识别的坑前言 再项目开发中,针对前端传递的参数信息…...
c语言基础练习题详解
💞💞 1.C语言程序的基本单位是(C)。 A.程序行 B. 语句 C. 函数 D.字符 💞💞 2.已知各变量的类型说明如下: int m6,n,a,b; unsigned long w8;…...
C语言设计模式:实现简单工厂模式和工程创建
目录 一,设计模式概念引入 ① 什么是设计模式 ② 什么是类和对象 ③ 什么是工厂模式 二,C语言工厂模式的实现 ① 普通类和对象的代码实现 ② 工厂模式代码实现 ● cat.c ● dog.c ● person.c ● animal.h ● mainpro.c ● 完善mainpro.c …...
3.6日报
今天进行3.0信号整理工作 做官网后台技术文档 了解grpc gRPC是rpc框架中的一种,是rpc中的大哥 是一个高性能,开源和通用的RPC框架,基于Protobuf序列化协议开发,且支持众多开发语言。 面向服务端和协议端,基于http…...
中文代码88
PK 嘚釦 docProps/PK 嘚釦|,g z docProps/app.xml漅AN??駠(髂v诖m岼侸 魣,g踃$秂D廋Qvf漶x莗笳w?:瘜^?俍欶辇2}?睧汎 t#:?效7治XtA鏊?羄鈋嫿饄攗Tv契"D桷撵vJ鉂?闌 Jg??浱?樱沲gic鋹峡?sū窛葻?]迾?9卑{艏 rk\?洺萹啰N?W??2&quo…...
ElasticSearch 基础(五)之 映射
目录前言一、映射(Mapping)简介二、动态映射(Dynamic mapping)1、动态字段映射1.1、日期检测1.1.1、禁用日期检测1.1.2、自定义检测到的日期格式1.2、数值检测2、动态模板三、显示映射(Explicit mapping)1、…...
【C语言督学训练营 第二天】C语言中的数据类型及标准输入输出
文章目录一、前言二、数据类型1.基本数据类型①.整形②.浮点型③.字符型2.高级数据类型3.数据分类①.常量②.变量三、标准输入输出1.scanf2.printf四、进制转换1.进制转换简介2.十进制转其他进制3.其他进制转换五、OJ网站的使用一、前言 王道2024考研408C语言督学营第二天&…...
重资产模式和物流网络将推动京东第四季度利润率增长
来源:猛兽财经 作者:猛兽财经 强劲的2022年第三季度财务业绩 2022年11月18日,京东(JD)公布了2022年第三季度财务业绩,净收入为2435亿元人民币,增长了11.4%。净服务收入为465亿元人民币…...
做博彩类的网站/全国疫情防控最新数据
1、区别 watch 中的函数是不需要调用的 computed 内部的函数调用的时候不需要加() watch 属性监听 监听属性的变化 computed: 计算属性通过属性计算而得来的属性 watch 需要在数据变化时执行异步或开销较大的操作时使用 对于任何复杂逻辑或一个数据属性在它所依赖的属性发生…...
什么是网站app/培训总结心得体会
一、今天学习到了vim编辑器的快捷键操作 全选复制:gg->y->G 全选删除:gg->d->G 二、shell编程方面 1、echo -e 表示开始转义,所以 echo -e "Hello \n World"执行结果是: Hello World 2、echo -n 表示…...
有什么网站做交流会/网页搜索引擎大全
转自:http://www.openphp.cn Eclipse 是一款很强大的 IDE,本站曾经也发过两篇关于使用它配置 PHP 调试环境的文章,现在已经出了 3.0.1 版本和中文语言包了,所以本文简单介绍一下它的汉化方法。 下载 Eclipse 3.0.1 和语言包&…...
黄石商城网站建设/淮北网站建设
作为一只科研狗,在NCBI上搜索文章是最基本的生存技能。NCBI上的PubMed 是一个免费的搜索引擎,提供生物医学方面的论文搜索以及摘要,目前收录有至少2600万文章。其网址如下:https://www.ncbi.nlm.nih.gov/pubmed。例如我们想搜索水…...
烟台市建设工程质量检测网站/seo外包网站
SHA256withRSA 完美工具类 RSAUtils,包含: 1、签名 2、验签 3、公钥加密》私钥解密 4、私钥加密》公钥解密代码:RSAUtils.java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.…...
深圳专业网站建设多少钱/百度一下你就知道123
1、由于刚装完电脑系统,需要提前安装好IIS服务; 控制面板->程序->启动或关闭Windows功能,我默认全选 2、由于我现在需求是,发布自己本地的项目,便于平时调试代码,可以附加(不是给测试人员…...