基于表情分析的智能语音陪伴机器人
本次电子设计是一个从综合性的实践项目,主要涉及基于STM32的各种资源编程、SD卡DMA方式读/存取、树莓派、语音模块等,该作品参加比赛并获得全国二等奖,部分技术能力已申请专利和软件著作权。
对于想要获取此课程设计报告word/PDF版本的同学,欢迎光顾小生寒舍 GitHub:https://github.com/ChromeWei?tab=repositories
特此申明,此报告只做学习交流之用,若涉及商用应用等涉及相关著作权问题,还望与作者联系e-mail:yidazhang1@gmail.com。
摘要
以情绪分析和智能语音为研究对象,作者充分调研了目前家居机器人的研究现状,大部分都是以释放人类体力与脑力为目标,而忽视了“家”的真正含义;在这个基础上作者提出了智能家居的新方向——情感交互。整个项目的最终目标是为了营造一个真正的智能“家”居,让科技与人类情感产生共鸣,缓解人们的生活压力,打造一个温馨舒适的情感家居环境。采用全彩12阶光立方作为三维动态显示器,基于表情识别和智能语音制作一种智能陪伴机器人。
本系统主要由三部分组成:表情识别摄像头——树莓派+摄像头搭建完成;智能音箱——LDV5语音识别模块;三维动态显示系统——包括电源开关电路、控制电路和级联驱动电路,并留下足够空间扩展后续电路。全彩的3D显示效果增加了使用者的视觉体验,表情识别和智能语音促进了人机交互,真正实现了人机语音交互,更加智能化、人性化。
关键字: M智能语音;表情识别;机器人;Open;数字程控
第一部分 设计概述
1.1系统设计简述
随着人们工作、学习生活的压力不断增加,抑郁症、精神分裂等严重精神疾病的发病率也在呈上升趋势。缓解人们精神压力的实际问题十分严峻,也逐渐成为相关领域专家学者的研究重点。为解决或者提供一种舒缓人的精神压力的娱乐系统,设计开发了一种基于动态表情识别的语音AI娱乐互动系统,旨在帮助人们舒缓精神压力,搭建一个更好的智能健康生活环境,改善人们的精神状况。
以情绪分析和智能语音为研究对象,作者充分调研了目前家居机器人的研究现状,大部分都是以释放人类体力与脑力为目标,而忽视了“家”的真正含义;在这个基础上作者提出了智能家居的新方向——情感交互。整个项目的最终目标是为了营造一个真正的智能“家”居,让科技与人类情感产生共鸣,缓解人们的生活压力,打造一个温馨舒适的情感家居环境。采用全彩12阶光立方作为三维动态显示器,基于表情识别和智能语音制作一种娱乐AI互动系统。
本系统主要由三部分组成:表情识别摄像头——树莓派+摄像头搭建完成;智能音箱——LDV5语音识别模块和麦克风播报;三维动态显示系统——包括电源开关电路、控制电路,并留下足够空间扩展后续电路。全彩的3D显示效果增加了使用者的视觉体验,表情识别和智能语音促进了人机交互,真正实现了一个AI娱乐互动系统。
1.2系统应用领域
本系统主要由三大部分组成:表情识别摄像头——树莓派+摄像头搭建完成;智能音箱——LDV5语音识别模块和麦克风播报;三维动态显示系统——包括电源开关电路、控制电路,并留下足够空间扩展后续电路。全彩的3D显示效果增加了使用者的视觉体验,表情识别和智能语音促进了人机交互,真正实现了一个AI娱乐互动系统。采用12片SM16126串转并芯片(16个输出口)级联形成144个输出口控制,对应于光立方的一面LED。通过DataIN数据端口输入时序控制,进行PWM调制,产生RGB全彩颜色调节。
3D动态显示系统软件可以实现对光立方系统的控制,同时可在多种应用设计中得到二次开发,比如:智能家居领域(家庭、城市装饰、大型会展等)、智能教育领域(儿童几何空间启蒙教育、兴趣启发等)。同时,也是电子类专业学习者软件编程、课程设计的最佳练习方式。
娱乐互动系统可应用的技术:在线控制—通过无线模块将陪伴机器人与服务器相连,实现实时控制;配合安装自主设计的智能音箱,实现人机语音交互,更加智能化、人性化。
本系统的功能定位:
家庭娱乐——配合搭载语音识别、麦克风等技术终端的智能音箱让陪伴机器人更加人性化,提高生活的幸福度;
科普教育——全彩光立方动画激发孩子对三维空间的想象力、对智能科技的兴趣,传播三维建模知识;
情感补足——根据情绪分析结果,光立方利用不同旋律的音乐和动画表达自己的感情,让交互更加生动有趣,治愈情感。
1.3参考资料
[1] 单片机的C语言应用程序设计.第5版[M],马忠梅、王美刚等编,北京航空航天大学出版社,2013.1
[2] 清华大学电子学教研组编,童诗白、华成英主编.模拟电子技术基础.第3版[M].北京:高等教育出版社,2001
[3] Jeon, Jinwoo, et al. “A Real-time Facial Expression Recognizer using Deep Neural Network.” International Conference on Ubiquitous Information Management and Communication ACM, 2016:94.
第二部分 系统实现方案
2.1软件设计的总体方案
2.1.1软件系统框图
2.1.2软件系统概述
软件总体设计包括主程序、摄像头采集、表情识别程序、音频采集、音频处理程序、显示系统程序、蓝牙通信程序、Fatfs系统读取TF卡程序以及上位机端的图形开发程序。
主程序中通过调用人体检测模块程序来检测光立方的周围是否有人,如果有就产生中断并且调用显示程序,显示开机的动画。此时语音模块开始采集周围的音频信号,当检测到相应的音频信号,经过滤波、降噪、识别的处理与语音库做对比,并产生相应的信号,通过蓝牙模块将信号发送至显示端,显示端检测收到的信号,并从TF卡中读入相应动画的数据,从而使得光立方显示相应的动画。使用树莓派进行人脸表情识别(主要识别6种基本的表情),针对识别结果,通过蓝牙串口发送控制字符与STM32通信,播放相应的动画和背景音乐,舒缓情绪、释放压力。
2.1.3优越性及创新点
本系统的优越性与创新点在于:
(1)实现了差错隔离。 部分子节点出错或损坏不会影响到整个系统的正常工作,同时也可以很容易地定位到出错的位置。
(2)提高人机交互性能。 通过按键、红外模块、语音模块控制光立方的显示方式和显示效果。
(3)表情识别和智能语音聊天功能的加入,使得整个系统更加智能化,缩短机器与人的心理距离,更好的实现智能“家”居。
(4)显示画面可自主设计。 小组成员自主开发设计的上位机,用户可自主设计图案,设置显示效果,简单可操作。上位机的系统兼容性较好,可在PC端使用。其产生的编码可直接load在TF卡中,方便三维图案及显示效果的设计。
(5)可二次开发。 3D动态显示系统软件可以实现对光立方系统的控制,同时可在多种应用设计中得到二次开发,比如:智能家居领域(家庭、城市装饰、大型会展等)、智能教育领域(儿童几何空间启蒙教育、兴趣启发等)。同时,也是电子类专业学习者软件编程、课程设计的最佳练习方式。
(6)环境友好,绿色环保。 选用低功耗、发光波长较短(460~465nm)的雾状散光LED灯,尽量不采用大面积青蓝色图像显示,降低对人眼的伤害,提高环境友好性,节能环保。
(7)色彩灰度阶级可调。 国内外的多家公司、实验室对3D显示技术展开研究,目前市场上的光立方显示系统显示画面颜色较为单一,三维视觉效果不佳。本系统软件采用PWM脉宽调制的方法,可实现RGB全彩的显示。
2.2 各模块概述
本系统采用了4种元件或模块实现一种3D动态显示系统,有树莓派摄像头、蓝牙模块、语音识别模块、人体红外检测模块以下对这些传感器模块进行详细介绍。
2.2.1 RGB LED灯
LED发光体的体积越小,光立方整体的通透性就越好,也就是说后排的LED就越不容易被前排的LED挡住;另一方面,发光体越大,越容易看到光点,例如使用直径更大的LED或是使用屋面而非光面的LED。此外,还要注意LED光点的可视角度,雾状LED要比光面LED要大。
本项目使用的LED灯为5MM、RGB雾状散光LED灯,其最大电流为20mA,电压范围3.0-3.5V,波长460-465nm。实物如图2.2所示:
2.2.2 Raspberry Pi 摄像头
Raspberry Pi Camera v2是树莓派新推出的官方摄像头板,采用高质量8百万像素索尼IMX219传感器扩展板,拥有定焦镜头,可以捕捉3280 x 2464像素静态图片和30FPS 1080P的视频,也支持1080p30, 720p60 and 640x480p60/90摄像功能。树莓派摄像头通过板上表面的小插槽连接树莓派,并使用专门为树莓派设计的CSI接口连接。
主要技术参数:800万像素;感光芯片为索尼IMX219;CCD尺寸:1/4英寸;光圈(F):2.0;焦距(Focal Length):3.04mm;视场角(FOV):73.8度;静态图片分辨率为3280 × 2464;支持1080p30, 720p60以及640 × 480p90视频录像;尺寸:25mm × 24mm × 9mm;重量:3g。实物如图2.2所示:
在本系统中,摄像头主要用来拍摄视频和/或采集图像信息。
2.2.3蓝牙通信模块
本系统中,蓝牙模块用来实现语音识别模块与STM32之间的通信功能。STM32对采集到的音频信号进行识别处理,通过蓝牙串口发出控制指令,从机接收后STM32控制显示相应的三维动画。
2.2.4语音识别模块
对于音频信号的处理,我们采用LDV5模块进行音频信号的采集。接着通过STM32模拟SPI与模块通信读取其寄存器的值,从而获取所捕获的音频信号,并对其做FFT快速傅里叶变换进行语音信号处理,通过与语音库做对比来发送相应的指令。
选用LDV5的另外一个好处是,它可以识别语音,并通过设置可以进行简单的语音聊天,例如:播放音乐、讲故事、语音聊天的功能。
2.2.5人体红外检测模块
本系统采用HC-SR505来实现人体检测,此模块是基于红外线技术的自动控制产品,灵敏度高,可靠性强,小体积,低电压工作模式。广泛应用于各类自动感应电器设备。
第三部分 系统硬件设计
3.1 SD卡读写
3.1.1 SD卡简介
本设计中显示系统与TF卡系统数据的交换采用的是SPI串行外设接口(Serial Peripheral Interface)通信协议。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚。
其管脚约束为:
(1)SDI – SerialData In,串行数据输入;
(2)SDO – SerialDataOut,串行数据输出;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS – Chip Select,从设备使能信号,由主设备控制。
其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。
3.1.2 SD卡通信协议
(1)SD卡引脚定义
(2)SPI与SD卡通信连接
(3)SD卡命令格式
SD卡的命令格式如下,6字节共48位,传输时最高位(MSB)先传输:
SD卡的command(命令)占6位,通常称之为CMDx或ACMDx,比如CMD1就是1,CMD13就是13,ACMD41就是41,依此类推。
Command Argument(命令参数)占4个字节,并不是所有命令都有参数,没有参数的话该位一般就用置0。最后一个字节由7 bit CRC校验位和1 bit停止位组成。在SPI模式下,CRC是被忽略的,可以都置1或置0。
3.1.3 SPI读取SD卡数据
(1)初始化
首先MCU向SD卡发送CMD55(表示使用ACMDx类命令),当MCU接收到0x01时,接着发送ACMD41,若收到0x00表示初始化成功。
(2)读单块扇区
1.发送CMD17,收到0x00表示chengg
2.连续读直到读到开始字节0xFE
3.读512字节
4.读两个CRC字节
(3)读多块扇区
1.发送CMD18读,收到0x00表示成功
2.连续读直到读到开始字节0xFE
3.读512字节
4.读两个CRC字节
5.如果还想读下一扇区,重复2-4
6.发送CMD12来停止读多块操作
(4)写单块扇区
1.发送CMD24,收到0x00表示成功
2.发送若干时钟
3.发送写单块开始字节0xFE
4.发送512个字节数据
5.发送2字节CRC(可以均为0xff)
6.连续读直到读到XXX00101表示数据写入成功
7.继续读进行忙检测(读到0x00表示正忙),当读到0xff表示写操作完成
(5)写多块扇区
1.发送CMD25,收到0x00表示成功
2.发送若干时钟
3.发送写多块开始字节0xFC
4.发送512字节数据
5.发送两个CRC(可以均为0xff)
6.连续读直到读到XXX00101表示数据写入成功
7.继续读进行忙检测,直到读到0xFF表示写操作完成
8.如果想读下一扇区重复2-7步骤
9.发送写多块停止字节0xFD来停止写操作
10.进行忙检测直到读到0xFF
3.2 树莓派摄像头
可以直接使用raspistill和raspivid这两个命令行工具控制摄像头。Dave Jones用Python实现了相同功能。这意味着你可以直接使用Pythong脚本来控制摄像头模块。Python的picamera接口是一个非常美妙的库。用它来演示Pi摄像头模块非常好。
具体用法如下:
导入相关模块
import picamera
from time import sleep
初始化
camera = picamera.PiCamera()
捕获图像
camera.capture('image.jpg')
打开预览
camera.start_preview()
垂直翻转
camera.vflip = True
水平翻转
camera.hflip = True
控制摄像头亮度
camera.brightness = 60
控制摄像头录像
camera.start_recording('video.h264')
程序休眠,但摄像头继续工作
sleep(5)
停止录像
camera.stop_recording()
3.3显示系统程序
3.3.1显示系统流程图
3.3.2显示系统概述
单片机上电后首先进行系统时钟的初始化。设置系统的时钟为168MHZ,最大程度的加快数据处理的速度。这里还要对延迟函数进行时钟分频,利用函数可以方便地进行精确的延时,从而使各模块工作、通信协议更加稳定。
接着系统会初始化SPI通信协议以及所需要使用的IO口进行初始化,此时,文件系统将会打开,文件指针此时指向NONE,当赋予其一个值时,系统便会通过已经初始化完成的SPI协议对内存卡的扇区进行读写。
初始化工作的最后一步是进行定时器的初始化,每一帧静态画面都将得到合适的显示时间,使得动画的播放更加连贯。
接下来判断是否到达定时时间(500us)。若定时时间到了,则将会对下一帧静态画面的数据进行读取,从而产生一个连续的3D动画。
更为特别地,该显示系统可根据表情识别的结果来具有针对性的显示调节情绪的三维动画,配合播放的背景音乐能有效缓解人的精神压力、舒缓情绪。
3.4语音处理程序
3.4.1语音处理流程图
3.4.2语音处理概述
系统上电初始化完成后,MCU发送一条开始指令后,采集模块从低功耗模式转换为高速模式,待采集完成后向MCU发送一个应答信号,并送出40bit的数据,并触发一次软件滤波程序,去除周围环境噪声的影响。MCU将所取得的音频与其语音库中的数据进行对比,若存在该指令,则相应相对应的中断。同时语音合成模块通过扩音器(speaker)进行语音答复,实现人机交互。
3.4.3语音库配置教程
1. TF卡文件介绍
(1) 系统内部调用文件 ---- 不可删除、不可改名
Fyydz.ini--------------主菜单文件
parameter.ini--------系统参数配置文件
sys_sound.mp3-----系统开机声音(名字不能改,内容可换)
knock.mp3----------按键模式,按键按下提示声(名字不能改,内容可换)
exit.mp3-------------退出提示声(名字不能改,内容可换)
(2) 系统内部调用文件 ---- 不可删除、不用可删除
MP3 数据----MP3 点播功能的 MP3 文件( 名字不能改.内容可换)
T90.txt-----二级菜单文件( 名字不能改.不用的话可以删除 )
二级菜单一共可以定义10个,T90.txt-T99.txt。
(3) 用户自行调用文件,可改名可删除
NO .mp3------静音文件,不播放任何声音
其他文件可由用户自行添加并调用。
2.主菜单文件介绍
修改文件Fyydz.ini可实现对语音库以及语音识别成功后所相应的指令和串口所发送程序的配置。
下面说明文件中具体代码的意义,以序号0为例:
《0:00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF:xiao shi tou:小石头.mp3》
(1) “0:”代表该条关键词的序号,文本序号可以不按顺序编写。
(2) “00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF”表示当识别到0这个序号的语音指令时,将会通过串口发送00 00 00 00 00给MCU,连续的三个FF FF FF表示截止符。
(3) “xiao shi tou”这是“小石头”关键字的拼音,即要识别的语句。
(4) “小石头.MP3”这是识别到“小石头”这个关键字后,MCU将会调用此文件进行播放。
3.参数配置文件
在TF卡中存在这个参数配置文件,这个配置文件有5个功能,分别有波特率修改,喇叭音量大小,识别灵敏度调整,识别模式和延时参数这5个参数修改功能。
通常值可取4800、9600、115200bps等
(2) 音量
参数范围:0-15
(3) 麦克风灵敏度
参数范围:1-99
说明:灵敏度越高识别距离越远但误识别率也会变高。
(4) 识别模式
a) 0 ---- 口令模式
b) 1 ---- 普通模式
c) 2 ---- 按键模式
(5) 延时参数
默认参数为12,约10s左右,即当10s内为调用音频采集,音频模块将进入低功耗模式。
3.5树莓派工作介绍
3.5.1 系统结构
3.5.2 树莓派工作流程
树莓派上电后即可打开摄像头,进行表情识别,当识别到基本表情后,播放对应的调节情绪的背景音乐。并且,通过蓝牙通信发送控制指令给STM32,控制光立方显示不同的三维动画,配合播放的背景音乐能有效缓解人的精神压力、舒缓情绪。
第四部分 系统软件架构设计
4.1软件系统结构
下层软件负责为上层提供功能调用。分层实现的好处是随着抽象层次的提高,软件复杂度可以逐层简化,最终顶层可以通过简单的接口调用实现一个具体的复杂功能。
4.2代码结构分析
该系统软件源代码目录如图4.2-1所示。
接下来结合具体的源文件来分析每层实现的功能。
(1)寄存器接口层
寄存器接口层是外设驱动层和单片机硬件之间的桥梁,它直接操纵单片机内部的寄存器,封装实现了IO输入输出模块、定时器模块、ADC模块和串口模块。
其中STM32F4xx.h头文件中定义了单片机的型号以及相关IO口寄存器等定义。Sys.c中封装了IO管脚的地址偏移;usart.c中封装了串口模块;而TIM.c中封装了定时器模块。
(2)外设驱动层
外设驱动层主要由SM16126驱动模块、SPI总线驱动和SD卡读取驱动构成。
其中SM16126.c中封装了SM16126驱动模块,通过MCU模拟IIC通信对SM16126寄存器进行操作,调用了底层的IO输入输出模块以及定时器模块。
diskio.c中封装了SD卡读写驱动,通过调用寄存器层的IO输入输出模块。
SPI_MSD0_Driver.c中封装了SPI总线驱动,调用了底层的IO输入输出模块以及定时器模块,搭建了基于DMA传输的SPI通信协议。
(3)应用层
应用层设计主要是面向用户并且负责处理具体事务。主要包括了显示系统,语音系统以及FATFs文件系统。
main.c文件中封装了整个程序的入口函数main(),它只负责启动任务模块。
LED_CUBE.c文件中封装了显示系统的操作函数,同时其头文件LED_CUEB.h中对所用管脚以及各全局变量进行了定义,如图4.2-2。
同时该文件已经完成了数十种动画的播放,并封装成了相应的函数,如图4.2-3。
TFCard.c中封装了FATFs文件系统调用的相关配置。通过基于DMA传输的SPI总线进行快速的对内存卡的扇区进行读写操作,同时该文件的头文件呢TFCard.h中也封装了所占用的具体管脚以及DMA总线的初始化内容。
4.3部分源码分析
4.3.1 主函数分析
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
MSD0_SPI_Configuration();
delay_init(168);
uart_init(9600);
SM12126_GPIO_Init();
Level_GPIO_Init();
ShowCHINA();
while(Cube_Index==9) ShowCHINA();
while(1)
{
switch(Cube_Index)
{
case 1: Cube_Index = 100;
ShowFPGA();
USART_SendData(USART1,code);
break;
case 2: Cube_Index = 100;
ShowCOUNT();
ShowSIN();
ShowSPIRAL();
ShowSWIRLS();
ShowRIPPLE();
ShowIMP();
USART_SendData(USART1,code);
break;
case 3: Cube_Index = 100;
ShowCUBE();
USART_SendData(USART1,code);
break;
case 4: Cube_Index = 100;
ShowSPIRAL();
USART_SendData(USART1,code);
break;
case 5: Cube_Index = 100;
ShowSWIRLS();
USART_SendData(USART1,code);
break;
case 6: Cube_Index = 100;
ShowRIPPLE();ShowRIPPLE();
USART_SendData(USART1,code);
break;
case 7: Cube_Index = 100;
ShowIMP();
USART_SendData(USART1,code);
break;
case 8: Cube_Index = 100;
ShowSIN();ShowSIN();
USART_SendData(USART1,code);
break;
case 9: JJ_flag=0; while(Cube_Index==9) ShowJJ();
break;
case 10: ALL_flag=0; while(Cube_Index==10) ShowALL();
break;
case 11: NONE_flag=0; while(Cube_Index==11) ShowNONE();
break;
case 12: MAGIC_flag=0; while(Cube_Index==12) ShowMAGIC();
break;
default:break;
}
}
}
主程序首先对系统时钟、外设、各个模块等进行初始化,然后通过调用人体检测模块程序来检测光立方的周围是否有人,如果有就产生中断并且调用显示第一个动画CHINA即为开机动画。此时MCU发送一个起始信号给语音模块,语音模块接收到起始信号后,开始采集周围的音频信号,当检测到相应的音频信号,经过滤波、降噪、识别的处理与语音库做对比,并产生应答信号,通过蓝牙模块将信号发送至显示端,显示端检测收到的信号,并从TF卡中读入相应动画的数据,从而使得光立方显示相应的动画。
4.3.2 SM16126驱动程序分析
#include "SM12126.h"
void SM12126_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(SDI1_GPIO_CLK|SDI2_GPIO_CLK|SDI3_GPIO_CLK|CLK_GPIO_CLK|LE_GPIO_CLK|OE_GPIO_CLK , ENABLE)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType= GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Pin = SDI1_GPIO_PIN;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SDI2_GPIO_PIN;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SDI3_GPIO_PIN;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = CLK_GPIO_PIN;
GPIO_Init(GPIOC,&GPIO_InitStructure);
CLK = 0;
GPIO_InitStructure.GPIO_Pin = LE_GPIO_PIN;
GPIO_Init(GPIOC,&GPIO_InitStructure);
LE = 0;
GPIO_InitStructure.GPIO_Pin = OE_GPIO_PIN;
GPIO_Init(GPIOD,&GPIO_InitStructure);
OE = 1;
}
void WriteData(unsigned char Data_A,unsigned char Data_B,unsigned char Data_C)
{
SDI1 = Data_A;
SDI2 = Data_B;
SDI3 = Data_C;
CLK = 1;
CLK = 0;
}
void OpenLED(void)
{
LE = 1;
LE = 0;
OE = 0;
}
void CloseLED(void)
{
OE = 1;
}
void StartLatch(void)
{
LE = 1;
LE = 0;
}
该程序通过模拟IIC通信,在CLK为低电平时准备要传输的数据,在CLK上升沿时进行一位数据的传输。同时该模块通过DI和DO进行移位串行输入,从而只需要对一个端口进行多次数据传输即可传完整个模块的数据,并且实现串行输入并行输出的效果,极大地削减了IO口的需求量。
4.3.3 表情识别程序分析
4.3.3.1 相关Python库介绍
Dlib包含广泛的机器学习算法。所有的设计都是高度模块化的,快速执行,并且通过一个干净而现代的C ++ API,使用起来非常简单。它用于各种应用,包括机器人技术,嵌入式设备,手机和大型高性能计算环境。
本系统软件使用Dlib和OpenCV图像处理库,调用人脸分类器dlib.get_frontal_face_detector(),完成对人脸信息的提取,经过特征点的计算分析比对,在一定阈值范围内认定为人脸,该系统的阈值为0.8。
import dlib #人脸识别的库dlib
import numpy as np #数据处理的库numpy
import cv2 #图像处理的库OpenCv
import serial #串口通信
import RPi.GPIO as GPIO #GPIO
import time
from skimage import io #图像显示的库
import pygame #音频播放的库
4.3.3.2 识别规则
1、嘴巴张开距离占面部识别框宽度的比例越大,说明情绪越激动,可能是非常开心,也可能是极度愤怒。
2、眉毛上扬,17-21 或者 22-26 号特征点距离面部识别框顶部与识别框高度的比值越小,说明眉毛上扬越厉害,可表示惊讶、开心。眉毛的倾斜角度,开心时眉毛一般是上扬,愤怒时皱眉,同时眉毛下压的比较厉害。
3、眯眼睛,人在开怀大笑的时候会不自觉的眯起眼睛,愤怒或者惊讶的时候会瞪大眼睛。
计算了25个人脸的开心表情的嘴巴张开比例、嘴巴宽度、眼睛张开程度、眉毛倾斜程度,导入excel表格生成折线图:
4.3.3.3 程序实现流程图
4.3.3.4 程序实现过程
首先使用dlib完成人脸识别,并提取人脸信息68个特征点。
然后实例化一个 shape_predictor 对象,使用dlib作者训练好人脸特征检测器,进行人脸的特征点标定。
# 利用预测器预测
shape = predictor(img, d)
# 标出68个点的位置
for i in range(68):
cv2.circle(img, (shape.part(i).x, shape.part(i).y), 4, (0, 255, 0), -1, 8)
cv2.putText(img, str(i), (shape.part(i).x, shape.part(i).y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
# 显示一下处理的图片,然后销毁窗口
cv2.imshow('face', img)
cv2.waitKey(0)
标定的时候使用opencv的circle方法,在特征点的坐标上面添加水印,内容就是特征点的序号和位置。
到此,68个特征点的信息就获取到了,下面就需要跟根据这个68个特征点的坐标信息,进行综合计算,作为每个表情的判断指标。
根据上面说到的判断指标,先计算嘴巴的张开比例,由于人离摄像头距离的远近,导致人脸识别框的大小不一,故选择比例来作为判断指标。在选择指标的标准数值之前,先对多个开心的人脸照片进行分析。计算开心时的嘴巴张卡比例的平均。
下面是截取对人眉毛的数据处理方法,对左边眉毛上面的5个特征点进行线性拟合,拟合出一个一次函数直线,用拟合直线的斜率近似代表眉毛的倾斜程度。
# 眉毛
brow_sum = 0 # 高度之和
frown_sum = 0 # 两边眉毛距离之和
for j in range(17,21):
brow_sum+= (shape.part(j).y - d.top()) + (shape.part(j+5).y- d.top())
frown_sum+= shape.part(j+5).x - shape.part(j).x
line_brow_x.append(shape.part(j).x)
line_brow_y.append(shape.part(j).y)
self.excel_brow_hight.append(round((brow_sum/10)/self.face_width,3)) self.excel_brow_width.append(round((frown_sum/5)/self.face_width,3))
brow_hight[0]+= (brow_sum/10)/self.face_width # 眉毛高度占比
brow_width[0]+= (frown_sum/5)/self.face_width # 眉毛距离占比
tempx = np.array(line_brow_x)
tempy = np.array(line_brow_y)
z1 = np.polyfit(tempx, tempy, 1) # 拟合成一次直线
self.brow_k=-round(z1[0], 3) #拟合出曲线的斜率和实际眉毛的倾斜方向是相反的计算出每个表情的眉高、嘴宽的数据,然后分类进行讨论,给出判别阈值。通过对多个不同表情数据的分析,得出每个指标的参考值,可以写出简单的表情分类标准:
# 分情况讨论
# 张嘴,可能是开心或者惊讶
if round(mouth_higth >= 0.03):
if eye_hight >= 0.056:
cv2.putText(im_rd, "amazing", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4)
else:
cv2.putText(im_rd, "happy", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4)
# 没有张嘴,可能是正常和生气
else:
if self.brow_k <= -0.3:
cv2.putText(im_rd, "angry", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4)
else:
cv2.putText(im_rd, "nature", (d.left(), d.bottom() + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, 4)
由于人感情的复杂性,这些表情确实不能完完全全的代表一个人内心深处的情绪波动,如要提高判断的准确性,则需要心率检测、语音处理等综合评价。
4.3.4 树莓派开机自启程序
[Desktop Entry]
Name= emotion_dectaion
Comment=My Python Program
Exec=python /home/pi/MyProject/dlib-python-test/emotiontest/ emotion_dectaion.py
Icon=/home/pi/lena.png
Terminal=flase
MultipleArgs=flase
Type=Application
Categories=Application;Development;
StartupNotify=ture
本程序主要是几个参数的设置,Name设置为需要开机运行的程序的名称(以.py结尾的文件),Exec设置程序执行语言和文件所在路径,设置图标Icon。设置完这几个参数后,将Terminal和MultipleArgs设置为相应的Bool值,保存关闭即可完成开机自启的设置。
第五部分 系统调试
1.动态表情识别
简单来说,面部表情是人体(形体)语言的一部分,是一种生理及心理的反应,通常用于传递情感。人类的面部表情有很多种,目前对高兴、吃惊、悲伤、愤怒、厌恶和恐惧6种人类基本表情的识别情况比较好,能较好的识别到面部表情,并给出标识、发送指令控制人机交互设备完成相应的动作。
由于人情感的复杂性,这些表情还不足以完全确定一个人内心深处的情绪波动,如要提高判断的准确性,还需要通过心率检测、语音处理等综合评价。
2.智能语音实现情况
语音识别采用LDV5语音模块和FPGA的语音采样、滤波、识别实现。经过长时间的调试和参数设定,针对常用的语句识别率较高,通过本地语义分析检索,完成语音聊天功能。智能语音对答、轻音乐播放、讲故事、语音控制光立方显示等功能现都比较完善,但语音识别率还有待提高,响应时间也需要再降低。
3.全彩光立方显示
4.整体实现情况
树莓派上电后打开摄像头,进行动态表情识别,当识别到面部表情后,播放调节情绪的背景音乐。同时,通过蓝牙通信发送指令给STM32,控制光立方显示不同的三维动画,配合播放的背景音乐营造出轻松舒适而温馨的家居环境,能有效缓解人的精神压力、舒缓情绪。
来源:CSDN
作者:Tony Zhang
链接:https://blog.csdn.net/Charmve/article/details/103464674