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
若此博文能幫到您,歡迎掃碼小額贊助。
微信:
支付寶: