频道栏目
首页 > 程序开发 > 综合编程 > 其他综合 > 正文
图像滤镜艺术---水彩画滤镜
2015-09-13 09:56:21      个评论    来源:Trent1985的专栏  
收藏   我要投稿
水彩画滤镜

水彩画滤镜算法如下:

1,假设原始图像为F(x,y),灰度化得到G(x,y);

2,构建一个半径为Radius的正方形模板M,边长为2*Radius+1;

3,将M在F上依次遍历每个像素,对于当前像素P(x,y):

设置一个油漆桶数N,由于图像灰度值范围为0-255,因此我们油漆桶的数量N要小于255,这个油漆桶是用来盛放不同类别的像素。

3.1首先按照油漆桶数N将0-255的范围划分为等距的N个油漆桶,对于模板中对应的像素,我们按照其灰度值,依次将其放入相应的油漆桶中;

3.2统计N个油漆桶中的像素数目,计算像素数最多的那个油漆桶内,像素的均值Mean,这个均值RGB就是模板中心像素P(x,y)的值。

示意图如下:

data-cke-saved-src=/uploadfile/Collfiles/20150913/2015091308574646.jpg

Fig.1 油画滤镜示意图(N=8)

注意:油漆桶数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;

}

效果图如下:

data-cke-saved-src=/uploadfile/Collfiles/20150913/2015091308574647.jpg

原图

data-cke-saved-src=/uploadfile/Collfiles/20150913/2015091308574648.png

水彩画滤镜效果图

 

 

点击复制链接 与好友分享!回本站首页
上一篇:图像滤镜艺术---(Lightleaks Filter)漏光滤镜
下一篇:图像滤镜艺术---(Punch Filter)交叉冲印滤镜
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站