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

2024-04-22 01:48
文章标签 图像 艺术 滤镜 水彩画

本文主要是介绍图像滤镜艺术---水彩画滤镜,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

水彩画滤镜

水彩画滤镜算法如下:

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

这篇关于图像滤镜艺术---水彩画滤镜的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/924563

相关文章

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

Python+wxPython构建图像编辑器

《Python+wxPython构建图像编辑器》图像编辑应用是学习GUI编程和图像处理的绝佳项目,本教程中,我们将使用wxPython,一个跨平台的PythonGUI工具包,构建一个简单的... 目录引言环境设置创建主窗口加载和显示图像实现绘制工具矩形绘制箭头绘制文字绘制临时绘制处理缩放和旋转缩放旋转保存编

python+OpenCV反投影图像的实现示例详解

《python+OpenCV反投影图像的实现示例详解》:本文主要介绍python+OpenCV反投影图像的实现示例详解,本文通过实例代码图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前言二、什么是反投影图像三、反投影图像的概念四、反向投影的工作原理一、利用反向投影backproj

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

基于WinForm+Halcon实现图像缩放与交互功能

《基于WinForm+Halcon实现图像缩放与交互功能》本文主要讲述在WinForm中结合Halcon实现图像缩放、平移及实时显示灰度值等交互功能,包括初始化窗口的不同方式,以及通过特定事件添加相应... 目录前言初始化窗口添加图像缩放功能添加图像平移功能添加实时显示灰度值功能示例代码总结最后前言本文将