利用Python通过频谱分析和KNN完成iphone拨号的语音识别

【SLP·Python】基于 DTW GMM HMM 三种方法实现的语音分类识别系统 前言 在孤立词语音识别(Isolated Word Speech Recognition) 中,DTW,GMM 和 HMM 是三种典型的方法: 动态时间规整(DTW, Dyanmic Time Warping) 高斯混合模型(GMM, Gaussian Mixed Model) 隐马尔可夫模型(HMM, Hidden Markov Model) 本文并不介绍这三种方法的基本原理,而是侧重于 Python 版代码的实现,针对一个具体的语音识别任务——10 digits recognition system 阅读详情

原文

最近这段时间,学校里的事情实在太多了,从七月下旬一直到八月底实验室里基本天天十二点或者通宵,实在是没有精力和时间来写博客。这周老师出国开会,也算有了一个短暂的休息机会,刚好写点有意思的东西。

上周在天津的会议上碰到一个北交的姐们儿,她想利用小波变换来处理失超信号,刚好之前自己就有这个想法,所以回来后就想着把相关的内容好好复习复习,最相关的就是傅里叶分析和小波变换了。数学推导固然重要,但写那个实在是太乏味了,然后想到之前网上一个新闻,说一个同学通过新闻里记者拨号的声音反推出了周鸿祎的手机号码,就想着能不能自己也做一个这样的号码识别程序呢?

说做就做,首先整理一下思路,我觉得大概的流程应该包括一下几步:

1 单键声音的采集与分析

这是后面号码识别的基础,针对每个按键音分析其在频域上的分布规律进而得到一个基准,后面再采集到的声音可据此进行判定。

2 声音的降噪

自己录的这些声音总不会太完美,直接进行频谱分析,会得到一个非常杂乱的结果,所以有效的声音降噪可以帮助我们更加精确地进行判断。

3 号码识别思路

我想的方案主要是两种,刚好也符合我最近复习的这两种变换

A 对声音文件进行有效区域划分,然后对每个区域单独进行频谱分析,然后比对训练数据,推断每一处对应的号码,最后输出。

B 采用小波分析,输出对应声音文件的小波时频图,观察其在不同时刻频域各处强度的变化,进而确定所拨的号码。

两种方案我感觉应该都可以,不过第一种感觉相对要简单一点,所以我们就先来试试第一个。

Ok,那第一步我们得先找到合适的单个按键音数据,这个上网一搜iphone按键音就找到了,下载下来发现刚好又是wav文件,可以用Python自带的wave库直接处理,简直美滋滋。

简单说一下wave库,用它读取一个wave文件后,我们可以获取四个参数,包括通道数目,样本宽度,采样率以及采样数目。根据通道数目,你可以确定是单通道和双通道,如果是单通道你直接读取采样文件就行,但如果是双通道,采样是一左一右轮着来的,所以到时候你还得把它分成两列,然后选择其中一列来读。从网上下载的这些音源刚好是单声道的,所以直接读取就行了,下面以0为例,读取它的波形并画出来。

复制代码

import numpy as np  
import wave  
from matplotlib import pyplot as plt  
file_path='C:\Users\**\Desktop\iphone\dtmf-0.wav'  
f=wave.open(file_path,'rb')  
num=file_path[-5]   
params=f.getparams()  
nchannels,samplewidth,framerate,nframes=params[:4]  
str_data=f.readframes(nframes)  
f.close()  
wave_data=np.fromstring(str_data,dtype=np.short)  
wave_data.shape=-1,1  
if nchannels==2:  
    wave_data.shape=-1,2  
else:  
    pass  
wave_data=wave_data.T  
time=np.arange(0,nframes)*(1.0/framerate)  
plt.subplot(211)  
plt.plot(time,wave_data[0],'r-')  
plt.xlabel('Time/s')  
plt.ylabel('Ampltitude')  
plt.title('Num '+num+' time/ampltitude')  
plt.show() 

复制代码

结果如下

其实波形看起来还是比较规律的,但明显是有不同频率的波叠加在一起,所以下一步我们采用傅里叶分析,看看它在频域上是什么样的。Python中进行傅里叶分析是十分方便的,直接利用numpy中的fft就行,分解完成后,考虑到高频的成分不需要,所以选择4000做个阈值,超出这个区域的都舍掉。另外,因为目前我并不考虑信号的重构,所以我直接把对应频率的幅值去了绝对值,这样方便我下一步寻找波峰。完成这些操作后,画个频谱图看看有什么规律。

复制代码

