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

简介: 原文:图像滤镜艺术---水彩画滤镜水彩画滤镜 水彩画滤镜算法如下: 1,假设原始图像为F(x,y),灰度化得到G(x,y); 2,构建一个半径为Radius的正方形模板M,边长为2*Radius+1; 3,将M在F上依次遍历每个像素,对于当前像素P(x,y): 设置一个油漆桶数N,由于图像灰度值范围为0-255,因此我们油漆桶的数量N要小于255,这个油漆桶是用来盛放不同类别的像素。
原文: 图像滤镜艺术---水彩画滤镜

水彩画滤镜

水彩画滤镜算法如下:

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

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

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

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

3.1首先按照油漆桶数N0-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

目录
相关文章
|
C# 计算机视觉
图像滤镜艺术---Swirl滤镜
原文:图像滤镜艺术---Swirl滤镜Swirl Filter Swirl 滤镜是实现图像围绕中心点(cenX,cenY)扭曲旋转的效果,效果图如下: 原图 效果图 代码如下:         //         ///     ...
915 0
|
算法 C#
图像滤镜艺术---霓虹、浮雕、木刻滤镜
原文:图像滤镜艺术---霓虹、浮雕、木刻滤镜  图像特效往往可以将普通的照片呈现出一种令人耳目一新的效果,特效的种类繁多,比如各种流行的 滤镜特效等等,今天,我们介绍几种最简单的滤镜:霓虹效果,浮雕效果和木刻效果。
1722 0
|
C#
图像滤镜艺术---暗调滤镜
原文:图像滤镜艺术---暗调滤镜本文介绍暗调滤镜的实现过程,这个滤镜主要是呈现一种暗调,对比度明显的效果,原理很简单,公式如下: newR = R*R/255; newG = G*G/255; newB = B*B/255; 实现代码如下:  private Bitmap Filte...
913 0
|
C#
图像滤镜艺术---连环画滤镜
原文:图像滤镜艺术---连环画滤镜 小时候我们都喜欢看连环画,虽然是黑白色的,但是也能让我们看的津津有味。 今天,我在这里介绍一种连环画特效的实现方法,带你回到那个记忆的年代。
957 0
|
算法 vr&ar
图像滤镜艺术---漫画滤镜
原文:图像滤镜艺术---漫画滤镜 漫画滤镜 所谓漫画滤镜就是通过复杂的算法来模拟漫画的特点,从而使真实照片呈现出漫画的风格。要实现漫画的效果,首先要了解漫画的特点,漫画具有几个比较明显的特点如下: 1,颜色泛用 漫画中,使用的颜色比较单一,一般不会超过7种颜色,不像真实照片那样,具有丰富的...
1384 0
|
C# 计算机视觉
图像滤镜艺术--大雾效果滤镜
原文:图像滤镜艺术--大雾效果滤镜 今天给大家介绍一款大雾效果的滤镜,先看下效果图:                                                               ...
1109 0
|
C#
图像滤镜艺术---怀旧风格滤镜
原文:图像滤镜艺术---怀旧风格滤镜怀旧风格滤镜 本文介绍一款怀旧风格滤镜特效的代码实现,这个滤镜效果跟前面我们介绍的老照片滤镜效果相比,听起来感觉没太大差,实际上老照片不仅 有怀旧的风格,更多了一些怀旧的痕迹,比如照片的褶皱,裂纹等等,而怀旧风格,只是一种发黄的颜色风格而已。
1131 0
|
C# 计算机视觉
图像滤镜艺术--Toaster滤镜
原文:图像滤镜艺术--Toaster滤镜     根据Instagram CEO的说法,Toaster滤镜是Instagram所有滤镜中最复杂的滤镜,这个滤镜给人一种新奇的红色烘烤感,很能让人联想起这个Toaster单词的本意呵呵,今天我将用C#实现这个滤镜,当然我也只是探索,如何逼近它的效果,差异的存在在所难免,大家勿怪哦。
1130 0
|
C#
图像滤镜艺术--大雪滤镜
原文:图像滤镜艺术--大雪滤镜   今天给大家介绍一款大雪滤镜,可以使你夏天的照片瞬间幻化为大雪纷飞的场景哦!先看下效果图:   上面三张图像分别是(a)原始图像,(b)PS效果图,(c)C#代码效果图 这个大雪滤镜也比较简单,按照之前的步骤,我们依次介绍PS实现过程以及代码实现过程。
1225 0
|
C# 计算机视觉
图像滤镜艺术--暴雨滤镜
原文:图像滤镜艺术--暴雨滤镜     今天给大家介绍的是一款暴雨滤镜,可以将一些风和日丽的风景照片变换为暴雨效果的照片,废话不多说,先给大家看下效果:                             ...
1100 0
下一篇
无影云桌面