python实现对语音的离散余弦变换与离散余弦逆变换
离散余弦变换
离散余弦变换(DCT)信号谱分量丰富、能量集中,且不需要对语音相位进行估算等优点,在较低的运算复杂度下取得较好的语音增强效果。 假设一余弦序列
x
(
n
)
=
cos
?
(
2
π
f
n
f
s
)
,
0
<
=
n
<
1000
x(n)=\cos(\frac{2\pi fn}{{f}_{s}}), 0<=n<1000
x(n)=cos(fs?2πfn?),0<=n<1000 其中f=50Hz,
f
s
{f}_{s}
fs?=1000Hz。 则信号的离散余弦变换:
X
(
k
)
=
2
N
∑
n
=
0
N
?
1
C
(
k
)
x
(
n
)
cos
?
(
(
2
n
+
1
)
k
π
2
N
)
,
N
=
0
,
1
,
.
.
.
N
?
1
X(k) = \sqrt{\frac{2}{N}}\sum_{n=0}^{N-1}C(k)x(n)\cos(\frac{(2n+1)k\pi}{2N}),N=0,1,...N-1
X(k)=N2?
?n=0∑N?1?C(k)x(n)cos(2N(2n+1)kπ?),N=0,1,...N?1
C
(
k
)
C(k)
C(k)是正交因子
C
(
x
)
=
{
2
2
k=0
1
k=[1,2,...N-1]
C(x)= \begin{cases} \frac{\sqrt{2}}{2}& \text{k=0}\\ 1& \text{k=[1,2,...N-1]} \end{cases}
C(x)={22
??1?k=0k=[1,2,...N-1]?
代码:
import numpy as np
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['STSong']
f = 50
N = 1000
fs = 1000
n = np.array([i for i in range(N)])
xn = np.cos(2 * np.pi * f * n / fs)
def dct(x):
N = len(x)
X = np.zeros(N)
ts = np.array([i for i in range(N)])
C = np.ones(N)
C[0] = np.sqrt(2) / 2
for k in range(N):
X[k] = np.sqrt(2 / N) * np.sum(C[k] * np.multiply(x, np.cos((2 * ts + 1) * k * np.pi / 2 / N)))
return X
s_dct = dct(xn)
plt.figure(figsize=(8, 4))
plt.subplot(211)
plt.plot(xn)
plt.xlabel('样点')
plt.title('原信号', fontsize=12, color='black')
plt.subplot(212)
plt.plot(s_dct)
plt.xlabel('样点')
plt.title('离散余弦变换', fontsize=12, color='black')
plt.subplots_adjust(hspace=0.6)
plt.show()
结果:
离散余弦逆变换
则DCT的逆变换为
x
(
n
)
=
2
N
∑
n
=
0
N
?
1
C
(
k
)
X
(
k
)
cos
?
(
(
2
n
+
1
)
k
π
2
N
)
,
N
=
0
,
1
,
.
.
.
N
?
1
x(n) = \sqrt{\frac{2}{N}}\sum_{n=0}^{N-1}C(k)X(k)\cos(\frac{(2n+1)k\pi}{2N}),N=0,1,...N-1
x(n)=N2?
?n=0∑N?1?C(k)X(k)cos(2N(2n+1)kπ?),N=0,1,...N?1 代码:
def idct(X):
N = len(X)
x = np.zeros(N)
ts = np.array([i for i in range(N)])
C = np.ones(N)
C[0] = np.sqrt(2) / 2
for n in range(N):
x[n] = np.sqrt(2 / N) * np.sum(np.multiply(np.multiply(C[ts], X[ts]), np.cos((2 * n + 1) * np.pi * ts / 2 / N)))
return x
s_idct = idct(ss_dct)
plt.figure(figsize=(8, 4))
plt.plot(s_idct)
plt.xlabel('样点')
plt.title('离散余弦逆变换恢复', fontsize=12, color='black')
plt.show()
结果:
调包实现
代码:
ds_dct = cv2.dct(xn)
ds_idct = cv2.dct(ds_dct)
plt.figure(figsize=(8, 6))
plt.subplot(311)
plt.plot(xn)
plt.xlabel('样点')
plt.title('原信号', fontsize=12, color='black')
plt.subplot(312)
plt.plot(ds_dct)
plt.xlabel('样点')
plt.title('离散余弦变换', fontsize=12, color='black')
plt.subplot(313)
plt.plot(ds_idct)
plt.xlabel('样点')
plt.title('离散余弦逆变换恢复', fontsize=12, color='black')
plt.subplots_adjust(hspace=0.6)
plt.show()
结果:
|