df=framerate/(nframes-1)  
freq=[df*n for n in range(0,nframes)]  
transformed=np.fft.fft(wave_data[0])  
d=int(len(transformed)/2)  
while freq[d]>4000:  
    d-=10  
freq=freq[:d]  
transformed=transformed[:d]  
for i,data in enumerate(transformed):  
    transformed[i]=abs(data)  
plt.subplot(212)  
plt.plot(freq,transformed,'b-')  
plt.xlabel('Freq/Hz')  
plt.ylabel('Ampltitude')  
plt.title('Num '+num+' freq/ampltitude')  
plt.show() 

复制代码

结果如下

哎呀我去,这也太完美了吧……我都怀疑下的这些波形文件是电脑写的,也太规整了,仅在两个频率处出现了峰值,其余处为0,感觉事情并不简单,上网查了一圈发现Iphone的按键音采用的是DTMF,双音多频,每个按键音都是一个高频加一个低频信号的叠加。原来如此,那我就放心继续做下去了。那么下一步是提取这两个频率值,上面我已经说了,为了方便我寻找这两个波峰,我已经将平率对应幅度全部取绝对值,现在其实就是找到两个局部极值对应的频率就好。那首先找到两个极大值,然后确定它们的位置再对应到频域上就OK,代码如下

复制代码

local_max=[]  
for i in np.arange(1,len(transformed)-1):  
    if transformed[i]>transformed[i-1] and transformed[i]>transformed[i+1]:  
        local_max.append(transformed[i])  
local_max=sorted(local_max)  
loc1=np.where(transformed==local_max[-1])  
max_freq=freq[loc1[0][0]]  
loc1=np.where(transformed==local_max[-2])  
min_freq=freq[loc1[0][0]]  
print 'Two freq ',max_freq,min_freq

复制代码

结果如下

Two freq  1278 900

 

好的,针对一个数字的音频分析完成了,那其他的数字也如法炮制,定义一个函数,再用个循环就好,最后把这些数字所对应的频率画在图上,整体代码如下:

复制代码

import wave  
import numpy as np  
from matplotlib import pyplot as plt  
  
def wave_analysis(file_path):  
    f=wave.open(file_path,'rb')  
    num=file_path[-5]   
    params=f.getparams()  
    nchannels,samplewidth,framerate,nframes=params[:4]  
    str_data=f.readframes(nframes)  
    f.close()  
    wave_data=np.fromstring(str_data,dtype=np.short)  
    wave_data.shape=-1,1  
    if nchannels==2:  
        wave_data.shape=-1,2  
    else:  
        pass  
    wave_data=wave_data.T  
    time=np.arange(0,nframes)*(1.0/framerate)  
    plt.subplot(211)  
    plt.plot(time,wave_data[0],'r-')  
    plt.xlabel('Time/s')  
    plt.ylabel('Ampltitude')  
    plt.title('Num '+num+' time/ampltitude')  
    plt.show()  
    df=framerate/(nframes-1)  
    freq=[df*n for n in range(0,nframes)]  
    transformed=np.fft.fft(wave_data[0])  
    d=int(len(transformed)/2)  
    while freq[d]>4000:  
        d-=10  
    freq=freq[:d]  
    transformed=transformed[:d]  
    for i,data in enumerate(transformed):  
        transformed[i]=abs(data)  
    plt.subplot(212)  
    plt.plot(freq,transformed,'b-')  
    plt.xlabel('Freq/Hz')  
    plt.ylabel('Ampltitude')  
    plt.title('Num '+num+' freq/ampltitude')  
    local_max=[]  
    for i in np.arange(1,len(transformed)-1):  
        if transformed[i]>transformed[i-1] and transformed[i]>transformed[i+1]:  
            local_max.append(transformed[i])  
    local_max=sorted(local_max)  
    loc1=np.where(transformed==local_max[-1])  
    max_freq=freq[loc1[0][0]]  
    loc1=np.where(transformed==local_max[-2])  
    min_freq=freq[loc1[0][0]]  
    plt.show()  
    print 'Two freq ',max_freq,min_freq  
    return max_freq,min_freq  
      
  
def main():  
    x=[]  
    y=[]  
    for i in np.arange(0,10):  
        path='C:\Users\<span style="font-family: Arial, Helvetica, sans-serif;">**</span><span style="font-family: Arial, Helvetica, sans-serif;">\Desktop\iphone\dtmf-'+str(i)+'.wav'</span>  
        max_freq,min_freq=wave_analysis(path)  
        x.append(i)  
        y.append(max_freq)  
        x.append(i)  
        y.append(min_freq)  
    plt.scatter(x,y,marker='*')  
    plt.show()  
  
