stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux+单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2Cortex-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/​​,持续更新中。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板

可实战项目:14个Linux+Qt综合项目案例,8个MP1A物联网拓展项目

1、Linux+Qt综合项目案例:华清远见stm32mp157开发板优势特色部分,包括音乐播放器、智慧家庭、智能工业电表、智能出行助手、智能猫眼、环境监测、智能安防、智能语音识别等10余个项目案例,涉及家居、医疗、农业多种应用方向,在案例中使用了多种物联网和嵌入式技术,包括OT开发、linux应用开发、linux驱动开发、物联网云端接入、MQTT协议、json字符串等知识点。

基于Linux+Qt的智能猫眼项目

项目简介:

家居生活存在各种安全隐患:小朋友独自在家,有陌生人拜访,看不到门外是谁,却贸然门;门锁被撬,小偷入室行窃;外出出差,担心有歹人进家,想关心家人的情况……不管是为了自身的人身或财产安全,还是家人的安全,智能猫眼作为家居生活中第一道安全防线变得越来越不可或缺。

项目配套文档及源码,可在下方评论区留言索取~~

项目演示视频:

​STM32 Linux开发板FS-MP1A项目案例之【智能猫眼】-人脸识别技术MQTT连接百度云微信小程序远程控制_哔哩哔哩_bilibili​

开发平台:

华清远见stm32mp157开发板豪华套餐(开发板+仿真器+五寸屏+摄像头+资源扩展板+tf卡+读卡器)

项目功能:

1、人脸识别: 基于百度专业的深度学习算法和海量数据训练可进行人脸识别,轻松知晓访客身份。

2、智能报警: 实时检测非法闯入,可以自动布防,当触发警报时实时报警,最短时间内远程通知微信小程序。

3、智能侦测: 利用人体热释红外传感器实时感知门前动态,有效降低信息误报,提升系统效率。

4、物联网云端接入: 系统支持百度云端接入,同时可对接微信小程序进行远程布控 

项目实战:

Qt开发环境搭建

Qt Creator 安装

将 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 实验源码\工具软件)复制到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp 方式将文件存入家目录下的 Downloads 目录。我们需要在终端中赋予安装程序可执行的权限

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_02

我们可以使用图形化的文件管理器来查看

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_03

双击“qt-creator-opensource-linux-x86_64-4.10.1.run”图标运行安装程序。出现如下界面:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_04

等待程序验证完成后点击“Next”

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_05

这里我们需要登录或者注册一个账号,如果我们之前已经注册过直接登录就可以。如果没有注册过则需要新注册有一个账号后登录。这里笔者已经注册过账号,所以直接登录。 登录成后出现如下界面,点击 Next

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_06

这里选择安装路径

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_07

可以直接默认,Next。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_08

这路选择安装的组件,直接默认即可

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_09

这里我们需要同意用户协议

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_10

这个界面告诉我们安装完成后需要占用的空间。点击”Install”按钮后开始安装。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_11

安装完成后出现如下界面

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_12

点击“Finish”按钮后将弹出 Qt Creator 主界面

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_13

点击“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 ,一般按上面步骤执行后都会有。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_14

点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C"。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_15

填写信息如下,"Name"为"Auto-GCC","Compiler path"点击旁边的

"Browse.."按钮选择编译器的路径,例子中的路径是 “/usr/bin/gcc”

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_16

2)配置 G++

点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C++",下面的文本框填写"Name" 为"Auto-G++","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是" /usr/bin/g++"。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_17

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_18

填写完成后,点击"Apply"。

3)配置 qmake

选择"Qt Versions"标签,如果有下面红框中的文本,可以跳过下面步骤

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_19

如果没有,在右侧点击"Add..."

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_20

会弹出 qmake 路径选择对话框,这里以"

/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"为例子。 选择”qmake”文件后,点

击"Open"按钮。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_21

"Version name"改为" Qt %{Qt:Version} GCC"。然后点击"Apply"按钮。

4)配置 Kits

点击左侧"Kits",右侧选择"Kits"标签。检查有没有下图红框选中的文本,

如果有可以跳过下面步骤

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_22

然后没有,点击 Add:

在弹出的对话框中"Name"为"Desktop","Device Type"选择"Desktop"选项,

