不過因為發現了一些奇怪的事情,原本的測試目的(找最佳的 MPEG-4 Codec)反而變得不重要,所以我最後還是硬著頭皮把它做完了。
這個奇怪的現象我想來想去找不出合理的解釋,所以我把測試結果貼上來,順便請大家一起來研究看看這個現象是什麼原因造成的。
測試的方法是取一段 sample clip,用各種 MPEG-4 Codec 壓縮,然後比較壓縮後的影像和原本影像的差距,計算每一張畫面的 PSNR(Peak-SNR)訊噪比,單位是 dB,訊噪比越高的和原來畫面的差距就越小,越接近原始畫面,代表壓縮的品質越好。
PSNR 的算式定義我就不詳述了,有興趣者可自行參考
http://bmrc.berkeley.edu/courseware/cs2 ... /psnr.html
PSNR 低於 25dB 的話,一般人都無法滿意這樣的畫質;高於 35dB,一般會認為畫質不錯;高於 40dB 以上,不定格注意看的話通常無法分辦和原圖有何不同。
因為剛好我正在壓一部動畫的 OP,所以想也沒想就拿這部 OP 來測試了,經過 24fps 補正,Lanczos3 Resize 縮小..等處理以後,就用 AviUtl 壓縮,然後要比較計算 PSNR 的時候... 我傻眼了,因為要和原本的影像比較,我必須拿 AviUtl 處理過之後的影像來比較,不能拿 DVD 上原始 720x480,YUV 4:2:0 的影像來比較,所以我最後只好轉成 VFAPI,比較 RGB 的 PSNR。
知道我在說什麼嗎?我的意思是,本來要測試的話,最好是直接原封不動的把原始 YUV 4:2:0 的影像送進 Codec 壓縮,然後比較壓縮後的 YUV 4:2:0 和壓縮前的 YUV 4:2:0 Data,這樣就不會經過 YUV 4:2:0(原始資料)--> RGB24(內插補點轉換為 RGB24 給 AviUtl 處理)--> YUV 4:2:0(Codec 壓縮)--> RGB24(解壓縮再展開,比較 PSNR),這麼多重的手續了。而且 YUV <--> RGB 轉換是有損失的,反覆的轉來轉去會喪失一些精確度。
不過檔案都已經壓好了,我實在沒力再重壓一遍 YUV 直入的版本,而且
1. 大家的原始影像都是 AviUtl 處理過之後的影像,和 AviUtl 的影像比較,大家的基準點還是都一樣
2. 影像最後要顯示,還是要轉為 RGB 才能顯示,所以 YUV 解壓縮展開為 RGB 之後再比較,也是很合理的
所以... 就這麼硬著頭皮測下去了(汗)
(所以這篇的參考價值不高,因此貼在聊天打屁區 )
下面是測試結果
1. MS MPEG-4 V2
用ネペパ樣的 M4C plugin,設定是
rate: 32767, key: 9999, cc: 100, pixel: 28, diff: 12
2. FFVFW
CQ quantizer 2x,沒有用 B-Frame,keyframe 間距 250(應該設 240,我設錯了,不過算了 )ME 用 EPZS,high quality,4MV(一個 Macroblock 16x16 的像素方塊中,允許上下左右四個 8x8 的方塊各自尋找最匹配的參考方塊,總共有四個移動向量,理論上可以提高壓縮率),量化的方法採用 H.263(uniform quantization,畫面會比較模糊)
因為在我的電腦上 FFVFW VFW Codec 自己解碼會當機,所以我把 4CC 改成 XviD,由 XviD 的 Codec 來解碼
3. XviD Nic's build 9/10
quantizer 2x,key 250,EPZS^2,H.263
4. DivX 5.02 AviUtl
quantizer 2x,沒有用 B-Frame,slowest,key 250
前面的檔案都是用 AviUtl 壓的。我用的 AviUtl 0.98B 壓 DivX 5.02 開 B-Frame 的話會當掉,所以只好轉成 VFAPI,送給 VirtualDub 壓,同時沒有使用 B-Frame 的版本也用 VD 壓一個
5. DivX 5.02 VirtualDub
6. DivX 5.02 with B-Frame
測出來的 RGB-PSNR(RGB 三個分量的誤差總和)數據如下
代碼: 選擇全部
Comparing channel(s) RGB
Total frames processed: 2182
M4C: 34.4MB
Minimum Average Maximum
Mean Absolute Deviation: 0.0000 2.9154 8.6358
Mean Deviation: -1.4536 -0.7389 +0.0225
PSNR: 24.6355 36.9992 106.5268
FFVFW: 36.0MB
Minimum Average Maximum
Mean Absolute Deviation: 0.0000 3.5582 8.4511
Mean Deviation: -4.0049 -2.6206 +0.0000
PSNR: 26.6886 33.6259 106.5268
XviD: 38.3MB
Minimum Average Maximum
Mean Absolute Deviation: 0.0000 3.6458 8.3808
Mean Deviation: -3.9869 -2.8831 +0.0000
PSNR: 26.7289 33.5407 106.5268
DivX 5.02 AviUtl: 38.4MB
Minimum Average Maximum
Mean Absolute Deviation: 0.0000 2.9405 103.1112
Mean Deviation: -26.8836 -1.2053 +70.4096
PSNR: 6.0462 37.3114 106.5268
DivX 5.02 VirtualDub: 39.5MB
Minimum Average Maximum
Mean Absolute Deviation: 0.0000 3.9974 9.0646
Mean Deviation: -3.9360 -3.3034 +0.0000
PSNR: 24.5653 35.1597 106.5268
DivX 5.02 with B-frame: 32.3MB
Minimum Average Maximum
Mean Absolute Deviation: 0.0000 3.9233 9.0646
Mean Deviation: -3.9360 -3.0705 +0.0000
PSNR: 24.5653 35.2418 106.5268
我後來有想到一個在現有的情況下,比較精確的比較方法。
先將原始影像轉為 YUV,然後設定各個 Codec 解碼輸出 YUY2 格式(除了 MS MPEG-4 V2 3920 Codec 以外。MS MPEG-4 V2 Codec 只能輸出 RGB,必需要再轉換為 YUV),然後只比較 Y-channel 的 PSNR,這樣就不會有內插補點演算法不同造成的精確度問題了。(一般播放使用 DirectShow Filter 走 DirectDraw Overlay,會直接丟 YV12 的 data 給顯示卡,由顯示卡統一做硬體色空間轉換,所以補點的效果各個 Codec 壓出來的都一樣,不像現在實驗中,由 Codec 自行展開為 RGB,不知道各個 Codec 內部展開的算法優劣,這樣比較就沒有意義了)
不過這個實驗等以後再做,現在重點不是這個
上面的數據中,最大的 PSNR 有 106.5268dB 的,那是因為壓縮的畫面是一張全黑的畫面。
我發現 XviD 和 FFVFW(XviD 解碼)的顏色和原來差距較大,所以差不多每一張的畫面 PSNR 都輸 M4C。壓全白(RGB 255,255,255)的畫面測試,M4C 解出來是 RGB (254,254,254),XviD 和 FFVFW 都是 (253,253,253)。
另外我又發現 DivX 5.02 不用 B-Frame,以 AviUtl 壓出來有一個很奇怪的現象:
代碼: 選擇全部
M4C:
Mean Max Max
Absolute Mean Pos. Neg.
Frame Dev. Dev. Dev. Dev. PSNR (dB)
-----------------------------------------------------
906 3.4166 -0.6048 29 -28 36.1130
907 2.2439 -0.8765 39 -35 38.6011
908 2.5717 -0.8202 40 -37 37.5100
909 3.1709 -0.7919 40 -44 35.8069
910 3.5057 -0.7287 41 -45 35.1616
911 3.7912 -0.6942 45 -45 34.6511
DivX 5.02 AviUtl:
Mean Max Max
Absolute Mean Pos. Neg.
Frame Dev. Dev. Dev. Dev. PSNR (dB)
-----------------------------------------------------
906 3.6055 -1.2993 33 -28 35.8181
907 1.6161 -0.8691 28 -30 40.9100
908 35.9429 +4.7657 255 -255 11.4417
909 2.5504 -1.0653 31 -43 37.5625
910 2.9446 -1.1254 30 -40 36.6907
911 3.1894 -1.2157 43 -37 36.1986
我覺得非常奇怪,檢查這張 #908 才發現,它的畫面變成和前面的那張 keyframe 一模一樣,也就是說 keyframe 重複顯示,出現了兩次。
這種現象每一個 keyframe 後面都會發生。
譬如原來畫面的順序是
1 2 3 4 5 6 7 8
3 是 keyframe,則壓縮後畫面會變成
1 2 3 3 5 6 7 8
3 重複出現兩次,而 4 則不見了,直接跳掉
所以畫面比對的時候差距才會那麼大,PSNR 才會那麼低。
這個 bug 是 DivX 5.01 的時候就有的,有用 B-Frame 的時候正常,但是如果不用 B-Frame 就會出現這種現象。我以為 DivX 5.02 已經修掉這個 bug 了(用 VD 壓不會有這種現象),沒想到用 AviUtl 壓竟然又會出現這個 bug。
所以我才會用 VD 也壓一個不使用 B-Frame 的版本來比較看看,沒想到這一試,又試出一個更詭異的現象,我怎麼想都想不通會什麼會這樣。
那就是... 同樣的設定,用 VD 壓出來的畫質竟然大輸給 AviUtl(請參照上面的數據,AviUtl 平均 PSNR 37.3114dB,VD 35.1597dB,不是只有少數幾張差距很大,而是每一張畫面都輸差不多 1.5~3dB)。
這這這... 這實在太神奇了,這怎麼有可能呢?
VD 壓的時候,是拿 AviUtl 的專案檔轉成的 VFAPI AVI 來壓縮的,同樣經過 AviUtl 處理。AviUtl 處理的時候是 RGB24,VFAPI 內部也一律都是以 RGB24 運作,所以不會做色空間轉換的處理,直接丟給 VD。我為了確認,還用 VD 開啟輸入的 VFAPI AVI 之後,不經任何處理直接輸出畫面到剪貼簿,儲存後和 AviUtl 的畫面比對 PSNR,結果兩者完全一樣。也就是說,壓縮的訊源,AviUtl 和 VD 是完全一樣的。
再者,VD 壓縮的時候,我試過 Fast recompression(直接丟原始的 data 給 Codec),Normal recompression(由 VD 先將格式轉換為 RGB,再丟給 Codec,一樣不經過 VD 的 Filter),兩種壓出來的結果都一樣。
測試全白的畫面,VD 壓出來是 (251,253,253),AviUtl 壓出來是 (255,255,255)
發現這樣的結果之後,我怕是我自己忙中有錯,不小心更動了設定而不自知,或是電腦太老了突然秀逗,所以隔了一天之後重開機再壓一次,結果還是一樣。
這這這... 實在太奇怪了,同樣的設定,同樣的訊源,壓出來結果卻不一樣,有人知道這是為什麼嗎?
下面是一堆圖,如果看不到請在圖的位置上按滑鼠右鍵,「顯示圖片」,多試幾次
Frame #1582 原圖
M4C 壓縮後的圖。這是一張 keyframe。
M4C 和原圖的差異(difference),僅顯示 Y(亮度)的差異。
MS MPEG-4 keyframe 的預設值,quantizer 最低只能到 4x,所以只要是 keyframe 畫質都很慘。由差異圖可以看到,銳利線條旁邊都是斑斑點點的量化瑕疵。
FFVFW
FFVFW 的差異圖
H.263 的量化矩陣,線條、邊緣的部分都被削光了,畫面變得模糊。不過看起來很舒服
XviD
XviD 差異圖
同樣,H.263 量化矩陣。
DivX 5.02 AviUtl 壓縮,沒有使用 B-Frame
DivX 5.02 AviUtl 差異圖
喔喔,看起來很不錯
DivX 5.02 VD 壓縮,沒有使用 B-Frame
DivX 5.02 VD 差異圖
謎啊~~ .....
其他的圖,有機會再貼