if __name__=='__main__':  
    main()

复制代码

中间的振幅和频域的图就不贴了,就看一下最后一张每个数字所对应的特定频率图

把数字填到表格里是这样

 

其实规律还是很容易看出来的,每个按键音对应于一个高频和一个低频,其中,123,456,789的低频部分相似,147,258,369的高频部分相似,这和DTMF是一致的,从百科上扒了一张图,大家可以对比一下

展现出来的规律是相似的,但数值并不完全一样,我们计算出来的似乎有那么一点点偏小,但这并不重要,赶紧拿个实际录音来看看吧。

先录了10个单音,看看频谱分析怎么样,完全同样的方法,针对数字0,结果如下

Two freq  1283 1270

发现问题了没

1 录音的数据并不是全程都是按键音,很大一部分是无用的,整体进行傅里叶分析会产生非常大的干扰信号

2 录音的数据里叠加有很多噪声,导致频域分布复杂。

3 频域信号里有很多的毛刺,这样导致产生了很多局部极大值,导致我们之前用的寻找波峰的算法失效。

OKOK,那我们一步步来解决问题。

首先第一个相当于就是有效波形的提取了。高级的方法我也不会啊,但就直观来看,明显有效区域的波形幅度远大于无效区,那我们是不是可以取个阈值,从第一个超过该阈值的开始记为起始点,然后连续超过多少个点都小于阈值后记为终止点,当然可以,在这里我选择的阈值是最大值的5%,事实表明这样还是很有效的。

那对与第二个问题,其实噪声很多都是高频的,首先滤除高频部分是一个选项,其次即使是噪声,它往往也是周期性的,一个周期内的噪声叠加起来往往为0,所以我们选一个时间窗口,进行移动平均,这样可以有效的消除噪声的影响。同时,这也能解决第三步遇到的问题,移动平均最大的好处就是会使曲线变得光滑,不会出现很多的毛刺,这样通过移动平均处理后的频域图又可以重新使用我们之前所说的寻找局部极值来确定频率的方法。哦,对了对了,移动平均可以通过卷积操作来实现,非常简单。代码如下

复制代码

import wave  
import numpy as np  
from matplotlib import pyplot as plt  
#load wave file and get params  
file_path='C:\\Users\\**\\Desktop\\iphone\\Test\\0.wav'  
f=wave.open(file_path,'rb')  
#num=file_path[-5]   
num=str(0)  
params=f.getparams()  
nchannels,samplewidth,framerate,nframes=params[:4]  
str_data=f.readframes(nframes)  
f.close()  
wave_data=np.fromstring(str_data,dtype=np.short)  
wave_data.shape=-1,1  
if nchannels==2:  
    wave_data.shape=-1,2  
else:  
    pass  
wave_data=wave_data.T  
#moving average  
def moving_average(data,n):  
    weights=np.ones(n)  
    weights/=weights.sum()  
    ma=np.convolve(data,weights,mode='full')[:len(data)]  
    ma[:n]=ma[n]  
    return ma  
  
new_data=moving_average(wave_data[0],10)  
new_data=moving_average(new_data,10)  
new_data_2=[]  
max_wave=new_data.max()  
#look for the start point and end point  
index=0  
flag=False  
for i in np.arange(0,len(new_data)):  
#    index=0  
    if abs(new_data[i])>=0.05*max_wave:  
        new_data_2.append(new_data[i])  
        index=0  
        if abs(new_data[i+1])<0.05*max_wave:  
            for j in np.arange(1,40):  
                if abs(new_data[i+1+j])<0.05*max_wave:  
                    index+=1  
                    if index>=39:  
                        print index   
                        flag=True  
                        break  
    if flag==True:  
        break  
                  
  
time=np.arange(0,len(new_data_2))*(1.0/framerate)  
plt.subplot(211)  
plt.plot(time,new_data_2,'r-')  
plt.xlabel('Time/s')  
plt.ylabel('Ampltitude')  
plt.title('Num '+num+' time/ampltitude')  
plt.show()  
df=framerate/(len(new_data_2)-1)  
freq=[df*n for n in range(0,len(new_data_2))]  
transformed=np.fft.fft(new_data_2)  
d=int(len(transformed)/2)  
while freq[d]>2000:  
    d-=10  
freq=freq[:d]  
transformed=transformed[:d]  
for i,data in enumerate(transformed):  
    transformed[i]=abs(data)  