"Sysroot"选择目标设备的系统目录,"Compiler"选择之前配置的名称"AutoGCC"和"Auto-G++","Qt version"选择之前配 置的名称"Qt 5.14.1 GCC",其它

默认即可,最后点击"Apply"和"OK"按钮

 

Qt Creator 新建工程

注意:工程路径最好不要包含中文、特殊字符、空格等

我们可以新建一个“qt”文件夹,该文件夹用作我们以后存放源代码

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_23

打开 Qt Creator,在欢迎页面点击 “New”按钮,来新建一个工程

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_24

在出现的新建项目窗口中,我们选则“Application”->“Qt Widgets

Application”,然后点击右下方“Choose…”按钮,来创建一个桌面 Qt 应用。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_25

我们在这里设置项目介绍和源码位置,我们这里创建一个名为

“HelloWorld”的示例项目,设置完成之后点击 next

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_26

直接点击 next

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_27

随后进行细节设置,主要设置要创建的源码文件的基本类信息,包括类名等。这里我们可以根据自己的项目特点进行设置。需要说明的一点就是基类的选择,这里基类有 QMainWindow、QWidget、QDialog 三种,它们的不同之处如下:

⚫ QMainWindow 类提供一个带有菜单条,工具条和一个状态条的主应用程序窗口。主窗口通常提供一个大的中央窗口部件,以及周围菜单,工具条,和一个状态栏。QMainWindow 窗口经常被继承,使得封装中央部件,菜单,工具条,状态栏等都变得很容易,当用户点击它的时候,相应的槽就会被调用;

⚫ QWidget 类是所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。一个窗口部件可以被他的父窗口或者是其他窗口挡住一部分;

⚫ QDialog 类是对话框窗口的基类,对话框窗口主要用于短期任务和用户进行短期通讯的顶级窗口,QDialog 可以是模态对话框或者是非模态对话框。QDialog 支持扩展并带有返回值,他们可以带有默认值;我们在这里选择 QDialog 类即可,点击 next 完成类信息设置。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_28

直接点击 next 按钮即可。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_29

然后进行工具选择,该页面可以选择我们创建的工程可以使用的工具,选择想要使用的编译器模块,例如下图 。点击 next

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_30

最后我们设置汇总信息,如果不需要版本控制等功能,直接点击完成 finish即可。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_31

随后我们就进入到了主界面,这时候 Qt 已经帮我们做好了一些准备工作,包括创建了一些文件,写好了一些前置代码等等。我们可以点击左边 protect 栏,来查看我们的编译选项。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_32

我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_33

左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_34

点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_35

 

Qt Creator 导入工程

我们可以将已存在的 Qt 程/home/linux/qt/helloworld 路径下

点击欢迎页面的“Open” 按钮可以打开已有的工程

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_36

找到我们刚才解压好的源码,选择“helloworld.pro”文件并点击打开

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_37

接下来我们就可以进入到代码编辑界面了。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_38

左上角是项目栏,点击项目名称左边的小箭头可以展开项目目录

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_39

我们可以点击左边项目栏,来查看我们的编译选项。需注意的是构建设置中的路径应与工程路径处于同级目录下。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_40

我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_41

左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_42

点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_43

 

Qt Creator 文件说明

通过上面两个章节,我们学习到了 Qt 程序的新建与导入的方法,也知道了Qt 会帮我们做一些基础工作,比如帮我们建立了一些文件,那么这些文件都是干什么用的呢?我们以HelloWorld 程序来说明一下。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_44

以“.pro”为后缀名的文件,为 Qt 的项目管理文件,存储项目设置的文件;

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_45

“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 对窗体进行可视化设计;

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_46

UI 设计器有以下一些功能区域:

组件面板:窗口左侧是界面设计组件面板,分为多个组,如 Layouts、Buttons、Display Widgets 等,界面设计的常见组件都可以在组件面板里找到。

中间主要区域是待设计的窗体。如果要将某个组件放置到窗体上时,从组件面板上拖放一个组件到窗体上即可。

Signals 和 Slots 编辑器与 Action 编辑器是位于待设计窗体下方的两个编辑器。Signals 和 Slots 编辑器用于可视化地进行信号与槽的关联,Action 编辑器用于可视化设计 Action。布局和界面设计工具栏:窗口上方的一个工具栏,工具栏上的按钮主要实现布局和界面设计。

