python实现一个简洁siri功能

这篇文章主要介绍了关于python利用不到一百行代码实现了一个小siri的相关资料,文中介绍的很详细,对大家具有一定的参考借鉴价值,需要的朋友们下面来一起看看吧。

前言

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

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

设计思路

立即学习“Python免费学习笔记(深入)”;

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

算法流程:

python实现一个简洁siri功能

特征提取

和之前的听歌识曲一样,同样是将一秒钟分成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)为两个特征的距离代价。

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

python实现一个简洁siri功能 

我们需要从(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),这就是两个音频的距离。

python实现一个简洁siri功能 

python实现一个简洁siri功能 

python实现一个简洁siri功能 

源代码和注释

# coding=utf8import osimport waveimport dtwimport numpy as npimport pyaudiodef 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:programTencentQQBinQQScLauncher.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:datamusic\audio\audio\ (9).wav') #播放一段音乐 # r = record() # r.record(RECORD_SECONDS=3,WAVE_OUTPUT_FILENAME='zhimakaimen_09.wav')

登录后复制

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

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

【相关推荐】

1. Python免费视频教程

2. Python基础入门手册

3. 马哥教育python基础语法全讲解视频

以上就是python实现一个简洁siri功能的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2273261.html

(0)
上一篇 2025年2月27日 13:18:54
下一篇 2025年2月27日 13:19:11

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • Python基础篇之正则表达式

    正则表达式并不是python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。下面这篇文章主要介绍了关于python正则表达式基础的相关资料,需要的朋友…

    编程技术 2025年2月27日
    200
  • Python捕获篇之正则表达式

    什么是捕获呢?使用小括号指定一个子表达式后,匹配这个子表达式的文本(即匹配的内容)可以在表达式或者其他过程中接着用,下面这篇文章就主要介绍了python正则表达式中关于捕获的相关资料,需要的朋友可以参考下。 前言 在上一篇文中,我们介绍了关…

    编程技术 2025年2月27日
    200
  • Python关于正则贪婪与非贪婪特性的详解

    这篇文章主要介绍了python正则表达式中贪婪/非贪婪特性的相关资料,文中通过示例代码介绍的很详细,对大家具有一定的参考价值,需要的朋友下面来一起看看吧。 之前已经简单介绍了Python正则表达式的基础与捕获,那么在这一篇文章里,我将总结一…

    编程技术 2025年2月27日
    200
  • 非强制终止python线程的方法介绍

    本文给大家分享的是走着的一些强制杀掉python线程经验教训,如果你使用强制手段干掉线程,那么很大几率出现意想不到的bug。  请记住一点,锁资源不会因为线程退出而释放锁资源 ! 前言:     不要试图用强制方法杀掉一个python线程,…

    编程技术 2025年2月27日
    200
  • Python多进程导入CSV至数据库

    本文给大家分享的是使用python实现多进程导入csv文件数据到mysql的思路方法以及具体的代码分享,有相同需求的小伙伴可以参考下 前段时间帮同事处理了一个把 CSV 数据导入到 MySQL 的需求。两个很大的 CSV 文件, 分别有 3…

    编程技术 2025年2月27日
    200
  • 详解防止sql注入的python方法

    sql注入是比较常见的网络攻击方式之一,它不是利用操作系统的bug来实现攻击,而是针对程序员编程时的疏忽,通过sql语句,实现无帐号登录,甚至篡改数据库。下面这篇文章主要给大家介绍了关于python中防止sql注入的方法,需要的朋友可以参考…

    编程技术 2025年2月27日
    200
  • python识别验证码的代码详解

    这篇文章主要介绍了python中识别验证码的相关资料,这属于学习python的基本入门教程,文中介绍的非常详细,文末也给出了完整的示例代码,需要的朋友们可以参考学习,下面来一起看看吧。 前言 验证码?我也能破解? 关于验证码的介绍就不多说了…

    2025年2月27日 编程技术
    200
  • 链接和操作 memcache的方法详解

    下面小编就为大家带来一篇python 链接和操作 memcache方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 1,打开memcached服务 memcached -m 10 -p 12000 登录后复…

    编程技术 2025年2月27日
    200
  • 简述SQLAlchemy中排序的容易犯的一个错误

    这篇文章主要介绍了关于python中sqlalchemy排序的一个坑,文中给出了详细的示例代码,需要的朋友可以参考借鉴,感兴趣的朋友们下面来一起学习学习吧。 前言 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数…

    编程技术 2025年2月27日
    200
  • 关于python函数中的参数详解

    昨天看《python核心编程》的时候,刚好看到了函数部分,于是顺势将目前接触到的集中参数类型都总结一下吧^^ (1)       位置参数,调用函数时按位置传入参数 (2)       默认参数,即在函数定义时就给出参数的值,设置默认参数时…

    编程技术 2025年2月27日
    200

发表回复

登录后才能评论