transformed=moving_average(transformed,5)  
transformed=moving_average(transformed,5)  
transformed=moving_average(transformed,5)      
plt.subplot(212)  
plt.plot(freq,transformed,'b-')  
plt.xlabel('Freq/Hz')  
plt.ylabel('Ampltitude')  
plt.title('Num '+num+' freq/ampltitude')  
plt.show()  
#look for local maximum  
local_max=[]  
for i in np.arange(1,len(transformed)-1):  
    if transformed[i]>transformed[i-1] and transformed[i]>transformed[i+1]:  
        local_max.append(transformed[i])  
local_max=sorted(local_max)  
loc1=np.where(transformed==local_max[-1])  
freq1=freq[loc1[0][0]]  
loc1=np.where(transformed==local_max[-2])  
freq2=freq[loc1[0][0]]  
      
              
print 'Two freq ',freq1,freq2

复制代码

结果如下

Two freq  1368 981

蛤蛤蛤,perfect!!!有效信号的提取以及频谱分析都没有问题了,唯一的遗憾就是分解出来的两个频率值又和之前下载的版本不一致了,不过没关系,我们还是要相信实际结果。接下来依次对录的其他号码进行分析,得到新的各个号码对应两个频率值。

得到了所有号码对应的两个频率值之后,我们就可以对再采集的信号进行预测了。采用什么预测方法呢?在之前博客里写过很多很多分类方法,但我觉得都不用,为啥呢,训练数据太少了,算法再高级也没卵用,哎呀,好丧啊……那我们就用最朴素的方法吧,计算采样数据的两个频率与所有训练数据频率的距离,选择最小的那个作为输出,当然你也可以宣称用的是KNN算法,没毛病啊,就是最近邻呀……

回到最开始说的,我们想做的是一个语音号码识别,所以这里还要考虑一段数据包含多个按键音的有效区域提取,因为之前的算法时针对单音的。一开始我以为只要把之前的跳出循环操作改成保存数据,标记置0就OK,后来发现我实在是天真了,这样做的后果就是除了我们真实有效区域以外,偶尔有一个噪声超过阈值的也全都提取出来了。所以除了幅度阈值之外,我对提取的有效区域长度也做了一个限制,进而保提取的区域都是我们的目标区域。

至此,全部的问题都解决了,整合一下代码,最终如下

复制代码

import wave  
import numpy as np  
from matplotlib import pyplot as plt  
  
#moving average  
def moving_average(data,n):  
    weights=np.ones(n)  
    weights/=weights.sum()  
    ma=np.convolve(data,weights,mode='full')[:len(data)]  
    ma[:n]=ma[n]  
    return ma  
  
  
          
#get wave data  
def get_wave_data(file_path):  
    f=wave.open(file_path,'rb')  
    params=f.getparams()  
    nchannels,samplewidth,framerate,nframes=params[:4]  
    str_data=f.readframes(nframes)  
    f.close()  
    wave_data=np.fromstring(str_data,dtype=np.short)  
    wave_data.shape=-1,1  
    if nchannels==2:  
        wave_data.shape=-1,2  
    else:  
        pass  
    wave_data=wave_data.T  
    return wave_data[0],framerate  
  
#find the efficient area in wave  
def find_efficient_area(wave_data):  
    wave_data=moving_average(wave_data,10)  
    wave_data=moving_average(wave_data,10)  
    wave_data=moving_average(wave_data,10)  
    wave_data=moving_average(wave_data,10)  
    new_data=[]  
    max_wave=wave_data.max()  
    efficient_data=[]  
    index=0  
    count=0  
    flag=False  
    for i in np.arange(0,len(wave_data)):  
        if abs(wave_data[i])>=0.05*max_wave:  
            new_data.append(wave_data[i])  
            index=0  
            if i+1>=len(wave_data):  
                break  
            if abs(wave_data[i+1])<0.05*max_wave:  
                for j in np.arange(1,60):  
                    if i+1+j>=len(wave_data):  
                        break  
                    if abs(wave_data[i+1+j])<0.05*max_wave:  
                        index+=1  
                if index>=59:   
                    flag=True  
                          
                  
                
        if flag==True:  
            if len(new_data)>2000:  
#                plt.plot(new_data,'r-')  
#                plt.show()  
                efficient_data.append(new_data)  
                count+=1  
            new_data=[]  
            index=0  
            flag=False  
    print 'Find ',count,' efficient wave'  
    return efficient_data,count  
  
#Analysis single wave data  
def wave_analysis_single(efficient_data,framerate):  
    time=np.arange(0,len(efficient_data[0]))*(1.0/framerate)  