对象浏览器(Object Inspector):窗口右上方是 Object Inspector,用树状视图显示窗体上各组件之间的布局包含关系,视图有两列,显示每个组件的对象名称(ObjectName)和类称。

属性编辑器(Property Editor):窗口右下方是属性编辑器,是界面设计时最常用到的编辑器。属性编辑器显示某个选中的组件或窗体的各种属性及其取值,可以在属性编辑器里修改这些属性的值。属性编辑器的内容分为两列,左侧为属性的名称,右侧为属性的值。属性又分为多个组,实际上表示了类的继承关系,位于下方的类属性组继承自位于上方的类属性组;

如果我们需要新建资源文件、源码文件等,可以在项目文件夹出点击鼠标右键,选择 Add New;如果我们有新的文件需要添加,可以在项目文件夹出点击鼠标右键,选择 Add Existing Files。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_47

 

Qt Creator 帮助文档

Qt 的帮助文档是伴随我们学习 Qt 开发的好伙伴。在 Qt 开发过程中,我们会面临图形接口使用的问题,它不像 C 语言那样就那么几个函数接口,图形接口的接口数量可以用海量来形容,常用的我们可能能记住,其它的就没有必要去记了,用到什么就去帮助文档查看用法是比较方便的。我们可以按 F1 按键,或通过上方导航栏的“help->contects”来进入帮助文档

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_48

上方的前进后退按钮方便我们查看文档,如返回到上一步,返回到下一步。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_49

我们可以通过帮助文档来查看以下几个部分:

类使用的相关介绍;

查看相关类的使用介绍,我们可以先进入到帮助文档,然后在左上角选择“Search”。笔者这里以 QWidget 类为例,输入我们想要查找的类的名字,然后双击查找结果来查看说明。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_50

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_51

也可以先将鼠标移动到想要查询的类的位置,如图所示,将鼠标移动至“QWidget”处,然后按“F1”键,即可跳转到相应的帮助文档。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_52

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_53

我们可以通过再按一次“F1”键来全窗口查看帮助文档,按“Esc”键可以退出。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_54

部分常用的成员元素包括以下几项:

⚫ 公有成员函数:操作部件属性的相关函数;

⚫ 公有槽函数:Qt 类中已经定义好的槽函数,直接可与信号相连接;

⚫ 信号:软中断,如按下按钮触发 pressed() 信号等;

⚫ 保护成员函数:通常事件所对应的虚函数放在此处;

⚫ 事件:常用事件,如操作鼠标触发的鼠标事件;

滚动鼠标滚轮,向下即可看到“Qwdget Class”类的相关说明了。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_55

1) 查看所用的部件的相应成员函数。

我们可以查找到该类所用部件的相应成员函数的使用方法、功能、参数、返回值等等,我们以“按钮”控件,即“QPushButton Class”类为例,我们通过索引搜索的方式,来找到这个类

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_56

我们可以通过点击“Public Functions” 来查看“QPushButton”这个类中的成员函数。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_57

这里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”为例,我们点击函数名字可以进入到函数详情中。我们可以看到相应的描述为:以“text”为显示内容,以“parent”为父对象,构造一个push 按钮。“text”“parent”为函数参数,由于是构造函数,所以此函数没有返回值。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_58

还有一些函数是继承自其它类的,例如“Public Functions”中有 21 个继承自“QAbstractButton”类的函数,我们点击“QAbstractButton”即可查看。

点击“QAbstractButton”即可查看

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_59

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_60

同样我们可以点击相应的函数进入查看详情。如查看“void setText(const QString &text)”。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_61

2) 查看所用的部件的信号。

我们这里还是以“PushButton”为例,我们点击“Public Slots”。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_62

可以看到“PushButton”本身有一个“void showMenu()”的信号,并且有很多继承自其他类的信号。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_63

一般来说我们用的“PushButton”的信号,最多的是用到其继承自基类“

QAbstractButton”中的几个信号,分别是点击(按下后抬起)、按压(单按下)、释放(单抬起)等

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_64

我们可以点击相应信号查看详情。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_65

3) 查看所用的部件的事件(所对应的虚函数如何编写)。

部件常用事件主要在 “QWidget”中声明,选择“Events”即可查看相关说明。

每个事件都对应着事件函数。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_66

点击事件函数可查看详情

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_67

QT 程序设计

人脸添加


人脸采集

在 pro 文件添加

QT += network

QT += multimedia

使用 V4L2 进行图像采集,新建 v4l2api.h 和 v4l2api.cpp。

采集/dev/video0 摄像头设备的图像,但是采集到的是 yuyv 格式的图像,需要进行转换成 rgb 格式才能显示在 lcd 屏幕上面。

主要功能代码如下:

void V4l2Api::run()

{

 char buffer[WIDTH*HEIGHT*3];

 char rgbbuffer[WIDTH*HEIGHT*3];

 int len;

 while(1)

 {

 grapImage(buffer, &len);

 yuyv_to_rgb888((unsigned char *)buffer, (unsigned char *)rgbbuffer);

 //把 RGB 数据转为 QImage

 QImage image((uchar*)rgbbuffer, WIDTH, HEIGHT,

QImage::Format_RGB888);

 emit sendImage(image);

 msleep(5);

 }

}

 

Yuyv 转 RGB 函数实现

bool V4l2Api::yuyv_to_rgb888(unsigned char *yuyvdata, unsigned char *rgbdata,

int picw, int pich)

{

 int i, j;

 unsigned char y1,y2,u,v;

 int r1,g1,b1,r2,g2,b2;

 //确保所转的数据或要保存的地址有效

 if(yuyvdata == NULL || rgbdata == NULL)

 {

 return false;

 }

 int tmpw = picw/2;

 for(i=0; i<pich; i++)

 {

 for(j=0; j<tmpw; j++)// 640/2 == 320

 {

 //yuv422

 //R = 1.164*(Y-16) + 1.159*(V-128);

 //G = 1.164*(Y-16) - 0.380*(U-128)+ 0.813*(V-128);

 //B = 1.164*(Y-16) + 2.018*(U-128));

 //下面的四个像素为:[Y0 U0 V0] [Y1 U1 V1] -------------[Y2 U2

V2] [Y3 U3 V3]

 //存放的码流为: Y0 U0 Y1 V1------------------------Y2 U2 Y3

V3

 //映射出像素点为: [Y0 U0 V1] [Y1 U0 V1]--------------[Y2 U2

V3] [Y3 U2 V3]

 //获取每个像素 yuyv 数据 YuYv

y1 = *(yuyvdata + (i*tmpw+j)*4); //yuv 像素的

Y

 u = *(yuyvdata + (i*tmpw+j)*4+1); //yuv 像素

的 U

 y2 = *(yuyvdata + (i*tmpw+j)*4+2);

 v = *(yuyvdata + (i*tmpw+j)*4+3);

 //把 yuyv 数据转换为 rgb 数据

 r1 = 1.164*(y1-16) + 2.018*(u-128);

 g1= 1.164*(y1-16) - 0.380*(v-128)- 0.394*(v-128);

 b1 = 1.164*(y1-16) + 1.159*(v-128);

 r2 = 1.164*(y2-16) + 2.018*(u-128);

 g2= 1.164*(y2-16) - 0.380*(v-128)- 0.394*(v-128);

 b2 = 1.164*(y2-16) + 1.159*(v-128);

 if(r1 > 255) r1=255;

 else if(r1 < 0) r1 = 0;

 if(g1 > 255) g1=255;

 else if(g1 < 0) g1 = 0;

 if(b1 > 255) b1=255;

 else if(b1 < 0) b1 = 0;

 if(r2 > 255) r2=255;

 else if(r2 < 0) r2 = 0;

 if(g2 > 255) g2=255;

 else if(g2 < 0) g2 = 0;

if(b2 > 255) b2=255;

 else if(b2 < 0) b2 = 0;

 rgbdata[((i+1)*tmpw+j)*6] = (unsigned char)b1;

 rgbdata[((i+1)*tmpw+j)*6 + 1] = (unsigned char)g1;

 rgbdata[((i+1)*tmpw+j)*6 + 2] = (unsigned char)r1;

 rgbdata[((i+1)*tmpw+j)*6 + 3] = (unsigned char)b2;

 rgbdata[((i+1)*tmpw+j)*6 + 4] = (unsigned char)g2;

 rgbdata[((i+1)*tmpw+j)*6 + 5] = (unsigned char)r2;

 }

 }

 memcpy(yuyvdata,rgbdata,HEIGHT*WIDTH*3);

 return true;

}

 

