帖子

[demo分享] 【经验分享】树莓派+讯飞云制作有表情笑脸的语音机器人

[复制链接]

该用户从未签到

29039  楼主| logbird 发表于 2017-3-1 14:52:26 1#
本文为作者logbird原创,仅限在讯飞开放平台论坛内交流,任何人员不得擅自转载。

之前业余时间搞另一个可以学习的语音机器人玩了玩,具体效果如下:
1、可以通过对话完成简单的回答
2、可以通过屏幕显示出机器人的脸(包括表情之类的)
3、如果机器人回答不满意,可以通过语音让机器人学习,比如你问你叫什么名字,机器人回答我叫xxx,你告诉他不对你叫小明,然后下次再问,机器人就回答我叫小明。

准备工作:
基础硬件设备:
Raspberry Pi 3 Model
树莓派3 专用3.5寸触摸屏
USB树莓派麦克风
Leadsound/领尚 F10手机音箱 迷你直插便携小音响外接扩音器喇叭

软件相关:
讯飞的sdk树莓派版本的使用C语言完成调用。
录音、识别、语义分析、语音合成的调度使用python完成
笑脸的绘制使用PyGame来进行绘制。
录音部分使用 arecord 处理

简单进程流程图:
小智.jpg


大概思路是这样,具体实现如果感兴趣,稍后会一一介绍。

附一个pygame实现眨眼的代码给大家参考:

[mw_shl_code=python,true]#coding:utf8
import pygame
from pygame.locals import *

class SpriteEYES(pygame.sprite.Sprite):
    #鼻子宽度
    NOSE_WIDTH = 30
    #眼睛颜色
    EYE_COLOR = (0, 255, 255)
    #眼睛最大最小高度
    EYES_HEIGHT_MAX = 60
    EYES_HEIGHT_MIN = 15
    #眼睛宽度
    EYES_WIDTH = 120
    #眼睛高度
    EYES_HEIGHT = EYES_HEIGHT_MAX
    #睁眼动作
    EYE_OPEN = False
    #眨眼速度 眨眼 闭眼 + 睁眼, 每秒眨眼 3 次,眨眼距离 = 睁眼距离+闭眼距离,每秒眨眼三次,速度为 眨眼距离 * 3
    EYES_SPEED = (EYES_HEIGHT_MAX - EYES_HEIGHT_MIN) * 2 * 2
   
    angle = 0
    pos = (0, 0)
    wink_sum = None
    wink_time = None

    def __init__(self, pos, angle = 0):
        pygame.sprite.Sprite.__init__(self)
        self.draw()
        self.pos = pos
        self.angle = angle
        self.resetWink()

    def draw(self):
        self.image = pygame.Surface([self.EYES_WIDTH, self.EYES_HEIGHT_MAX]).convert()
        self.rect = self.image.get_rect()
        self.rect.topleft = self.pos
        self.image.fill((0, 0, 0))
        x = 0
        y = 0
        y = (self.EYES_HEIGHT_MAX - self.EYES_HEIGHT) / 2
        pygame.draw.ellipse(self.image, self.EYE_COLOR, Rect((x, y, self.EYES_WIDTH, self.EYES_HEIGHT)), 0)
        self.image = pygame.transform.rotate(self.image, self.angle)

    def resetWink(self):
        self.wink_time = 0
        self.wink_sum = 0

    def timePassed(self, ticks):
        self.wink_time += ticks
        return self.wink_time

    def doWink(self, ticks):
        ticks = ticks / 1000.0
        eye_distance = int(ticks * self.EYES_SPEED)
        #眨眼动作
        if self.EYE_OPEN:
            self.EYES_HEIGHT += eye_distance
        else:
            self.EYES_HEIGHT -= eye_distance
        #睁眼还是闭眼
        if self.EYES_HEIGHT > self.EYES_HEIGHT_MAX:
            self.wink_sum += 1
            #重置
            self.EYES_HEIGHT = self.EYES_HEIGHT_MAX
            self.EYE_OPEN = False
        elif self.EYES_HEIGHT < self.EYES_HEIGHT_MIN:
            #重置
            self.EYES_HEIGHT = self.EYES_HEIGHT_MIN
            self.EYE_OPEN = True
        self.draw()


