论DCT和IDCT的重要性,汇编SIMD版第一,此贴第二,就是这么狂 :-)
输入:输出: [ 3.464 -1.4140.000]
重建:
cos(0.0*π/3)*sqrt(1/N)*1.0 + cos(0.0*π/3)*sqrt(1/N)*2.0 + cos(0.0*π/3)*sqrt(1/N)*3.0 = 3.464
cos(0.5*π/3)*sqrt(2/N)*1.0 + cos(1.5*π/3)*sqrt(2/N)*2.0 + cos(2.5*π/3)*sqrt(2/N)*3.0 = -1.414
cos(1.0*π/3)*sqrt(2/N)*1.0 + cos(3.0*π/3)*sqrt(2/N)*2.0 + cos(5.0*π/3)*sqrt(2/N)*3.0 = 0.000
恭喜,你(基本)明白DCT了!可M为啥是正交矩阵?!
cos(0.0*π/3)*sqrt(1/N)*cos(0.0*π/3)*sqrt(1/N) + cos(0.0*π/3)*sqrt(1/N)*cos(0.0*π/3)*sqrt(1/N) + cos(0.0*π/3)*sqrt(1/N)*cos(0.0*π/3)*sqrt(1/N)
cos(0.0*π/3)*sqrt(1/N)*cos(0.5*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(1.5*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(2.5*π/3)*sqrt(2/N)
cos(0.0*π/3)*sqrt(1/N)*cos(1.0*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(3.0*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(5.0*π/3)*sqrt(2/N)
cos(0.5*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(1.5*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(2.5*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N)
cos(0.5*π/3)*sqrt(2/N)*cos(0.5*π/3)*sqrt(2/N) + cos(1.5*π/3)*sqrt(2/N)*cos(1.5*π/3)*sqrt(2/N) + cos(2.5*π/3)*sqrt(2/N)*cos(2.5*π/3)*sqrt(2/N)
cos(0.5*π/3)*sqrt(2/N)*cos(1.0*π/3)*sqrt(2/N) + cos(1.5*π/3)*sqrt(2/N)*cos(3.0*π/3)*sqrt(2/N) + cos(2.5*π/3)*sqrt(2/N)*cos(5.0*π/3)*sqrt(2/N)
cos(1.0*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(3.0*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(5.0*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N)
cos(1.0*π/3)*sqrt(2/N)*cos(0.5*π/3)*sqrt(2/N) + cos(3.0*π/3)*sqrt(2/N)*cos(1.5*π/3)*sqrt(2/N) + cos(5.0*π/3)*sqrt(2/N)*cos(2.5*π/3)*sqrt(2/N)
cos(1.0*π/3)*sqrt(2/N)*cos(1.0*π/3)*sqrt(2/N) + cos(3.0*π/3)*sqrt(2/N)*cos(3.0*π/3)*sqrt(2/N) + cos(5.0*π/3)*sqrt(2/N)*cos(5.0*π/3)*sqrt(2/N)
如果用上复数(欧拉公式),就可以用等比数列求和公式了!!
from math import cos, sqrt, pi
import numpy as np
π = pi; N = 3
m = None # DCT矩阵
mt = None # IDCT矩阵,m的转置
mc = None # "C"版本DCT矩阵
ms = None # string版DCT矩阵
ne = lambda a, b: not np.allclose(a, b, atol=1E-6)
def generate_dct_matrices():
global m; global mt; global mc; global ms
m = np.zeros((N, N))
# [*3]*3不对。*3得,再*3复制引用而非创建独立副本。修改任意一行会影响所有行;debug 1小时
mc = [ * N for _ in range(N)]
ms = [ * N for _ in range(N)]
for k in range(N):
for n in range(N):
mc = m = cos((n + 0.5) * k * pi / N)
ms = f'cos({(n+0.5)*k}*π/{N})'
m *= sqrt(1/N)
for n in range(N):
mc *= sqrt(1/N)
ms += f'*sqrt(1/N)'
m *= sqrt(2/N)
for k in range(1,N):
for n in range(N):
mc *= sqrt(2/N)
ms += f'*sqrt(2/N)'
mt = m.T
if ne(m, mc): raise ValueError()
# x是一维数组,shape=(3,),np将其视为列向量(3,1)
# 3x3 x 3x1 = 3x1 再摆平
dct= lambda x: np.dot(m,x)
idct = lambda y: np.dot(mt, y)
# So, dct和idct其实是一个函数
np.set_printoptions(
suppress=True,# 禁用科学计数法
precision=3, # 保留3位小数
floatmode='fixed'# 固定小数位数
)
generate_dct_matrices()
x = np.array(); print("输入:", x)
y = dct(x); print("输出:", y)
r = idct(y); print("重建:", r)
ee = np.eye(m.shape)
if ne(np.matmul(m, mt), ee): raise ValueError()
print()
y2 = * N
for i in range(N):
for j in range(N): y2 += mc * x
if ne(y, y2): raise ValueError()
y2 = * N
for i in range(N):
s = ''
for j in range(N): s += f'{ms}*{x} + '
s = s[:-3]
y2 = eval(s)
print(f'{} {s} = {y2:.3f}')
if ne(y, y2): raise ValueError()
print('')
print('恭喜,你(基本)明白DCT了!可M为啥是正交矩阵?!')
a = ms; b = np.array(ms).T; e = [ * N for _ in range(N)]
for i in range(N):
for j in range(N):
s = ''
for k in range(N): s += f'{a}*{b} + '
s = s[:-3]
print(f'[{i},{j}] {s}')
e = eval(s)
if ne(e, ee): raise ValueError()
print()
print('如果用上复数(欧拉公式),就可以用等比数列求和公式了!!')
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! 谢谢分享,辛苦了 鼓励转贴优秀软件安全工具和文档! 懂技术并乐意极积无私分享的人越来越少。珍惜 喜欢鼓捣这些软件,现在用得少,谢谢分享! yyds。多谢分享 喜欢鼓捣这些软件,现在用得少,谢谢分享! 喜欢鼓捣这些软件,现在用得少,谢谢分享! 这个好,看起来很实用 谢谢分享,辛苦了 感谢分享,学习下。 用心讨论,共获提升! 感谢分享,下载保存了,貌似很强大 喜欢鼓捣这些软件,现在用得少,谢谢分享! 感谢分享,学习下。 谢谢分享,辛苦了 这个好,看起来很实用 过来提前占个楼 感谢分享 感谢分享
页:
[1]
2