获取、关闭获取图像、拍照按钮槽函数

右键采集图像按钮,点击转到槽。其他两个按钮同样

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_68

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_69

函数实现如下:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_70

保存人脸信息

先录入姓名,录入后,人脸对着摄像头,拍照获取一帧图像保存到本地,并把姓名保存到本地数据库,和人脸相对应,一个人脸对应一个姓名。

 

人脸识别

申请百度 AI 开发平台人脸识别应用

人脸识别是利用百度的 API 在线识别。所以需要申请项目 ID。

首先登陆 https://ai.baidu.com/tech/face/compare,进入到人脸对比的界面。

选择立即使用

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_71

登陆自己的百度账号,可用手机号申请

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_72

点击创建应用:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_73

依次输入应用名称,选择类型,接口默认选择人脸识别,添加应用描述,点击立即创建

至此,应用创建完毕,现在就可以使用该应用了

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_74

点击返回应用列表,我们记住其中的 API Key 和 Secret Key,下面会用到

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_75

HTTP 请求类实现

我们采集的图像需要通过 HTTPS 协议上传到百度 AI 开发平台进行识别,之后 AI 平台会返回给我们识别的结果。

http 类只需要封装一个方法

static 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);

 static bool post_sync(QString

url,QMap<QString,QString>header,QByteArray requestData,QByteArray

&replyData);

signals:

};

#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;

 }

}

 

采集到的人脸处理

查看百度 ai 开发平台接口文档,我们看到 http 请求的 image 需要进行处理,图片需要 base64 编码、去掉编码头。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_76

新建 ImageProcess 类实现以下函数,返回 QbyteArray 类型的图像。

QByteArray IamgeProcess::imageBaseTo64ToUrlEncode(QString imagePth)

{

 QImage image(imagePth);

 QByteArray byte;

 //用 QByteArray 构造 QBuffer

 QBuffer buf(&byte);

 buf.open(QIODevice::WriteOnly);

 image.save(&buf,"JPG");

 //对图片做 base64 编码(不包含编码头)

 QByteArray byteBase64 = byte.toBase64();

 QTextCodec *codec = QTextCodec::codecForName("UTF-8");

 QByteArray imgData =

codec->fromUnicode(byteBase64)/*.toPercentEncoding()*/;

 return imgData;

}

 

发送请求

需要向百度 AI 平台发送两个请求,第一个请求是获取 access_token;第二个请求是向 URL 发送图片资源。

获取 access_token

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_77

我们复制示例中的 url 地址如下。

​https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&​

client_id=Va5yQRHlA4Fq5eR3LT0vuXV4&client_secret=0rDSjzQ20XUj5itV6WRtzn

PQSzr5pVw2&

把其中的 client_id 和 client_secret 后面的参数删掉,通过二维码扫描的方

式加入 URL 如下:

​https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credenti​

als&client_id=%1&client_secret=%2&

我们通过二维码生成器把我们的 API Key 和 Secret Key 写成 josn 的形式生成

二维码,如以下形式:

{

“client_id”:“xxxxxx”,

“client_secret”:“xxxxxx”

}

我们在下面开始实现通过识别二维码填充 client_id 和 client_secret 到上述的

URL 中。

右键转到槽,选择 clicked()。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_78

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_79

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_80

在这里识别二维码需要使用到 QZXing 库进行识别。我们提 QZXing 库的源代码在实验源码下的 qzxing.tar.xz。

解压后,将解压后的文件放到 QT 源码路径下

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_81

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_82

在 pro 文件下添加 include(qzxing/src/QZXing.pri)保存后,在 mainwindow.h 加入

#include< QZXing >头文件,这样就可以使用 QZXing 库了。下面开始编写识别二维码填充 URL。

在 mainwindow.cpp 添加下面 QString 定义。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_83

void MainWindow::on_pushButton_ewm_clicked()

