用符號運算驗證DCT的矩陣是正交矩陣
輸入: [1.000 2.000 3.000]
輸出: [ 3.464 -1.414 0.000]
重建: [1.000 2.000 3.000]
[0] 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
[1] 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
[2] 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為啥是正交矩陣?!
[0,0] 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)
[0,1] 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)
[0,2] 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)
[1,0] 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)
[1,1] 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)
[1,2] 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)
[2,0] 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)
[2,1] 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)
[2,2] 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)) # [[0]*3]*3不對。[0]*3得[0,0,0],再*3復制引用?而非創建獨立副本。修改任意一行會影響所有行;debug 1小時 mc = [[0] * N for _ in range(N)] ms = [[0] * N for _ in range(N)] for k in range(N): for n in range(N): mc[k][n] = m[k,n] = cos((n + 0.5) * k * pi / N) ms[k][n] = f'cos({(n+0.5)*k}*π/{N})' m[0,:] *= sqrt(1/N) for n in range(N): mc[0][n] *= sqrt(1/N) ms[0][n] += f'*sqrt(1/N)' m[1:,:] *= sqrt(2/N) for k in range(1,N): for n in range(N): mc[k][n] *= sqrt(2/N) ms[k][n] += f'*sqrt(2/N)' mt = m.T if ne(m, mc): raise ValueError() # x是一維數組,shape=(3,),np將其視為?列向量?(3,1) # 3x3 x 3x1 = 3x1. 720p是1280x720 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([1.0, 2.0, 3.0]); print("輸入:", x) y = dct(x); print("輸出:", y) r = idct(y); print("重建:", r) ee = np.eye(m.shape[0]) if ne(np.matmul(m, mt), ee): raise ValueError() print() y2 = [0] * N for i in range(N): for j in range(N): y2[i] += mc[i][j] * x[j] if ne(y, y2): raise ValueError() y2 = [0] * N for i in range(N): s = '' for j in range(N): s += f'{ms[i][j]}*{x[j]} + ' s = s[:-3] y2[i] = eval(s) print(f'{[i]} {s} = {y2[i]:.3f}') if ne(y, y2): raise ValueError() print('') print('恭喜,你(基本)明白DCT了!可M為啥是正交矩陣?!') a = ms; b = np.array(ms).T; e = [[0] * N for _ in range(N)] for i in range(N): for j in range(N): s = '' for k in range(N): s += f'{a[i][k]}*{b[k][j]} + ' s = s[:-3] print(f'[{i},{j}] {s}') e[i][j] = eval(s) if ne(e, ee): raise ValueError() print() print('如果用上復數(歐拉公式),就可以用等比數列求和公式了!!')
cos2(θ/3) + cos2(θ) + cos2(5θ/3) = ? sympy不能化簡。DeekSeek可以。

'''
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 pi as π, cos
import numpy as np
α = π / 3
N = 3
print(f'{(2/N)*(cos(α)**2 + cos(3*α)**2 + cos(5*α)**2):.3f}')
δ_plural = 0; βs = np.linspace(0, 2*π, 100);
for β in βs:
a = np.cos(β) + np.cos(3*β) + np.cos(5*β)
b = np.cos(3*β) * (2*np.cos(2*β) + 1)
δ = abs(a-b); δ_plural += δ
if δ > 1E-6: raise ValueError()
print(f'{δ_plural / βs.size:.3f}')
# cos2γ = (1 + cos2γ) / 2 = 1/2 + cos2γ/2
β = 2 * α
print(f'{(cos(3*β) * (2*cos(2*β) + 1) + 3/2) * 2/N:.3f}')
噫,算出1可不易。


實部永遠是實部,虛部永遠是虛部,實對實來虛對虛。

我還是不認為AI有啥智能。它提到了等比數列求和,對我是個小小的打擊(我還以為是我首創),無非是知道的人不少,而且發到網上了,AI看到了,我沒看到而已。至于上學時么,可能老師沒講,更可能我沒去上課或沒仔細聽,但我可以肯定我看到的課本上沒講。
AI還說:
① 設計正交矩陣時可利用三角函數的性質。矩陣的列向量(或行向量)必須兩兩正交且長度(模)為1。
② 最簡單的正交矩陣是二維或三維的旋轉矩陣(嗎?)竊以為是單位矩陣。
③ 哈達瑪矩陣(Hadamard Matrix)是由1和-1構成的正交矩陣。
在H.264/AVC等編碼標準中,4×4和8×8 Hadamard變換被用于SATD計算流程:
1. 對殘差信號矩陣執行二維變換,生成頻域系數
2. 計算系數絕對值之和作為SATD值
3. 通過歸一化處理消除階數差異影響
作為DCT的替代方案,Hadamard變換在JPEG標準中實現能量集中效率達87%,較DCT低約9%,但運算速度提升顯著。
微軟BitNet v2框架用Hadamard變換優化LLM激活值量化流程。

浙公網安備 33010602011771號