class SpriteHeartEYES(SpriteEYES):
     #眼睛最大最小高度
    EYES_HEIGHT_MAX = 120
    EYES_HEIGHT_MIN = 60
    EYES_WIDTH_MAX = 120
    EYES_WIDTH_MIN = 60
    #鼻子宽度
    NOSE_WIDTH = 60
    #眼睛宽度高度
    EYES_WIDTH = 70
    EYES_HEIGHT = 70

    def __init__(self, pos, angle = 0):
        SpriteEYES.__init__(self, pos, angle)

    def draw(self):
        self.image = pygame.Surface([self.EYES_WIDTH, self.EYES_HEIGHT]).convert()
        self.rect = self.image.get_rect()
        x = self.pos[0] - int((self.EYES_WIDTH - self.EYES_WIDTH_MIN)/2)
        y = self.pos[1] - int((self.EYES_HEIGHT - self.EYES_HEIGHT_MIN)/2)
        self.rect.topleft = (x, y)
        self.image.fill((0, 0, 0))
        radus = int(self.EYES_WIDTH * 0.3)
        pygame.draw.circle(self.image, self.EYE_COLOR, (radus, radus), radus, 0)
        pygame.draw.circle(self.image, self.EYE_COLOR, (self.EYES_WIDTH - radus, radus), radus, 0)
        pygame.draw.polygon(self.image, self.EYE_COLOR, [(0, radus), (int(self.EYES_WIDTH/2), self.EYES_HEIGHT), (self.EYES_WIDTH, radus)], 0)

    def doWink(self, ticks):
        ticks = ticks / 1000.0
        eye_distance = int(ticks * self.EYES_SPEED)
        #睁眼还是闭眼
        if self.EYES_HEIGHT > self.EYES_HEIGHT_MAX:
            self.wink_sum += 1
            #重置
            self.EYES_HEIGHT = self.EYES_HEIGHT_MAX
            self.EYE_OPEN = False
        elif self.EYES_HEIGHT < self.EYES_HEIGHT_MIN:
            #重置
            self.EYES_HEIGHT = self.EYES_HEIGHT_MIN
            self.EYE_OPEN = True
        #眨眼动作
        if self.EYE_OPEN:
            self.EYES_HEIGHT += eye_distance
            self.EYES_WIDTH += eye_distance
        else:
            self.EYES_HEIGHT -= eye_distance
            self.EYES_WIDTH -= eye_distance
        self.draw()
[/mw_shl_code]


评分

参与人数 2语点 +13 收起 理由
嘉木 + 8
栗子讲究 + 5 很给力!

查看全部评分

iflytek-小黑 发表于 2017-3-1 15:24:47
2#
楼主加油,~!抢个沙发先
使用道具 举报 回复
嘉木 发表于 2017-3-1 15:26:10
3#
哇厉害,学习一下
使用道具 举报 回复
guqiao 发表于 2017-3-2 23:45:06 来自手机
4#
楼主6得飞起啊,楼上的肯定学不会的。
使用道具 举报 回复
杨什么鸣 发表于 2017-3-3 09:38:57
5#
本帖最后由 杨什么鸣 于 2017-3-3 09:52 编辑

楼主,我比较好奇第三步纠正训练是怎么做的呢,图片里的更新自定义语义库怎么做到呢?我还一直以为自定义问答的话只能人为手动在开放语义网页上上传更新
使用道具 举报 回复
maxweng 发表于 2017-3-8 12:44:42
6#
请问楼主, Python的SDK哪儿可以下载?
使用道具 举报 回复
fendoumo 发表于 2017-5-18 10:11:05
7#
楼主太牛了,顶一个
使用道具 举报 回复
JZ2440 发表于 2017-6-12 11:37:36
8#
由于公司保密限制,即使看到与众不同的帖子,也不能流露出任何感谢的言辞。
使用道具 举报 回复
JZ2440 发表于 2017-6-12 11:38:02
9#
正好我有一块树莓派的板子,可以试一下
使用道具 举报 回复
1078452503@qq.c 发表于 2018-3-6 15:47:34
10#
扩展思路了 楼主666
使用道具 举报 回复