水彩畫濾鏡 html
水彩畫濾鏡算法以下:算法
1,假設原始圖像爲F(x,y),灰度化獲得G(x,y);ide
2,構建一個半徑爲Radius的正方形模板M,邊長爲2*Radius+1;spa
3,將M在F上依次遍歷每一個像素,對於當前像素P(x,y):.net
設置一個油漆桶數N,因爲圖像灰度值範圍爲0-255,所以咱們油漆桶的數量N要小於255,這個油漆桶是用來盛放不一樣類別的像素。orm
3.1首先按照油漆桶數N將0-255的範圍劃分爲等距的N個油漆桶,對於模板中對應的像素,咱們按照其灰度值,依次將其放入相應的油漆桶中;htm
3.2統計N個油漆桶中的像素數目,計算像素數最多的那個油漆桶內,像素的均值Mean,這個均值RGB就是模板中心像素P(x,y)的值。blog
示意圖以下:get
Fig.1 油畫濾鏡示意圖(N=8)it
注意:油漆桶數N能夠調節圖像平滑度,模板半徑Radius用來調節水彩畫的水彩程度。
上述算法在進行模板遍歷時,能夠採用快速均值濾波算法的方法來提升效率。
代碼以下:
private Bitmap OilpaintFilterProcess(Bitmap srcBitmap, int radius, int smooth)
{
if (radius == 0)
return srcBitmap;
smooth = smooth < 1 ? 1 : smooth;
smooth = Math.Max(1, smooth);
Bitmap a = new Bitmap(srcBitmap);
int w = srcBitmap.Width;
int h = srcBitmap.Height;
if (radius > Math.Min(w, h) / 2)
radius = (int)(Math.Min(w, h) / 2 - 0.5);
System.Drawing.Imaging.BitmapData srcData = a.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
IntPtr ptr = srcData.Scan0;
int bytes = h * srcData.Stride;
byte[] srcValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, srcValues, 0, bytes);
byte[] tempValues = (byte[])srcValues.Clone();
int stride = srcData.Stride;
int i, j, k;
int unit = 4;
int[] gray_bt = new int[smooth];
int[] r_bt = new int[smooth];
int[] g_bt = new int[smooth];
int[] b_bt = new int[smooth];
int[] gray_bt_src = new int[smooth];
int[] r_bt_src = new int[smooth];
int[] g_bt_src = new int[smooth];
int[] b_bt_src = new int[smooth];
int r, g, b;
int gray = 0, bt_index = 0, max = 0, maxindex = 0;
i = 0;
bool frist = true;
int pos = 0;
for (j = 0; j < h; j++)
{
if (frist)
{
for (int m = -radius; m <= radius; m++)
{
for (int n = -radius; n <= radius; n++)
{
pos = Math.Abs(n) * unit + Math.Abs(m) * stride;
b = srcValues[pos++];
g = srcValues[pos++];
r = srcValues[pos];
gray = (b + g + r) / 3;
bt_index = gray * smooth >> 8;
gray_bt_src[bt_index]++;
b_bt_src[bt_index] += b;
g_bt_src[bt_index] += g;
r_bt_src[bt_index] += r;
}
}
Array.Copy(gray_bt_src, gray_bt, smooth);
Array.Copy(b_bt_src, b_bt, smooth);
Array.Copy(g_bt_src, g_bt, smooth);
Array.Copy(r_bt_src, r_bt, smooth);
max = 0;
maxindex = 0;
for (k = 0; k < smooth; k++)
{
if (max < gray_bt[k])
{
max = gray_bt[k];
maxindex = k;
}
}
pos = j * stride;
tempValues[pos++] = (byte)(b_bt[maxindex] / max);
tempValues[pos++] = (byte)(g_bt[maxindex] / max);
tempValues[pos] = (byte)(r_bt[maxindex] / max);
frist = false;
}
else
{
for (int m = -radius; m <= radius; m++)
{
pos = Math.Abs(m) * unit + Math.Abs(j - radius - 1) * stride;
b = srcValues[pos++];
g = srcValues[pos++];
r = srcValues[pos];
gray = (b + g + r) / 3;
bt_index = gray * smooth >> 8;
gray_bt_src[bt_index]--;
b_bt_src[bt_index] -= b;
g_bt_src[bt_index] -= g;
r_bt_src[bt_index] -= r;
pos = Math.Abs(m) * unit + Math.Abs(j + radius) % h * stride;
b = srcValues[pos++];
g = srcValues[pos++];
r = srcValues[pos];
gray = (b + g + r) / 3;
bt_index = gray * smooth >> 8;
gray_bt_src[bt_index]++;
b_bt_src[bt_index] += b;
g_bt_src[bt_index] += g;
r_bt_src[bt_index] += r;
}
Array.Copy(gray_bt_src, gray_bt, smooth);
Array.Copy(b_bt_src, b_bt, smooth);
Array.Copy(g_bt_src, g_bt, smooth);
Array.Copy(r_bt_src, r_bt, smooth);
}
for (i = 1; i < w; i++)
{
for (int m = -radius; m <= radius; m++)
{
pos = Math.Abs(i - radius - 1) * unit + Math.Abs(j + m) % h * stride;
b = srcValues[pos++];
g = srcValues[pos++];
r = srcValues[pos];
gray = (b + g + r) / 3;
bt_index = gray * smooth >> 8;
gray_bt[bt_index]--;
b_bt[bt_index] -= b;
g_bt[bt_index] -= g;
r_bt[bt_index] -= r;
pos = Math.Abs(i + radius) % w * unit + Math.Abs(j + m) % h * stride;
b = srcValues[pos++];
g = srcValues[pos++];
r = srcValues[pos];
gray = (b + g + r) / 3;
bt_index = gray * smooth >> 8;
gray_bt[bt_index]++;
b_bt[bt_index] += b;
g_bt[bt_index] += g;
r_bt[bt_index] += r;
}
max = 0;
maxindex = 0;
for (k = 0; k < smooth; k++)
{
if (max < gray_bt[k])
{
max = gray_bt[k];
maxindex = k;
}
}
pos = i * unit + j * stride;
tempValues[pos++] = (byte)(b_bt[maxindex] / max);
tempValues[pos++] = (byte)(g_bt[maxindex] / max);
tempValues[pos] = (byte)(r_bt[maxindex] / max);
}
}
srcValues = (byte[])tempValues.Clone();
System.Runtime.InteropServices.Marshal.Copy(srcValues, 0, ptr, bytes);
a.UnlockBits(srcData);
return a;
}
效果圖以下:
原圖
水彩畫濾鏡效果圖
最後,放上一個完整的C#版程序DEMO下載地址:http://www.zealpixel.com/thread-61-1-1.html