信噪比(SNR)

有用信号功率与噪声功率的比(此处功率为平均功率),也等于幅度比的平方

$$SNR(dB)=10\log_{10}\frac{\sum_{n=0}^{N-1}s^2(n)}{\sum_{n=0}^{N-1}d^2(n)}=10*\log_{10}(\frac{P_{signal}}{P_{noise}})=20*log_{10}(\frac{A_{signal}}{A_{noise}})$$

$$SNR(dB)=10\log_{10}\frac{\sum_{n=0}^{N-1}s^2(n)}{\sum_{n=0}^{N-1}[x(n)-s(n)^2]}$$

其中:

$P_{signal}$为信号功率;$P_{noise}$为噪声功率;$A_{signal}$为信号幅度;$A_{noise}$为噪声幅度值,功率等于幅度值的平方

MATLAB版本代码

# 信号与噪声长度应该一样
function snr=SNR_singlech(Signal,Noise) P_signal = sum(Signal-mean(Signal)).^2; # 信号的能量
P_noise = sum(Noise-mean(Noise)).^2; # 噪声的能量
snr = 10 * log10(P_signal/P_noise)

python代码

def numpy_SNR(origianl_waveform, target_waveform):
# 单位 dB
signal = np.sum(origianl_waveform ** 2)
noise = np.sum((origianl_waveform - target_waveform) ** 2)
snr = 10 * np.log10(signal / noise)
return snr

$$np.linalg.norm(x)=\sqrt{x_1^2+x_2^2+...+x_n^2}$$

这个公式和上面是一样的

def wav_snr(ref_wav, in_wav):# 如果ref wav稍长,则用0填充in_wav
if (abs(in_wav.shape[0] - ref_wav.shape[0]) < 10):
pad_width = ref_wav.shape[0] - in_wav.shape[0]
in_wav = np.pad(in_wav, (0, pad_width), 'constant')
else:
print("错误:参考wav与输入wav的长度明显不同")
return -1 # 计算 SNR
norm_diff = np.square(np.linalg.norm(in_wav - ref_wav))
if (norm_diff == 0):
print("错误:参考wav与输入wav相同")
return -1 ref_norm = np.square(np.linalg.norm(ref_wav))
snr = 10 * np.log10(ref_norm / norm_diff)
return snr

峰值信噪比(PSNR)

表示信号的最大瞬时功率和噪声功率的比值,最大瞬时功率为语音数据中最大值得平方。

$$SNR(dB)=10*\log _{10}(\frac{MAX(P_{signal})}{P_{noise}})=10\log_{10}\frac{MAX[s(n)]^2}{d^2(n)}$$

$$SNR(dB)=10\log_{10}\frac{MAX[s(n)]^2}{\frac{1}{N}\sum_{n=0}^{N-1}[x(n)-s(n)]^2}=20\log_{10}\frac{MAX[s(n)]}{\sqrt{MSE}}$$

import numpy as np 

def psnr(ref_wav, in_wav):
MSE = numpy.mean((ref_wav - in_wav) ** 2)
MAX = np.max(ref_wav) # 信号的最大平时功率
return 20 * np.log10(MAX / np.sqrt(MSE))

分段信噪比(SegSNR)

  由于语音信号是一种缓慢变化的短时平稳信号,因而在不同时间段上的信噪比也应不一样。为了改善上面的问题,可以采用分段信噪比。分段信噪比即是先对语音进行分帧,然后对每一帧语音求信噪比,最好求均值。

MATLAB版本的代码

function [segSNR] = Evaluation(clean_speech,enhanced)

N = 25*16000/1000; %length of the segment in terms of samples
M = fix(size(clean_speech,1)/N); %number of segments
segSNR = zeros(size(enhanced));
for i = 1:size(enhanced,1)
for m = 0:M-1
sum1 =0;
sum2 =0;
for n = m*N +1 : m*N+N
sum1 = sum1 +clean_speech(n)^2;
sum2 = sum2 +(enhanced{i}(n) - clean_speech(n))^2;
end
r = 10*log10(sum1/sum2);
if r>55
r = 55;
elseif r < -10
r = -10;
end segSNR(i) = segSNR(i) +r;
end
segSNR(i) = segSNR(i)/M;
end

python代码

