Python 如何基于音频进行直方图均衡化?
我已经尝试过基于图像的直方图均衡化,效果很好。 但是现在我想用音频代替图像灰度实现同样的方法。这意味着我想使频谱更平坦。我使用的采样率是44.1kHz,希望使频率均匀分布在0-22050Hz的范围内,但峰值仍然是最高的 以下是频谱: 这就是我尝试过的: 我认为我绘制的原始直方图已经错了,我无法计算每个频率出现的次数,或者我根本不应该这样做。有人告诉我需要使用fft(),但我不知道如何使用 任何帮助都将不胜感激!谢谢 下面是我如何绘制光谱的代码:Python 如何基于音频进行直方图均衡化?,python,python-3.x,signal-processing,Python,Python 3.x,Signal Processing,我已经尝试过基于图像的直方图均衡化,效果很好。 但是现在我想用音频代替图像灰度实现同样的方法。这意味着我想使频谱更平坦。我使用的采样率是44.1kHz,希望使频率均匀分布在0-22050Hz的范围内,但峰值仍然是最高的 以下是频谱: 这就是我尝试过的: 我认为我绘制的原始直方图已经错了,我无法计算每个频率出现的次数,或者我根本不应该这样做。有人告诉我需要使用fft(),但我不知道如何使用 任何帮助都将不胜感激!谢谢 下面是我如何绘制光谱的代码: import librosa import
import librosa
import numpy as np
import matplotlib.pyplot as plt
import math
file = 'example.wav'
y, sr = librosa.load(file, sr=None)
n_fft = 2048
S = librosa.stft(y, n_fft=n_fft, hop_length=n_fft//2)
S = abs(S)
D_AVG = np.mean(S, axis=1)
plt.figure(figsize=(25, 12))
plt.bar(np.arange(D_AVG.shape[0]), D_AVG)
x_ticks_positions = [n for n in range(0, n_fft // 2, n_fft // 16)]
x_ticks_labels = [str(sr / 2048 * n) + 'Hz' for n in x_ticks_positions]
plt.xticks(x_ticks_positions, x_ticks_labels)
plt.xlabel('Frequency')
plt.ylabel('dB')
plt.savefig('spectrum.png')
“均衡”的意思是使一个平坦的频谱通常是由一个简单的电路来完成的。可能也会有帮助。正如Mark提到的,在图像处理中,这种谱均衡不同于直方图均衡
均衡/白化信号频谱:
fs
的样本阵列x
,您可以使用以下方法计算功率谱密度(PSD)的稳健估计:
此函数执行以下操作。基本上,它将信号分为几个部分,对每个部分进行FFT,并对功率谱进行平均,以很好地估计每个频率的平均功率x
。所有这一切的要点是,它得到了一个更可靠的频率特性,而不仅仅是将一个FFT的x
作为一个整体
eq_增益=1/(1e-6+psd)**0.5
或类似方法来确定均衡器的增益。1e-6
分母偏移是为了避免被零除。对于某些频率,PSD通常非常小,因为,例如,x
通过了抗混叠滤波器,使某些高频功率接近于零
eq\u增益
需要应用到信号x
以对其进行均衡。有很多方法可以做到这一点,但一种方法是将增益转换为FIR滤波器
eq_filter = scipy.signal.firwin2(99, f, eq_gain, fs=fs)
并使用卷积或将过滤器应用于x
。然后,您可以再次使用scipy.signal.welch
检查PSD是否比以前更平坦
您正在标记此Python,但没有提供代码。您也没有指定如何从音频到频谱图像和直方图图像。此外,通常当人们谈到均衡频谱时,他们谈论的是放大和抑制频率,而不是像图像均衡那样移动频率(改变灰度值)。请澄清(并举例说明)你想要达到的目标。@MarkJeronimus,我很抱歉,因为这是我的第一个问题。我已经添加了如何绘制光谱的代码,您可以忽略直方图图像。我只是想均衡一个频谱,就像你说的,但我不知道如何编写代码。在对
x
应用eq_滤波器之前,我应该使用scipy.signal.butter
?我尝试了scipy.signal.lfilter
和scipy.signal.filtfilt
将过滤器应用于x
,但它不起作用,PSD仍然与原始PSD相同。你能给我看看第三步的完整代码吗?那将非常有帮助,谢谢。在我的建议中,scipy.signal.firwin2
设计了均衡滤波器;无需使用scipy.signal.butter
。通过卷积eq_过滤器
和x
应用过滤器。一种方法是x\u equalized=scipy.signal.lfilter(eq\u filter,1,x)
。
eq_filter = scipy.signal.firwin2(99, f, eq_gain, fs=fs)