#    plt.plot(time,efficient_data[0],'r-')  
#    plt.xlabel('Time/s')  
#    plt.ylabel('Ampltitude')  
#    plt.title(' time/ampltitude')  
#    plt.show()  
    df=framerate/(len(efficient_data[0])-1)  
    freq=[df*n for n in range(0,len(efficient_data[0]))]  
    transformed=np.fft.fft(efficient_data[0])  
    d=int(len(transformed)/2)  
    while freq[d]>2000:  
        d-=10  
    freq=freq[:d]  
    transformed=transformed[:d]  
    for i,data in enumerate(transformed):  
        transformed[i]=abs(data)  
    transformed=moving_average(transformed,5)  
    transformed=moving_average(transformed,5)  
    transformed=moving_average(transformed,5)  
#    transformed=moving_average(transformed,5)  
#    plt.plot(freq,transformed,'b-')  
#    plt.xlabel('Freq/Hz')  
#    plt.ylabel('Ampltitude')  
#    plt.title(' freq/ampltitude')  
#    plt.show()  
    #look for local maximum  
    local_max=[]  
    for i in np.arange(1,len(transformed)-1):  
        if transformed[i]>transformed[i-1] and transformed[i]>transformed[i+1]:  
            local_max.append(transformed[i])  
    local_max=sorted(local_max)  
    loc1=np.where(transformed==local_max[-1])  
    freq_1=freq[loc1[0][0]]  
    loc1=np.where(transformed==local_max[-2])  
    freq_2=freq[loc1[0][0]]  
    print 'Frequency',freq_1,freq_2  
    return freq_1,freq_2  
          
          
  
  
#Get training data  
train_data={}  
for i in np.arange(0,10):  
    file_path='C:\\Users\\**\\Desktop\\iphone\\Test\\'+str(i)+'.wav'  
    wave_data,framerate=get_wave_data(file_path)  
    data,count=find_efficient_area(wave_data)  
    a,b=wave_analysis_single(data,framerate)  
    train_data[i]=[a,b]  
  
  
  
#multi_number estimate  
def number_estimate(freq1,freq2):  
    err=100000  
    num=0  
    for i in np.arange(0,10):  
        tmp=(freq1-train_data[i][0])**2+(freq2-train_data[i][1])**2  
        if tmp<err:  
            err=tmp  
            num=i  
        else:  
            pass  
    return num  
      
      
#Analysis multi wave data  
def wave_analysis_multi(efficient_data,framerate):  
    num=[]  
    for data in efficient_data:  
        time=np.arange(0,len(data))*(1.0/framerate)  
        plt.plot(time,data,'r-')  
        plt.xlabel('Time/s')  
        plt.ylabel('Ampltitude')  
        plt.title(' time/ampltitude')  
        plt.show()  
        df=framerate/(len(data)-1)  
        freq=[df*n for n in range(0,len(data))]  
        transformed=np.fft.fft(data)  
        d=int(len(transformed)/2)  
        while freq[d]>2000:  
            d-=10  
        freq=freq[:d]  
        transformed=transformed[:d]  
        for i,data in enumerate(transformed):  
            transformed[i]=abs(data)  
        transformed=moving_average(transformed,5)  
        transformed=moving_average(transformed,5)     
        transformed=moving_average(transformed,5)  
        plt.plot(freq,transformed,'b-')  
        plt.xlabel('Freq/Hz')  
        plt.ylabel('Ampltitude')  
        plt.title(' freq/ampltitude')  
        plt.show()  
#        look for local maximum  
        local_max=[]  
        for i in np.arange(1,len(transformed)-1):  
            if transformed[i]>transformed[i-1] and transformed[i]>transformed[i+1]:  
                local_max.append(transformed[i])  
        local_max=sorted(local_max)  
        loc1=np.where(transformed==local_max[-1])  
        freq_1=freq[loc1[0][0]]  
        loc1=np.where(transformed==local_max[-2])  
        freq_2=freq[loc1[0][0]]  
        if freq_1<freq_2:  
            freq_1,freq_2=freq_2,freq_1  
        print freq_1,freq_2  
        num.append(number_estimate(freq_1,freq_2))  
          
      
    print num  
          
file_path='C:\\Users\\**\Desktop\\iphone\\5201314999.wav'  
wave_data,framerate=get_wave_data(file_path)  
data,count=find_efficient_area(wave_data)  
wave_analysis_multi(data,framerate)

复制代码

结果如下

[2, 2, 8, 1, 6, 1, 4, 3, 9, 9]

家里领导很肉麻地录的是5201314999,结果出来效果真的很垃圾啊……不过想想这训练数据这么少,并且采用了那么朴素的判定方法,正确率高了才见鬼了好吧!!!