def SegSNR(ref_wav, in_wav, windowsize, shift):
if len(ref_wav) == len(in_wav):
pass
else:
print('音频的长度不相等!')
minlenth = min(len(ref_wav), len(in_wav))
ref_wav = ref_wav[: minlenth]
in_wav = in_wav[: minlenth]
# 每帧语音中有重叠部分,除了重叠部分都是帧移,overlap=windowsize-shift
# num_frame = (len(ref_wav)-overlap) // shift
# num_frame = (len(ref_wav)-windowsize+shift) // shift
num_frame = (len(ref_wav) - windowsize) // shift + 1 # 计算帧的数量 SegSNR = np.zeros(num_frame)
# 计算每一帧的信噪比
for i in range(0, num_frame): noise_frame_energy = np.sum(ref_wav[i * shift, i * shift+windowsize] ** 2) # 每一帧噪声的功率
speech_frame_energy = np.sum(in_wav[i * shift, i * shift+windowsize] ** 2) # 每一帧信号的功率
SegSNR[i] = np.log10(speech_frame_energy / noise_frame_energy) return 10 * np.mean(SegSNR)

对数拟然对比度(log Likelihood Ratio Measure)

  坂仓距离测度是通过语音信号的线性预测分析来实现的。ISD基于两组线性预测参数(分别从原纯净语音和处理过的语音的同步帧得到)之间的差异。LLR可以看成一种坂仓距离(Itakura Distance,IS)但是IS距离需要考虑模型增益。而LLR不需要考虑模型争议引起的幅度位移,更重视整体谱包络的相似度。

PESQ

  PESQ是用于语音质量评估的一种方法,ITU提供了C语言代码,下载请点击这里,但是在使用之前我们需要先编译C脚本,生成可执行文件exe

编译方式为:在命令行进入下载好的文件

  1. cd \Software\source
  2. gcc -o PESQ *.c

  经过编译,会在当前文件夹生成一个pesq.exe的可执行文件

使用方式为:

  1. 命令行进入pesq.exe所在的文件夹
  2. 执行命令:pesq 采样率 "原始文件路径名" "劣化文件路径名”
  3. 回车
  4. 等待结果即可,值越大,质量越好。
    • 例如:pesq +16000 raw.wav processed.wav

对数谱距离(Log Spectral Distance)

对数谱距离Log Spectral Distance是两个频谱之间的距离度量(用分贝表示)。两个频谱$P(W)$和$\hat{P}(w)$之间的对数谱距离被定义为:

$$D_{LS}=\sqrt{\frac{1}{2\pi}\int_{-\pi}^{\pi}[10*\log _{10}\frac{P(w)}{\hat{P}(w)}]^2dw}$$

其中,$p(w)$和$\hat{P}(w)$是功率谱。对数谱距离是时多对称的。

def numpy_LSD(origianl_waveform, target_waveform):
""" 比较原始和目标音频之间的对数谱距离(LSD),也称为对数谱失真,
是两个频谱之间的距离测量值(以dB表示) """ print("数据形状为", origianl_waveform.shape)
print("数据类型为", type(origianl_waveform)) original_spectrogram = librosa.core.stft(origianl_waveform, n_fft=2048)
target_spectrogram = librosa.core.stft(target_waveform, n_fft=2048) original_log = np.log10(np.abs(original_spectrogram) ** 2)
target_log = np.log10(np.abs(target_spectrogram) ** 2)
original_target_squared = (original_log - target_log) ** 2
target_lsd = np.mean(np.sqrt(np.mean(original_target_squared, axis=0))) return target_lsd

参考文献:

非典型废言的CSDN博客

视频质量度量指标

