轉《影象處理之表面濾波》
阿新 • • 發佈:2018-11-02
本文介紹經典的表面模糊Surface Blur演算法與實現。
表面模糊是PS裡一個重要的保邊濾波器,它的演算法很簡單,公式如下所示:
主要思想還是計算當前畫素X的鄰域範圍內不同畫素的加權求和,邊緣地方的畫素,加權比較大,平滑的地方加權比較小,以此來保留邊緣資訊,平滑平坦區域;
效果如下圖所示:
程式碼實現如下:
[cpp] view plain copy- #define MIN2(a, b) ((a) < (b) ? (a) : (b))
- #define MAX2(a, b) ((a) > (b) ? (a) : (b))
- #define CLIP3(x, a, b) MIN2(MAX2(a,x), b)
- void f_SurfaceBlur(unsigned char* srcData, int width, int height, int stride, int radius, int threshold)
- {
- if (srcData == NULL)
- {
- return;
- }
- float sumr = 0, sumrw = 0, sumg = 0, sumgw = 0, sumb = 0, sumbw = 0, k = 0;
- int pos = 0, pos0 = 0;
- unsigned char* tempData = (unsigned char*)malloc(sizeof(unsigned char) * height * stride);
- memcpy(tempData, srcData, sizeof(unsigned char) * height * stride);
- for(int j = 0; j < height; j++)
- {
- for(int i = 0; i < width; i++)
- {
- pos = i * 4 + j * stride;
- sumr = sumrw = sumg = sumgw = sumb = sumbw = 0;
- for(int n = -radius; n <= radius; n++)
- {
- for(int m = -radius; m <= radius; m++)
- {
- int x = CLIP3(i + m, 0, width - 1);
- int y = CLIP3(j + n, 0, height - 1);
- pos0 = x * 4 + y * stride;
- k = 1.0f - abs(tempData[pos0] - tempData[pos]) / (2.5f * threshold);
- sumb += k * tempData[pos0];
- sumbw += k;
- k = 1.0f - abs(tempData[pos0 + 1] - tempData[pos + 1]) / (2.5f * threshold);
- sumg += k * tempData[pos0 + 1];
- sumgw += k;
- k = 1.0f - abs(tempData[pos0 + 2] - tempData[pos + 2]) / (2.5f * threshold);
- sumr += k * tempData[pos0 + 2];
- sumrw += k;
- }
- }
- srcData[pos] = sumbw == 0 ? srcData[pos] : CLIP3(sumb / sumbw, 0, 255);
- srcData[pos + 1] = sumgw == 0 ? srcData[pos + 1] : CLIP3(sumg / sumgw, 0, 255);
- srcData[pos + 2] = sumrw == 0 ? srcData[pos + 2] : CLIP3(sumr / sumrw, 0, 255);
- }
- }
- free(tempData);
- }
程式碼沒有經過優化,是完全按照公式實現的,如果考慮優化,可以考慮使用多執行緒,或者是YCbCr顏色空間只對Y處理,以此加速,效果會比較明顯。