簡易 bokeh 圖像散景效果算法實現

bokeh百度百科的解釋html

 
攝影鏡頭光圈大小和拍攝距離決定了拍攝時的景深,相對於焦點位置,焦點前與焦點後的被拍攝物體會顯得模糊,這個模糊區域被稱爲焦外。
焦外具體的模糊程度還受到鏡頭中鏡片單體和組合的物理特性影響,造成了由鏡頭不一樣而獲得的不一樣的焦點外的圖像。因而焦外成像這個技術名詞出現了。
優秀的焦外成像柔順而迷人,色彩過渡天然,絲絕不遜色於焦點處的圖像魅力。
最典型的例子,就是夜景拍攝中的遠景模糊炫麗的燈光效果。c++

 

因爲算法邏輯比較簡單,就很少解釋。算法

簡單的說就是以半徑圓圈內的各通道基於明度進行權重計算。微信

  

#ifndef ClampToByte #define  ClampToByte(  v )  (((unsigned)int(v)) <(255) ? (v) : (v < 0) ? (0) : (255)) 
#endif

void bokeh(unsigned char *Input, unsigned char *Output, int Width, int Height, int Stride, int Radius) { int Channels = Stride / Width; int rsq = max(1, sqrtf(Radius)); for (int y = 0; y < Height; y++) { unsigned char * LinePD = Output + y*Stride; for (int x = 0; x < Width; x++) { unsigned int sum[3] = { 0 }; unsigned int weightsum = 0; for (int ny = max(0, y - Radius); ny < min(y + Radius, Height); ny++) { const    unsigned char * sampleLine = Input + ny*Stride; for (int nx = max(0, x - Radius); nx < min(x + Radius, Width); nx++) { if (sqrtf(nx - x) + sqrtf(ny - y) < rsq) { const    unsigned char * sample = sampleLine + nx*Channels; const    unsigned char&R = sample[0]; const    unsigned char&G = sample[1]; const    unsigned char&B = sample[2]; float weight = sqrtf((unsigned char)((21627 * R + 21627 * G + 21627 * B) >> 16)); for (int c = 0; c < Channels; c++) { sum[c] += weight*sample[c]; } weightsum += weight; } } } for (int c = 0; c < Channels; c++) { LinePD[c] = ClampToByte(sum[c] / weightsum); } LinePD += Channels; } } }

這個算法以上述寫法進行測試,速度極其的慢。ide

將這個算法的思想稍微變通一下,修改後1080P圖片可達到cpu單線程實時處理。函數

具體優化思路,參照 圖像紋理合成及紋理傳輸算法學習(附源碼)。 學習

源碼中的函數GetLocalSquareSum。測試

初學者可參考 分享用於學習C++圖像處理的代碼示例 ,稍微改改就能夠跑起來這個算法了。優化

 這裏就不貼優化後的代碼了。ui

這個算法思路用逆反思路,則能夠實現聚焦算法,算是一種特例化的反捲積算法。

一直很想把這個算法簡單的寫一下,寫着寫着又犯懶了。

明天與imageshop博主 碰個面,吃個飯,也是很久沒折騰圖像方面的東西了。

真懷念與imageshop博主搭檔攻克圖像算法的那些日子。

 

如有其餘相關問題或者需求也能夠郵件聯繫俺探討。

郵箱地址是: 
gaozhihan@vip.qq.com

 

若此博文能幫到您,歡迎掃碼小額贊助。

微信:  

 

 

支付寶: 

相關文章
相關標籤/搜索