全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

python利用不到一百行代码实现一个小siri

前言

如果想要容易理解核心的特征计算的话建议先去看看我之前的听歌识曲的文章,传送门:https://www./article/97305.htm

本文主要是实现了一个简单的命令词识别程序,算法核心一是提取音频特征,二是用DTW算法进行匹配。当然,这样的代码肯定不能用于商业化,大家做出来玩玩娱乐一下还是不错的。

设计思路

就算是个小东西,我们也要先明确思路再做。音频识别,困难不小,其中提取特征的难度在我听歌识曲那篇文章里能看得出来。而语音识别难度更大,因为音乐总是固定的,而人类说话常常是变化的。比如说一个“芝麻开门”,有的人就会说成“芝麻开门”,有的人会说成“芝麻开门”。而且在录音时说话的时间也不一样,可能很紧迫的一开始录音就说话了,也可能不紧不慢的快要录音结束了才把这四个字说出来。这样难度就大了。

算法流程:


特征提取

和之前的听歌识曲一样,同样是将一秒钟分成40块,对每一块进行傅里叶变换,然后取模长。只是这不像之前听歌识曲中进一步进行提取峰值,而是直接当做特征值。

看不懂我在说什么的朋友可以看看下面的源代码,或者看听歌识曲那篇文章。

DTW算法

DTW,Dynamic Time Warping,动态时间归整。算法解决的问题是将不同发音长短和位置进行最适合的匹配。

算法输入两组音频的特征向量: A:[fp1,fp2,fp3,......,fpM1] B:[fp1,fp2,fp3,fp4,.....fpM2]
A组共有M1个特征,B组共有M2个音频。每个特征向量中的元素就是之前我们将每秒切成40块之后FFT求模长的向量。计算每对fp之间的代价采用的是欧氏距离。

设D(fpa,fpb)为两个特征的距离代价。

那么我们可以画出下面这样的图

 

我们需要从(1,1)点走到(M1,M2)点,这会有很多种走法,而每种走法就是一种两个音频位置匹配的方式。但我们的目标是走的总过程中代价最小,这样可以保证这种对齐方式是使我们得到最接近的对齐方式。

我们这样走:首先两个坐标轴上的各个点都是可以直接计算累加代价和求出的。然后对于中间的点来说D(i,j) = Min{D(i-1,j)+D(fpi,fpj) , D(i,j-1)+D(fpi,fpj) , D(i-1,j-1) + 2 * D(fpi,fpj)}

为什么由(i-1,j-1)直接走到(i,j)这个点需要加上两倍的代价呢?因为别人走正方形的两个直角边,它走的是正方形的对角线啊

按照这个原理选择,一直算到D(M1,M2),这就是两个音频的距离。

 

 

 

源代码和注释

# coding=utf8
import os
import wave
import dtw
import numpy as np
import pyaudio

def compute_distance_vec(vec1, vec2):
 return np.linalg.norm(vec1 - vec2) #计算两个特征之间的欧氏距离

class record():
 def record(self, CHUNK=44100, FORMAT=pyaudio.paInt16, CHANNELS=2, RATE=44100, RECORD_SECONDS=200,
    WAVE_OUTPUT_FILENAME="record.wav"):
  #录歌方法
  p = pyaudio.PyAudio()
  stream = p.open(format=FORMAT,
      channels=CHANNELS,
      rate=RATE,
      input=True,
      frames_per_buffer=CHUNK)
  frames = []
  for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
   data = stream.read(CHUNK)
   frames.append(data)
  stream.stop_stream()
  stream.close()
  p.terminate()
  wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
  wf.setnchannels(CHANNELS)
  wf.setsampwidth(p.get_sample_size(FORMAT))
  wf.setframerate(RATE)
  wf.writeframes(''.join(frames))
  wf.close()

class voice():
 def loaddata(self, filepath):
  try:
   f = wave.open(filepath, 'rb')
   params = f.getparams()
   self.nchannels, self.sampwidth, self.framerate, self.nframes = params[:4]
   str_data = f.readframes(self.nframes)
   self.wave_data = np.fromstring(str_data, dtype=np.short)
   self.wave_data.shape = -1, self.sampwidth
   self.wave_data = self.wave_data.T #存储歌曲原始数组
   f.close()
   self.name = os.path.basename(filepath) # 记录下文件名
   return True
  except:
   raise IOError, 'File Error'

 def fft(self, frames=40):
  self.fft_blocks = [] #将音频每秒分成40块,再对每块做傅里叶变换
  blocks_size = self.framerate / frames
  for i in xrange(0, len(self.wave_data[0]) - blocks_size, blocks_size):
   self.fft_blocks.append(np.abs(np.fft.fft(self.wave_data[0][i:i + blocks_size])))
 @staticmethod
 def play(filepath):
  chunk = 1024
  wf = wave.open(filepath, 'rb')
  p = pyaudio.PyAudio()
  # 播放音乐方法
  stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
      channels=wf.getnchannels(),
      rate=wf.getframerate(),
      output=True)
  while True:
   data = wf.readframes(chunk)
   if data == "": break
   stream.write(data)
  stream.close()
  p.terminate()
