图像滤镜艺术---水彩画滤镜

水彩画滤镜

水彩画滤镜算法如下:

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)的值。

示意图如下:

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;

}

效果图如下:

原图

水彩画滤镜效果图

最后,放上一个完整的C#版程序DEMO下载地址:http://www.zealpixel.com/thread-61-1-1.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 14:50:14

图像滤镜艺术---水彩画滤镜的相关文章

图像滤镜艺术--Toaster滤镜

根据Instagram CEO的说法,Toaster滤镜是Instagram所有滤镜中最复杂的滤镜,这个滤镜给人一种新奇的红色烘烤感,很能让人联想起这个Toaster单词的本意呵呵,今天我将用C#实现这个滤镜,当然我也只是探索,如何逼近它的效果,差异的存在在所难免,大家勿怪哦. 按照之前的说法,还是先使用Photoshop进行模拟,然后根据模拟步骤,进行C#代码编写. 首先,看下效果图: (a)PS效果图 (b)Instagram效果图 (c)C#代码效果图 效果怎么样我说了不算呵呵,下面介绍P

图像滤镜艺术--暴雨滤镜

    今天给大家介绍的是一款暴雨滤镜,可以将一些风和日丽的风景照片变换为暴雨效果的照片,废话不多说,先给大家看下效果: (a)原图 (b)PS效果图 (c)代码实现效果图 这个暴雨滤镜也比较简单,按照之前的步骤,我们依次介绍PS实现过程以及代码实现过程. PS实现过程如下: 1,暴雨模板图像生成: 这个过程我简单介绍一下我的实现,不过大家不需要自己制作模板了,我已经把模板放在了资源里,大家直接使用即可.模板制作步骤如下: 1.1 新建一个空白图像,大小按照自己的需要确定,我这里取的是1000*

图像滤镜艺术--大雪滤镜

今天给大家介绍一款大雪滤镜,可以使你夏天的照片瞬间幻化为大雪纷飞的场景哦!先看下效果图: 上面三张图像分别是(a)原始图像,(b)PS效果图,(c)C#代码效果图 这个大雪滤镜也比较简单,按照之前的步骤,我们依次介绍PS实现过程以及代码实现过程. PS实现过程如下: 1,打开原始图像,复制图层a,新建图层mask,填充为黑色: 2,滤镜--杂色--添加杂色: 3,模糊--进一步模糊: 4,调整色阶: 5,高斯模糊,与a进行混合,选择混合图层-滤色模式: 6,原图调出冷色调: 这样就出来了大雪效果

图像滤镜艺术---Swirl滤镜

Swirl Filter Swirl 滤镜是实现图像围绕中心点(cenX,cenY)扭曲旋转的效果,效果图如下: 原图 效果图 代码如下: // /// /// Swirl Filter /// /// Source image. /// The X position of Swirl. /// The Y position of Swirl. /// The degree of swirl,0-360. /// The result image. private Bitmap SwirlFil

图像滤镜艺术---Wave滤镜

Wave Filter水波滤镜 水波滤镜是通过坐标变换来模拟水波效果,使图像呈现出水波的特效.这个滤镜有一个可调参数:水波的扭曲程度. 代码如下; // /// /// Wave Filter /// /// Source image. /// The degree of wave,0-100. /// The result image. private Bitmap WaveFilterProcess(Bitmap srcBitmap, int degree) { Bitmap a = new

滤镜艺术---新海诚滤镜特效的实现解密

最近新海诚滤镜特效很火,Camera360为此还专门开发了相应的app,天天P图等等也是争先恐后,今天,本人来给大家解密一下. 先给大家看下本人程序实现的效果图: 原图 效果图 下面本人来详细说明一下如何程序实现这个滤镜特效: 1,天空检测与分割 这个滤镜中最主要的就是天空区域的分割与替换,关于天空分割,本人给出一篇参考文献: Sky detection by effective context inference. Neurocomputing.2016 该文章是基于训练学习来实现天空分割的,

图像滤镜艺术---ZPhotoEngine超级算法库

一直以来,都有个想法,想要做一个属于自己的图像算法库,这个想法,在经过了几个月的努力之后,终于诞生了,这就是ZPhotoEngine算法库. 这个算法库目前包含两个模块:基础图像算法模块+滤镜模块,使用C语言实现,现在免费分享给大家,可以适用于PC/Android/Ios三大平台. 1,基础图像算法模块 这个模块,本人以Photoshop基础算法为原形,模拟出了PS大部分的基础算法. 为什么选择Photoshop算法?这个也是我的算法库一个优势,目前开源算法库多如牦牛,但是,能和PS媲美的,少之

图像滤镜艺术---(Instagram)1977滤镜

图像特效---(Instagram)1977滤镜 本文介绍1977这个滤镜的具体实现,这个滤镜最早是Instagram中使用的 ,由于Instagram滤镜备受欢迎,因此,美图秀秀中也使用了这个滤镜,只是名字不是1977,而是1970. 原理不多说了,直接给出代码最实在,这个代码是经过优化过的,复杂的算法都已经写成了一个映射表,这样做可以大大提高效率,代码如下: private Bitmap FilterProcess(Bitmap a) { Bitmap srcBitmap = new Bit

图像滤镜艺术---保留细节的磨皮之C#程序实现

上一篇博文"保留细节的磨皮滤镜之PS实现"一文中.我简介了本人自己总结的一种非常easy的磨皮滤镜,这个滤镜在磨光皮肤的同一时候,会保留非常不错的细节,今天,我将介绍使用C#程序实现这个磨皮的过程. 这里,我们相同是使用ZPhotoEngine库来实现,毕竟这个库中实现的效果跟PS是差点儿一模一样的.关于下载地址,文章最后会给出.废话不多说了,磨皮过程例如以下: 一.对原图的副本a运行表面模糊,半径15: 二.对原图运行高反差保留,半径1.0. 三.对高反差结果与原图做线性光图层处理,