水彩画滤镜

水彩画滤镜算法如下:

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

图像滤镜艺术---水彩画滤镜相关推荐

  1. 图像滤镜艺术---漫画滤镜

    图像滤镜艺术---漫画滤镜 原文: 图像滤镜艺术---漫画滤镜 漫画滤镜 所谓漫画滤镜就是通过复杂的算法来模拟漫画的特点,从而使真实照片呈现出漫画的风格.要实现漫画的效果,首先要了解漫画的特点,漫画具 ...

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

    图像滤镜艺术---Wave滤镜 原文:图像滤镜艺术---Wave滤镜 Wave Filter水波滤镜 水波滤镜是通过坐标变换来模拟水波效果,使图像呈现出水波的特效.这个滤镜有一个可调参数:水波的扭曲程 ...

  3. 用php照片艺术化,图像滤镜艺术--大雪滤镜

    今天给大家介绍一款大雪滤镜,可以使你夏天的照片瞬间幻化为大雪纷飞的场景哦!先看下效果图: 上面三张图像分别是(a)原始图像,(b)PS效果图,(c)C#代码效果图 这个大雪滤镜也比较简单,按照之前的步 ...

  4. 图像滤镜艺术---(Lightleaks Filter)漏光滤镜

    原文:图像滤镜艺术---(Lightleaks Filter)漏光滤镜 (Lightleaks Filter)漏光滤镜 漏光拍摄其实就是一种摄影手法,最初是因为强烈光照导致相片交卷的过分曝光,最终在成 ...

  5. 图像滤镜艺术---(Nostalgla Filter)老照片滤镜

    原文:图像滤镜艺术---(Nostalgla Filter)老照片滤镜 (Nostalgla Filter)老照片滤镜 Nostalgla Filter主要是通过算法来模拟一种复古,陈旧的照片风格,以 ...

  6. 图像滤镜艺术---图像滤镜晕影调节算法研究

    原文:图像滤镜艺术---图像滤镜晕影调节算法研究 本文对滤镜中常见的晕影,晕角效果的实现做了研究,具体如下: 1 晕影调整算法 所谓晕影就是给图像四个角添加暗影效果,这暗影向图像中心逐渐淡化.我们使用 ...

  7. 图像滤镜艺术---PS图层混合模式之明度模式

    图像滤镜艺术---PS图层混合模式之明度模式 本文将介绍PS图层混合模式中比较复杂 的"明度"模式的算法原理及代码实现内容. 说到PS的图层混合模式,计算公式都有,具体代码实现也能 ...

  8. 图像滤镜艺术--编码基础(Photoshop基础变换的代码实现)

    原文:图像滤镜艺术--编码基础(Photoshop基础变换的代码实现) 自从上一篇博客写完之后,到现在已经有段时间了,这段时间不是不想接着写,只是想做的更好了在写出来给大家看呵呵. 今天,我将给大家介 ...

  9. 图像滤镜艺术---微软自拍APP滤镜实现合集DEMO

    原文:图像滤镜艺术---微软自拍APP滤镜实现合集DEMO 微软最近推出了自家的美颜app,大家有兴趣可以在苹果商店中下载一下看一看,今天,我们要说的便是这款app中的所有滤镜实现问题. 这款app中 ...

最新文章

  1. centos7下的glusterfs的安装与使用
  2. Tableau必知必会之如何做嵌套组合饼图
  3. Linux设备驱动开发-linux驱动中的阻塞访问方式
  4. yii2之原生sql
  5. 利用HTTP watch观察SAP CRM WebClient UI popup window
  6. workunit 的指的工作单元是什么_分频器是做什么用的?
  7. 微纪实 | 人工智能产业落地最真实的样子
  8. 数据库mysql常用操作_mysql数据库常用操作
  9. hadoop重新启动之后Datanode无法启动的问题
  10. matlab 遗传算法资料,matlab遗传算法代码
  11. poj3537 Crosses and Crosses 博弈论
  12. linux系统中文件不同颜色的含义
  13. ACM2023SWJTU寒假选拔赛2不完全题解
  14. U盘再次中毒——U盘文件消失却占内存
  15. Latex声调(一声、二声、三声等)
  16. Xmanager7 解决图形显示问题
  17. signed和unsigned区别
  18. 程序员应该知道的10大编程格言
  19. java 删除文件失败_java中File的delete()方法删除文件失败的原因
  20. 夏杰语音麦克精灵:智能语音交互升级新体验

热门文章

  1. 腾讯云服务器80等端口无法访问
  2. Java开发商用免费必备神器
  3. 卡尔曼滤波(kalman)相关理论以及与HMM、最小二乘法关系
  4. 哈密顿圈 MATLAB程序,matlab求最佳哈密顿圈遇到错误
  5. Office 2021:让人耳目一新
  6. 智慧仓储:打造仓储管理一张图
  7. unity3d学习笔记(一)方向键移动物体
  8. 我们会有我们的天长地久
  9. 路径中 / ./ ../ ../../ ../../../ 的含义
  10. Flutter 中 GestureDetector 的使用误区