{

 if(picTorF == false)

 {

 QMessageBox::warning(this, "警告", "请先拍照保存图片");

 return ;

}

 QZXing zxing;

 QString imagePth ="./pic.jpg";

 QImage image(imagePth);

 QByteArray byte = zxing.decodeImage(image).toUtf8();// 该 方 法 返 回

QString 串,标识图片二维码的内容

 QJsonObject obj = QJsonDocument::fromJson(byte).object();

 client_id = obj.value("client_id").toString();

 secret_id = obj.value("secret_id").toString();

 qDebug()<< "client_id:"<<client_id;

 qDebug()<< "secret_id:"<<secret_id;

 if(client_id =="")

 {

QMessageBox::warning(this, "警告", "请重新填充秘钥");

 on_openBt_clicked();

 return ;

 }

 else

 {

 QMessageBox::information(this, "提示", "填充秘钥成功");

 ui->pushButton_ewm->setText("填充完成");

 ui->pushButton_ewm->setEnabled(false);

 Keypadding = true;

 picTorF = false;

 on_comboBox_activated(0);

 on_openBt_clicked();

 }

}

 

上传两个要对比的人脸

当人脸对比时,获取要对比的人脸,程序在本地人脸库选取人脸依次遍历和要对比的人脸对比。

人脸对比 URL:https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=?

将上一步获取到的 access_token 填充到上面的 URL 中,作为 HTTP 请求的请求URL。请求 DATA 按照下面组成 JOSN 数据,发起 HTTP 请求。其中两张人脸都要使用 4.1.5 的方法进行图像处理转换

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_84

接收返回信息并解析

接收到的数据返回示例如下图所示:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_85

我们只需要 JOSN 数据里的 score 的值即可,这里逻辑写的是如果

score>=80,人脸识别成功。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_86

按键进行人脸识别

开启线程实时监测按键是否按下,发送信号到主类。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_87

当按键按下后,执行人脸识别函数。

 

智能布防

智能布防界面如下图所示:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_88

设置布防的开始时间和结束时间,将时间转换成时间戳,填充到下图中标红的成员变量。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_89

当光电开关遮挡后,会执行上图槽函数,该槽函数如果满足了 if 语句的条件后,会驱动蜂鸣器进行报警,并通过 MQTT 上传数据到微信小程序。

 

微信小程序设计

创建新项目

打开微信开发者工具,新建项目,填写自己的 AppID,新建。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_90

注意:创建工程的路径一定不能有中文

 

修改微信小程序代码

修改 app.json 文件

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_91

下载支持 MQTT 协议和 sha1 加密的 js 库

下载 mqtt.js https://github.com/mqttjs/MQTT.js

下载 hex_hmac_sha1.js https://github.com/xihu-fm/aliyun-iotclient-sdk/tree/master/lib

 将这两个文件存放到 utils 目录下

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_92

编写 index.wxml,这个文件是用来编写页面的布局

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_93

编写 index.wxss,这个文件是用来配置页面的属性。

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_94

编写 index.js,修改设备信息三元组。这个文件用来主要逻辑的编写

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_95

socket 合法域名

所有的程序编写完成之后,进入调试窗口,就会看到下面这种情况:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_96

说明没有在微信小程序的开发管理中添加这个域名所导致的。

 打开小程序开发网页:

​https://mp.weixin.qq.com/wxamp/devprofile/get_profile?token=58461​

2979&lang=zh_CN

 打开开发管理->开发设置->服务器域名,修改 socket 合法域名,添加这个域名即可

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_97

实验源码

源码路径【13_智能猫眼\QT 实验源码\08-AiFace】

【13_智能猫眼\微信小程序源码\smartEye】

 

注意事项

1.在开发板运行时,需要导入中文字库,否则会因为识别不了中文。

将【13_智能猫眼\工具软件\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/

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_98

2.如果使用 mipi 五寸屏运行此项目,需要进行屏幕旋转以适应屏幕,具体

步骤如下:

在/etc/profile.d/qt-eglfs.sh 添加环境变量如下:

STM32MP157开发板Linux+Qt项目实战:智能猫眼_Qt_99

STM32MP157开发板Linux+Qt项目实战:智能猫眼_帮助文档_100

下面变量的 event0 设备需要填实际的触摸屏设备

STM32MP157开发板Linux+Qt项目实战:智能猫眼_开发板_101

这里即填 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