不过人的智慧是无穷的,通过改变数据移动平均的次数以及一个小trick

复制代码

#A little trick  
train_data[1][0]=train_data[4][0]=train_data[7][0]=(train_data[1][0]+train_data[4][0]+train_data[7][0])/3  
  
train_data[3][0]=train_data[6][0]=train_data[9][0]=(train_data[3][0]+train_data[6][0]+train_data[9][0])/3  
train_data[1][1]=train_data[2][1]=train_data[3][1]=(train_data[1][1]+train_data[2][1]+train_data[3][1])/3  
  
train_data[7][1]=train_data[8][1]=train_data[9][1]=(train_data[7][1]+train_data[8][1]+train_data[9][1])/3  
  
train_data[2][0]=train_data[5][0]=train_data[8][0]=train_data[0][0]=(train_data[1][0]+train_data[3][0])/2  
train_data[4][1]=train_data[5][1]=train_data[6][1]=(train_data[1][1]+train_data[7][1])/2  

复制代码

再次进行预测,结果为

[5, 2, 0, 1, 3, 1, 4, 9, 9, 9]

蛤蛤蛤,很厉害有没有?!

屁啦,没有普适性,对预测能力并没有质的提高,这个trick可以用,但是对数据进行移动平均的次数真的对预测结果有很大影响。

好啦,至此,我们第一个语音号码识别程序的demo已经出来了,虽然正确率只有60%左右,但这是个十分类问题啊喂,比你乱猜还是靠谱多了好吗!!!当然,提高的空间还很大,大家如果有兴趣的可以一起讨论讨论,比如我觉得可以对从频谱中得到的数据依照训练数据做个拉普拉斯平滑~

这周花了很多时间在这个小玩意儿上,课题的东西一点也没干,感觉周一组会老板回来要GoDie了,好慌啊,先歇个周六压压惊,周末愉快各位,蛤蛤蛤~~~
--------------------- 

 

使用k-NN分类器算法检测音乐音频剪辑中的各种情绪:Python实现与详细分析 k-NN,即k最近邻(k-Nearest Neighbors)算法,是一种基于实例的学习,或者说是懒惰学习的监督学习技术。该算法的工作原理是找到一个给定的输入值的k个最近的训练样本,并返回这些样本中最常见的输出值作为预测。 阅读详情

相关推荐

Mozart:光学音乐识别(OMR)系统。 将乐谱转换为机器可读的版本

:musical_notes: 将乐谱转换为机器可读的版本。 :memo: 目录 :face_with_monocle: 关于 该项目的目的是开发一种乐谱阅读器。 这称为光学音乐识别(OMR)。 其目的是将活页乐谱转换为机器可读的版本。 我们采用简化版本,将活页乐谱的图像转换为文本表示形式,可以对其进行进一步处理以生成Midi文件或音频文件,例如wav或mp3。 :laptop: 方法 1.噪声过滤和二值化 2.细分 3.人员线的检测和撤除 4.构建新的员工线 5.符号检测与识别 :chequered_flag: 安装 您可以使用随附的笔记本进行快速测试和可视化。 您可以在本地计算机上设置环境以运行项目: 安装 conda env create -f requirements.yml conda activate mozart python3 main.py <input directory path> <output> :pick: 内置使用

使用python实现语音识别

语音识别技术,也被称为自动语音识别,目标是以电脑自动将以人类的语音内容转换为相应的文字和文字转换为语音。

白帽阿叁的博客 7587

Axure RP 9在Windows 11环境下的高效安装与配置指南

本文提供Axure RP 9在Windows 11系统下的详细安装步骤与配置指南。针对Win11安全特性,从获取官方安装资源、调整系统权限,到定制化安装路径、精准汉化及性能优化,系统性地解决了安装闪退、汉化失败、运行卡顿等常见问题,确保用户获得稳定流畅的原型设计体验。

mango的博客 480

双音多频技术介绍及应用——识别电话号码

双音多频技术 作者:郑不挫。 原理 电话拨号有两种,脉冲和音频,所谓音频也称双音多频(DTMF)信号的拨号方式,双音多频既是电话拨号时每按一个键,有两个音频频率叠加成一个双音频信号,十二个按键由八个音频频率区分。如下图 应用 知道了双音多频技术的原理,下面讲讲如何通过双音多频技术来识别号码。采用的音频的采样频率为1000Hz,随意录制一段拨号音频,其时域波形如下: 为了进行号码识别,需要将音频信号进行切割,这里可以通过幅值来进行切割,比较简单就不说了。切割完成后,就得到了每个拨号的音频,然后对每个拨号进