python实现语音信号处理常用度量方法的更多相关文章

  1. Python - 基本数据类型及其常用的方法之字典和布尔值

    字典 特点:{"key1": value1, "key2":value2}  , 键值对中的值可以为任何数据类型,键不能为列表.字典(无法哈希),布尔值可以为键 ...

  2. Python - 基本数据类型及其常用的方法之元组

    元组 特点:一级元素无法被修改,且不能被增加或者删除. 基本操作: tu = (11, 22, ["aiden", 33, ("qwe", 11)], 77) ...

  3. python做语音信号处理

    音频信号的读写.播放及录音 标准的python已经支持WAV格式的书写,而实时的声音输入输出需要安装pyAudio(http://people.csail.mit.edu/hubert/pyaudio ...

  4. 用Python进行语音信号处理

    1.语音信号处理之时域分析-音高追踪及其Python实现 2.语音信号处理之时域分析-音高及其Python实现 参考: 1.NumPy

  5. Python学习入门基础教程(learning Python)--8.3 字典常用的方法函数介绍

    本节的主要讨论内容是有关dict字典的一些常用的方法函数的使用和范例展示. 1. clear清除字典数据 语法结构如下: dict_obj.clear() 示例代码如下: dict1 = {'web' ...

  6. Python图像处理库Pillow常用使用方法

    PIL(Python Imaging Library)是Python一个强大方便的图像处理库,只支持到Python2.7.Pillow是PIL的一个派生分支,在Python3中用Pillow代替PIL ...

  7. Python - 基本数据类型及其常用的方法之数字与字符串

    数字(int): 1.int()(将字符串换为数字) a = " print(type(a), a) b = int(a) print(type(b), b) num = "a&q ...

  8. Python - 基本数据类型及其常用的方法之列表

    列表: 特点:用 [] 括起来,切元素用逗号分隔:列表内的元素可以为任何的数据类型. 列表的基本操作: 1.修改 li = [12, 5, 6, ["Aiden", [2, 4], ...

  9. python中math模块常用的方法整理

    ceil:取大于等于x的最小的整数值,如果x是一个整数,则返回x copysign:把y的正负号加到x前面,可以使用0 cos:求x的余弦,x必须是弧度 degrees:把x从弧度转换成角度 e:表示 ...

随机推荐

  1. [开源] FreeSql 配套工具,基于 Razor 模板实现最高兼容的生成器

    FreeSql 经过半年的开发和坚持维护,在 0.6.x 版本中完成了几大重要事件: 1.按小包拆分,每个数据库实现为单独 dll: 2.实现 .net framework 4.5 支持: 3.同时支 ...

  2. VS 2017 + OpenCV + Spinnaker SDK(PointGrey) 配置

    1. OpenCV 配置 1.1 下载 opencv 源码,并将其添加至环境变量 D:\opencv4.1\build\x64\vc15\bin 注:vs2015 选 vc14,vs2017 选 vc ...

  3. IT兄弟连 Java语法教程 关系运算符

    关系运算符用来判定一个操作数与另外一个操作数之间的关系.特别是,它们可以判定相等和排序关系.表7中列出了关系运算符. 表7  关系运算符 关系运算符的结果为布尔值.关系运算符最常用与if语句和各种循环 ...

  4. 实现简易JDBC框架

    1 准备 JDBC 基本知识 JDBC元数据知识 反射基本知识 2:  两个问题 业务背景:系统中所有实体对象都涉及到基本的CRUD操作.所有实体的CUD操作代码基本相同,仅仅是发送给数据库的sql语 ...

  5. njnja 安装

    git clone git://github.com/ninja-build/ninja.git && cd ninja 安装re2c wget  https://kojipkgs.f ...

  6. WPF 使用EventTrigger时设置SouceName技巧

    使用情节触发器时,如果有触发源/触发源控件时可以将情节触发器放置最顶级的面板控件的触发器中. 通过blend这个神器真的是可以学到不少东西. 代码: //情节动画放置于顶级控制面板 <Widno ...

  7. TCP协议 - 面向连接

    一.TCP特性概览 1.面向连接 TCP是基于连接进行数据交互,通信双方在进行数据交互之前需要建立连接,该连接也只能用在双方之间进行交互.这点不像UDP中的组播和广播,可以在同一组中多个主机交互数据. ...

  8. rsync免交互方法

    添加-e "ssh -o StrictHostKeyChecking=no" rsync -avzP -e "ssh -o StrictHostKeyChecking=n ...

  9. C# convert between Image and Base64string

    static void ImageMSDemo(string picPath) { byte[] imageArray = System.IO.File.ReadAllBytes(picPath); ...

  10. pycharm 取消连按两下shift出现的全局搜索

    在来回切换中英文输入法的时候连按两下shift总是会蹦出来全局搜索框 真的很是麻烦,现在是把这个框给禁用掉 1.按ctrl+shift+a,弹出搜索框2.输入registry,然后按回车3.找到“id ...