可以從 rasterization, equalizer, 和算術去思考。
pipeline-1
pipeline-2
像素處理的程式碼片段:
其中 "Alpha blend components" 可透過改寫為以下:
給定每個 pixel 為 32-bit 的 RGBA 的 bitmap,其轉換為黑白影像的函式為:
人眼吸收綠色比其他顏色敏感,所以當影像變成灰階時,僅僅將紅色、綠色、藍色加總取平均,這是不夠的,常見的方法是將 red * 77, green * 151 + blue * 28,這三個除數的總和為 256,可使除法變簡單
提出效能改善的方案:
16 MB; 表格太大
降到 32 KB 以內; cache friendly
原始程式碼: RGBAtoBW
BMP (BitMaP) 檔是是很早以前微軟所開發並使用在 Windows 系統上的圖型格式,通常不壓縮,不像 JPG, GIF, PNG 會有破壞性或非破壞性的壓縮。雖然 BMP 缺點是檔案非常大,不過因為沒有壓縮,即使不借助 OpenCV、ImageMagick 或 .NET Framework 等等,也可以很容易地直接用 Standard C Library 作影像處理。
BMP 主要有四個部份組成:
以下是使用一張 1920x1080 的 BMP 圖片,所得知的檔案資訊:
執行時間:0.034494 sec
RGB 分別都是 8 bit,可以建立三個大小為 256 bytes 的 table,這樣就不用在每次轉 bw 過程中進行浮點數運算。
bw = (uint32_t) (r * 0.299 + g * 0.587 + b * 0.114);
bw = (uint32_t) (table_R[r] + table_G[g] + table_B[b]);
執行時間: 0.028148 sec
使用 pointer 的 offset 取代原本的繁雜的 bitwise operation。
執行時間: 0.020379 sec
將上述 Version 1 和 Version 2合併在一起
執行時間: 0.018061 sec
使用 ARM NEON 指令集 加速,執行環境是 Raspberry Pi 2 (Cortex-A7 x4),這是實作程式碼。
用 Raspberry Pi 2 測試:
NEON technology is an advanced SIMD (Single Instruction, Multiple Data) architecture for the ARM Cortex-A series processors.
Register :
簡言之,有了 NEON instruction set,就可以「同時」操作許多個 8, 16 或 32-bit 的資料,在訊號處理、影像處理、視訊解碼等有很高的應用價值。
首先先看 Version 4 :
將 RGB三色的 weight 丟進 r3 - r5。
vdup.8
(Vector Duplicate),分別複製到大小為 8 bit 的 NEON register d0 - d2
vld4.8
(Vector Load),載入 pixel 的資料到 4 個 8-bit 的 NEON register d4-d7,其中那個 4 是 interleave,因為我們有 ARGB,所以 gap = 4,從下面兩張圖就可以看出 vld 的用法。
再來就是計算 weighted average啦。Vector Multiply 和 Vector Multiply Accumulate
將值除以256就是我們要的灰階值了。
vrshrn
(Vector Shift Right by immediate value)
最後將結果儲存。
vst
(Vector Store)
執行時間: 0.016000 sec
從上面瀏覽過一遍用到的 NEON instruction set,就可以發現我們都是一次對多個 NEON register 作操作,下面討論分析有比較圖就可以看出效能差距。
再來看 Version 5
執行時間: 0.013200 sec
以上各版本執行時間都是 50 次迴圈平均下來的結果,測試檔為 1920x1080 32bit bmp 圖片。可以明顯看到 v2 效能表現比起 v1 來說 還好上許多,可見原始程式中「多次」的 bitwise operation 結果所帶來損耗比起浮點數運算還更多一些。若我們再將浮點數運算改成查表的話,最後時間能進步到 0.018061 sec,幾乎是原來的一半。
另外使用 perf 效能分析工具 來觀察原始版本和 version 3 中 instruction 和 cycle 數量。
可以看到 version 3 的 instruction 和 cycle 大約都只有原來的一半,這結果也正好反應在上面的執行時間上。
從這張表就可以很清楚了解使用 NEON 指令集加速後所得到的效能增長, Version 4 只花了原本 4.6%
的時間 就完成彩色轉灰階處理。