weixin_43535207的博客 5242

Perplexity AI 高效使用培训手册

Perplexity AI 是一款革命性的 AI 搜索引擎,提供免费版和专业版两种选择。免费版支持基础搜索、每日3次Pro搜索、3个文件上传和初步深度研究功能;Pro版则解锁无限次Pro搜索、无限制文件上传、AI图像生成等高级功能,适合专业用户深度研究。该工具能整合网络信息、分析本地文档、生成创意内容,并提供知识库管理功能,显著提升信息检索和内容创作效率。用户可根据需求选择合适版本,免费版已能满足日常使用,而Pro版则更适合专业场景。

conquer_qgw的博客 1207

代码审计工具学习之Seay(安装以及初步认识)

目录 1.1名词解释 1.2代码审计的重要性 1.3代码审计的步骤 1.4代码审计的内容 1.5常见的代码审计工具 2 Seay 2.1什么是Seay 2.2Seay的安装过程 3典型漏洞分析 3.1什么是命令注入漏洞 3.2 如何理解命令注入漏洞 3.3 如何防御命令注入漏洞 4 利用工具对命令注入漏洞进行分析 4.1DVWA靶场命令注入漏洞分析 4.2 Pikachu靶场命令注入漏洞分析 1.1名词解释 软件代码审计是对编程项目中源代码的全面...

weixin_52515588的博客 2万+

短时傅里叶变换的原理与应用:电话拨号声分析(3)

上一篇关于电话号码分析的文章,提供了一种实现思路,还放了一些PPT上来。Review:电话拨号声分析之大体思路剩下的就是实际动手实现了。我把动手实践的内容拆成3个部分来写。特征提取占2/3,模式匹配占1/3。今天先写第1个部分。也就是特征提取里的第一步。大致思路是这样的。1. 读入音频x,长这样。2. 对x整体做傅里叶变换肯定是不行了。只能看见x中所有的频率成分的含量,不能看见什么时候出现的。就会...

qcyfred的博客 3388

英飞凌TC3xx DSADC旋变软解码实战:从示波器波形到VX1000数据,手把手教你避坑

本文详细介绍了英飞凌TC3xx系列微控制器的DSADC模块在电机旋变软解码中的实战应用。从示波器波形分析到VX1000数据采集,提供了一套完整的调试方法论,帮助工程师快速定位和解决常见问题,提升解码精度和系统性能。

weixin_30598225的博客 517

拨号声音识别 非实时

拨号声音识别

xzy3150787的博客 446

STM32+ESP8266+MQTT协议连接阿里云物联网平台

一、环境介绍 单片机采用:STM32F103C8T6 上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。 开发软件:keil5 二、实现功能 通过阿里云物联网服务器实现设备数据远程上传、下发,实现数据交互。 在当前使用的开发板上有4盏LED灯、一个蜂鸣器、4个按键。 三、阿里云物联网服务器创建步骤 说明:如果没有账号的话,先点击网页右上角,注册一个账号,并完成实名认证再继续下一步。 产品名称根据自己情况填...

6万+

【雕爷学编程】Arduino动手做(111)---震动提醒模块

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来---小小的进步或是搞不掂的问题,希望能够抛砖引玉。

雕爷学编程 1898

【Matlab】Matlab电话拨号音合成与识别(代码+论文)【独一无二】