if __name__ == '__main__':
 r = record()
 r.record(RECORD_SECONDS=3, WAVE_OUTPUT_FILENAME='record.wav')
 v = voice()
 v.loaddata('record.wav')
 v.fft()
 file_list = os.listdir(os.getcwd())
 res = []
 for i in file_list:
  if i.split('.')[1] == 'wav' and i.split('.')[0] != 'record':
   temp = voice()
   temp.loaddata(i)
   temp.fft()
   res.append((dtw.dtw(v.fft_blocks, temp.fft_blocks, compute_distance_vec)[0],i))
 res.sort()
 print res
 if res[0][1].find('open_qq') != -1:
  os.system('C:\program\Tencent\QQ\Bin\QQScLauncher.exe') #我的QQ路径
 elif res[0][1].find('zhimakaimen') != -1:
  os.system('chrome.exe')#浏览器的路径,之前已经被添加到了Path中了
 elif res[0][1].find('play_music') != -1:
  voice.play('C:\data\music\\audio\\audio\\ (9).wav') #播放一段音乐
 # r = record()
 # r.record(RECORD_SECONDS=3,WAVE_OUTPUT_FILENAME='zhimakaimen_09.wav')

事先可以先用这里的record方法录制几段命令词,尝试用不同语气说,不同节奏说,这样可以提高准确度。然后设计好文件名,根据匹配到的最接近音频的文件名就可以知道是哪种命令,进而自定义执行不同的任务

这是一段演示视频:http://www.iqiyi.com/w_19ruisynsd.html

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者使用python能带来一定的帮助,如果有疑问大家可以留言交流。


# python实现小功能  # siri实现原理  # siri技术实现  # python3音乐播放器简单实现代码  # Python通过90行代码搭建一个音乐搜索工具  # 听歌识曲--用python实现一个音乐检索器的功能  # Python实现提取谷歌音乐搜索结果的方法  # 听歌  # 的是  # 走到  # 求出  # 说成  # 源代码  # 那篇  # 切成  # 都是  # 这是  # 特征值  # 就会  # 是个  # 也不  # 我在  # 在我  # 这就是  # 一是  # 说什么  # 更大 


相关文章: 一键网站制作软件,义乌购一件代发流程?  太原网站制作公司有哪些,网约车营运证查询官网?  详解jQuery中基本的动画方法  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何高效配置IIS服务器搭建网站?  如何在服务器上三步完成建站并提升流量?  陕西网站制作公司有哪些,陕西凌云电器有限公司官网?  装修招标网站设计制作流程,装修招标流程?  郑州企业网站制作公司,郑州招聘网站有哪些?  东莞专业制作网站的公司,东莞大学生网的网址是什么?  建站之星安装后如何自定义网站颜色与字体?  网站微信制作软件,如何制作微信链接?  图册素材网站设计制作软件,图册的导出方式有几种?  南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?  建站主机类型有哪些?如何正确选型  可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?  网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?  建站之星如何保障用户数据免受黑客入侵?  制作网站的软件免费下载,免费制作app哪个平台好?  建站之星后台管理系统如何操作?  h5网站制作工具有哪些,h5页面制作工具有哪些?  建站之星如何快速生成多端适配网站?  在线制作视频的网站有哪些,电脑如何制作视频短片?  建站之星如何优化SEO以实现高效排名?  建站之星免费版是否永久可用?  如何通过二级域名建站提升品牌影响力?  小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  MySQL查询结果复制到新表的方法(更新、插入)  如何用腾讯建站主机快速创建免费网站?  网站制作专业公司有哪些,如何制作一个企业网站,建设网站的基本步骤有哪些?  如何选择最佳自助建站系统?快速指南解析优劣  相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?  韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐  整蛊网站制作软件,手机不停的收到各种网站的验证码短信,是手机病毒还是人为恶搞?有这种手机病毒吗?  如何选择靠谱的建站公司加盟品牌?  黑客如何通过漏洞一步步攻陷网站服务器?  ,巨量百应是干嘛的?  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  上海网站制作网站建设公司,建筑电工证网上查询系统入口?  公司网站制作费用多少,为公司建立一个网站需要哪些费用?  建站之星如何取消后台验证码生成?  定制建站平台哪家好?企业官网搭建与快速建站方案推荐  Swift中swift中的switch 语句  香港服务器WordPress建站指南:SEO优化与高效部署策略  小型网站建站如何选择虚拟主机?  建站上市公司网站建设方案与SEO优化服务定制指南  香港网站服务器数量如何影响SEO优化效果?  建站之星如何实现网站加密操作?  如何快速上传自定义模板至建站之星? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。