sws_scale的算法有如下這些選擇。
#define SWS_FAST_BILINEAR 1
#define SWS_BILINEAR 2
#define SWS_BICUBIC 4
#define SWS_X 8
#define SWS_POINT 0x10
#define SWS_AREA 0x20
#define SWS_BICUBLIN 0x40
#define SWS_GAUSS 0x80
#define SWS_SINC 0x100
#define SWS_LANCZOS 0x200
#define SWS_SPLINE 0x400
首先,将一幅1920*1080的風景圖像,縮放為400*300的24位RGB,下面的幀率,是指每秒鐘縮放并渲染的次數。(經過我的測試,渲染的時間可以忽略不計,主要時間還是耗費在縮放算法上。)
算法 | 幀率 | 圖像主觀感受 |
SWS_FAST_BILINEAR | 228 | 圖像無明顯失真,感覺效果很不錯。 |
SWS_BILINEAR | 95 | 感覺也很不錯,比上一個算法邊緣平滑一些。 |
SWS_BICUBIC | 80 | 感覺差不多,比上上算法邊緣要平滑,比上一算法要銳利。 |
SWS_X | 91 | 與上一圖像,我看不出差別。 |
SWS_POINT | 427 | 細節比較銳利,圖像效果比上圖略差一點點。 |
SWS_AREA | 116 | 與上上算法,我看不出差別。 |
SWS_BICUBLIN | 87 | 同上。 |
SWS_GAUSS | 80 | 相對于上一算法,要平滑(也可以說是模糊)一些。 |
SWS_SINC | 30 | 相對于上一算法,細節要清晰一些。 |
SWS_LANCZOS | 70 | 相對于上一算法,要平滑(也可以說是模糊)一點點,幾乎無差別。 |
SWS_SPLINE | 47 | 和上一個算法,我看不出差別。 |
總評,以上各種算法,圖檔縮小之後的效果似乎都不錯。如果不是對比着看,幾乎看不出縮放效果的好壞。上面所說的清晰(銳利)與平滑(模糊),是一種客觀感受,并非清晰就比平滑好,也非平滑比清晰好。其中的Point算法,效率之高,讓我震撼,但效果卻不差。此外,我對比過使用CImage的繪制時縮放,其幀率可到190,但效果慘不忍睹,顔色嚴重失真。
第二個試驗,将一幅1024*768的風景圖像,放大到1920*1080,并進行渲染(此時的渲染時間,雖然不是忽略不計,但不超過5ms的渲染時間,不影響下面結論的相對準确性)。
算法 | 幀率 | 圖像主觀感受 |
SWS_FAST_BILINEAR | 103 | 圖像無明顯失真,感覺效果很不錯。 |
SWS_BILINEAR | 100 | 和上圖看不出差別。 |
SWS_BICUBIC | 78 | 相對上圖,感覺細節清晰一點點。 |
SWS_X | 106 | 與上上圖無差別。 |
SWS_POINT | 112 | 邊緣有明顯鋸齒。 |
SWS_AREA | 114 | 邊緣有不明顯鋸齒。 |
SWS_BICUBLIN | 95 | 與上上上圖幾乎無差別。 |
SWS_GAUSS | 86 | 比上圖邊緣略微清楚一點。 |
SWS_SINC | 20 | 與上上圖無差別。 |
SWS_LANCZOS | 64 | 與上圖無差別。 |
SWS_SPLINE | 40 | 與上圖無差別。 |
總評,Point算法有明顯鋸齒,Area算法鋸齒要不明顯一點,其餘各種算法,肉眼看來無明顯差異。此外,使用CImage進行渲染時縮放,幀率可達105,效果與Point相似。
個人建議,如果對圖像的縮放,要追求高效,比如說是視訊圖像的處理,在不明确是放大還是縮小時,直接使用SWS_FAST_BILINEAR算法即可。如果明确是要縮小并顯示,建議使用Point算法,如果是明确要放大并顯示,其實使用CImage的Strech更高效。
當然,如果不計速度追求畫面品質。在上面的算法中,選擇幀率最低的那個即可,畫面效果一般是最好的。
不過總的來說,ffmpeg的scale算法,速度還是非常快的,畢竟我選擇的素材可是高清的圖檔。
(本想順便上傳一下圖檔,但各組圖檔差異其實非常小,恐怕上傳的時候格式轉換所造成的圖像細節丢失,已經超過了各圖檔本身的細節差異,是以此處不上傳圖檔了。)
注:試驗了一下OpenCV的Resize效率,和上面相同的情況下,OpenCV在上面的放大試驗中,每秒可以進行52次,縮小試驗中,每秒可以進行458次。