理解DTMF(双音多频)信号:电话拨号音使用的是一种称为双音多频(DTMF)的信号。每个按键按下时会生成两个特定的频率。了解这些频率对应的按键是生成拨号音的基础。 生成DTMF信号:使用MATLAB的信号处理工具箱,为每个数字(0-9)和特殊字符(#,*)生成对应的DTMF信号。这通常涉及到生成两个正弦波的叠加,每个波的频率对应于DTMF标准中指定的频率,然后将它们合成一个信号。 保存或播放信号:生成的信号可以保存为音频文件或直接在MATLAB中播放,以验证其正确性。

测试开发自动化 1万+

《派出你的AI同事:WorkBuddy案例实战》062:投研资讯摘要与预警

投研资讯摘要与预警:新闻、公告、行情交给 AI 同事提炼与预警,投研从“刷资讯”变成“读摘要”。

LuckyHanMo的博客 182

【语音分析】基于matlab GUI语音信号线性预测(LPC)分析【含Matlab源码 910期】

语音信号线性预测(LPC)分析 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 1562

复合材料成型仿真案例大全|覆盖模压 / RTM / 固化 / SMC,实操步骤直接抄

本文整理了一套完整的PAM-COMPOSITE复合材料成型仿真案例合集,涵盖模压、RTM、固化变形、SMC四大核心工艺,包含6个实操案例和1个全流程衔接案例。每个案例都配有详细的操作步骤、核心要点和缺陷排查方法,适用于不同水平的工程师和研究人员。案例内容源自实际项目,可直接复用,帮助用户快速掌握复合材料成型仿真的关键技术,解决褶皱、纤维堆积、气泡残留等常见问题,实现从铺层设计到强度校核的全流程仿真闭环。特别针对热固性/热塑性材料差异、RTM衍生工艺、链式仿真等难点提供了专项解决方案。

源代码杀手的博客 320

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Kaggle实战——Gender Recognition by Voice声音的性别区分(结构化数据)(一)

这是以前的一次小组期末作业(当然编程部分都是我独立完成),写在这里也当做记录一下,顺便复习一下python和常用的机器学习算法吧。在进行数据分析时候第一件事情就是......数据集的查找........无论对于新手还是老手来说,Kaggle都是一个很好的数据平台,新手直接上手以前的玩具数据,至于老手可以直接对新数据进行比赛.......可以的话还可以混点奖金什么的(虽然哥从没得过奖)。这次的数据属...

peinbill的博客 6739

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

使用机器学习和深度学习对城市声音进行分类(Matlab代码实现)

部分代码:Fs = 44100;endendendendwhile trueendreturnendendend🎉3参考文献文章中一些内容引自网络,会注明出处或引用为参考文献,难免有未尽之处,如有不妥,请随时联系删除。[1]杨子明.基于图像和声音信号的城市轨道交通轨道线路病害识别技术研究[J].[2024-05-15].

weixin_67304359的博客 989

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

机器学习实战:Python基于K近邻KNN进行分类预测(四)

K近邻()是一种基本的分类与回归算法。其基本思想是将新的数据样本与已知类别的数据样本进行比较,根据K个最相似的已知样本的类别进行预测。具体来说,KNN算法通过计算待分类样本与已知样本之间的距离(欧式距离曼哈顿距离等),选取距离待分类样本最近的K个已知样本,再通过对这K个已知样本的类别进行投票、取平均等方式确定待分类样本的类别。KNN算法中,K的取值是一个重要的超参数,不同的取值可能会影响算法的性能。简单易懂:KNN算法的原理简单,易于理解和实现。

Senoh的博客 4837

python实现音乐分类_python音乐分类--knn

1 #利用knn算法分类音乐,将音乐进行情绪分类2 #将音乐分为兴奋的(excited), 愤怒的(angry),悲伤的(sorrowful),轻松的(relaxed)34 #可分离因素5 # mfcc67 import numpy asnp8 from matplotlib import pyplot asplt9 from scipy import io asspio10 fromsklear...

weixin_39651325的博客 1004

从拨号音分析拨号号码

http://blog.sina.com.cn/s/blog_3cef24f001018m8v.html 去年南京大学学生刘靖康利用网络上的视频分析出周鸿祎的手机号,本人实感钦佩。思路开阔,值得我学习。大学时我做过音乐编辑,经常用Adobe Audition,可是却没想到。当然《柯南》我也没看过。 读完刘同学写的教程后,很快就明白了。总结下来就是看声音的频谱,对号入座DTM

blade2001的专栏 5242

python语言铃声制作专家软件代码QZQ

qq_32257509的博客 396

python 实现PCM筛选电话忙音“嘟--”

如果有些的不对的地方, 还请大家补充: 需求:通过pcm音频来筛选是不是电话未接通音“嘟--”。 PCM概念: Pulse-code modulation(PCM) 是用 数字代表采样后的模拟信号的一种方法,它是计算机中数字音频的标准形式。 PCM 流有两个基本属性 去决定 是不是对原始模拟信号有保真度,采样率(每秒采样多少次),位深(决定用来代表采样的量化等级,在一定程度...

Nazimai_Ban 928

python绘制语谱图(详细注释)

用python 绘制语谱图 1.步骤: 1)导入相关模块 2)读入音频并获取音频参数  3)将音频转化为可处理形式(注意读入的是字符串格式,需要转换成int或short型) 代码如下: import numpy as np import matplotlib.pyplot as plt import os import wave #读入音频。 path = "E:\SpeechWare...

fzyjsy的博客 2万+
上一篇: 语音信号处理1
下一篇: Django 2.0实战:博客系统1
CopperDong
博客等级 码龄14年 1205粉丝 466原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值