用PIL实现滤镜(一)——素描、铅笔画效果

在计算机图形学发展史中,真实感绘制一直是主旋律。不过从20实际90年代中期开始,非真实感图像绘制(Non-Photorealistic Rendering,NPR)逐渐成为一个研究热点。说白了,真实感绘制目标是像照片般真实地再现客观世界,而非真实感图像绘制专注于图形个性化和艺术化的表达,它主要用来表现图形的艺术特质,以及模拟艺术作品(甚至包括作品中的缺陷)。

在介绍完非真实感图像绘制之后,我们再来提及一下PIL——Python Imaging Library(官方网址)。相信使用python的朋友们都不会陌生,因为在web应用中我们常常用它来生成缩略图。从名字也可以看出,PIL主要用来处理图片,它支持多种图片格式,并提供强大的图片和图像处理能力。详细的关于PIL的内容大家可以参阅手册

这个系列,我们就主要使用PIL来进行滤镜方面的处理,包括素描、铅笔画、油画等等滤镜效果的实现。在以后我会把代码托管出来。

PIL已经内置一些滤镜效果,详细见文档这篇文章

我们从素描效果开始。在PIL中,基础的类是Image类,首先有必要讲一下图片的mode。它有以下几种:

  • 1 (1-bit pixels, black and white, stored with one pixel per byte)
  • L (8-bit pixels, black and white):用来表示灰度图
  • P (8-bit pixels, mapped to any other mode using a colour palette)
  • RGB (3x8-bit pixels, true colour)
  • RGBA (4x8-bit pixels, true colour with transparency mask)
  • CMYK (4x8-bit pixels, colour separation)
  • YCbCr (3x8-bit pixels, colour video format)
  • I (32-bit signed integer pixels)
  • F (32-bit floating point pixels)

在开始素描效果之前,我们需要首先进行灰度图像预处理。所幸的是,用PIL非常容易实现。设img是Image类的实例,我们只要用convert函数强制转换为L模式即可。

?


1

img = img.convert("L")

不过还是有必要讲一下灰度预处理。何谓图像灰度化呢?图像灰度化即是使色彩的三种颜色分量的R,G,B的分量值相等,由于R,G,B的取值范围是[0, 255],所以灰度图像能够表示256种灰度颜色******像灰度法主要有三种算法:

  1. 最大值法(Maximum):使R、G、B的值等于三个色彩分量中的最大的一个分量值,即:R=G=B=Max(R,G,B)。
  2. 平均值法(Average):使R、G、B的值等于三个色彩分量的三个色彩分量的平均值,即:R=G=B= (R+G+B)/3。
  3. 加权平均值法(Weight Average):在这里我给R、G、B三分量分别附上不同的权值,表示为:R=G=B=WR*R+WG*G+WB*B ,其中WR,WG,WB分别是R、G、B的权值。在这里考虑由于人眼对绿色的敏感度最高,红色次之,对蓝色的敏感度最低,因此,当权值 WG > WR > WB时,所产生的灰度图像更符合人眼的视觉感受。PIL库使用ITU-R 601-2 luma transform:
    L = R * 299/1000 + G * 587/1000 + B * 114/1000
    即 WR=29.9%,WG=58.7%,WB=11.4%。

素描滤镜的处理关键是对边缘的查找。通过对边缘的查找可以得到物体的线条感。在对图像进行灰度化处理后,我们首先定义一个阈值(threshold)。我们知道素描主要强调的是明暗度的变化,绘制时是斜向方向,通过经验,我们将每个像素点的灰度值与其右下角的灰度值进行比较,当大于这个阈值时,就判断其是轮廓并绘制。

以下是素描滤镜的主函数:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

from PIL import Image

def sketch(img, threshold):

    ‘‘‘

    素描

    param img: Image实例

    param threshold: 介于0到100

    ‘‘‘

    if threshold < 0: threshold = 0

    if threshold > 100: threshold = 100

    

    width, height = img.size

    img = img.convert(‘L‘) # convert to grayscale mode

    pix = img.load() # get pixel matrix

    for w in xrange(width):

        for h in xrange(height):

            if w == width-1 or h == height-1:

                continue

            

            src = pix[w, h]

            dst = pix[w+1, h+1]

            diff = abs(src - dst)

            if diff >= threshold:

                pix[w, h] = 0

            else:

                pix[w, h] = 255

    return img

接着,我们写一个测试部分来看看效果:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

if __name__ == "__main__":

    import sys, os

    path = os.path.dirname(__file__) + os.sep.join([‘‘, ‘images‘, ‘lam.jpg‘])

    threshold = 15

    

    if len(sys.argv) == 2:

        try:

            threshold = int(sys.argv[1])

        except ValueError:

            path  = sys.argv[1]

    elif len(sys.argv) == 3:

        path = sys.argv[1]

        threshold = int(sys.argv[2])

    img = Image.open(path)

    img = sketch(img, threshold)

    img.save(os.path.splitext(path)[0]+‘.sketch.jpg‘, ‘JPEG‘)

可以在命令行中指定文件名和阈值,或者只指定阈值,或者不带参数。我的测试图片为:

效果图片:

不同的阈值,生成的效果不同。阈值越小,绘制的像素点就越多。

对于铅笔画来说,原理和素描十分相似,但是大家学过画画的就知道,素描强调的是阴影的效果,是斜向作画,而铅笔画主要是勾勒轮廓。因此在对每个像素点的处理上,就和素描产生变化。对于任意一个像素点,求出这个像素点的R、G、B三个分量与周围8个点的相应分量的平均值的差,如果这三个差都大于或者等于某个阈值,就画出线条。最后,铅笔画的作画不是单调的一种颜色,因此加入Alpha分量,大小等于对应点的alpha分量即可。于是,代码如下;

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

def pencil(img, threshold):

    ‘‘‘

    铅笔画

    param img: instance of Image

    param threshold

    ‘‘‘

    if threshold < 0: threshold = 0

    if threshold > 100: threshold = 100

    width, height = img.size

    dst_img = Image.new("RGBA", (width, height))

    if img.mode != "RGBA":

        img = img.convert("RGBA")

    pix = img.load()

    dst_pix = dst_img.load()

    for w in xrange(width):

        for h in xrange(height):

            if w == 0 or w == width - 1 \

               or h == 0 or h == height - 1:

                continue

            # 包括当前像素周围共9个像素点

            around_wh_pixels = [pix[i, j][:3] for j in xrange(h-1, h+2) for i in xrange(w-1, w+2)]

            # 排除当前像素点

            exclude_wh_pixels = tuple(around_wh_pixels[:4] + around_wh_pixels[5:])

            # 把各个像素点的各个分量求平均值         

            RGB = map(lambda l: int(sum(l) / len(l)), zip(*exclude_wh_pixels))

            

            cr_p = pix[i, j] # 当前像素点

            cr_draw = all([abs(cr_p[i] - RGB[i]) >= threshold for i in range(3)])

           

            if cr_draw:

                dst_pix[w, h] = 0, 0, 0, cr_p[3]

            else:

                dst_pix[w, h] = 255, 255, 255, cr_p[3]

    return dst_img

效果如图:

来自:http://qinxuye.me/article/implement-sketch-and-pencil-with-pil/

原文地址:https://www.cnblogs.com/zhn620/p/9251192.html

时间: 2024-08-30 04:09:12

用PIL实现滤镜(一)——素描、铅笔画效果的相关文章

如何使用SVG生成超酷的页面预加载素描动画效果

在线演示 本地下载 1 SVG简介 可缩放矢量图形是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式.它由万维网联盟制定,是一个开放标准. 2 SVG的特点 与其他图像格式相比(比如 JPEG 和 GIF),使用 SVG 的优势在于: SVG 图像可通过文本编辑器来创建和修改 SVG 图像可被搜索.索引.脚本化或压缩 SVG 是可伸缩的 SVG 图像可在任何的分辨率下被高质量地打印 SVG 可在图像质量不下降的情况下被放大 3 浏览器支持 Internet Exp

多媒体开发(6):滤镜实现各种图片效果 | Video-Filters | 变色

之前讲过使用FFmpeg的drawtext滤镜(把图片或文字加到视频上),而实际上,FFmpeg的滤镜很强大,远不止加字幕或加图片的功能.滤镜是很有趣的,可以把图片变模糊.变色.缩放旋转,等等. 本文介绍FFmpeg滤镜的使用.目的是让读者感受一下FFmepg的滤镜效果,这样在实际需要某种效果时,可以考虑使用FFmpeg. 小程这里直接使用FFmpeg的命令行来使用滤镜,不涉及写代码调用FFmpeg的内容,并且这里都是对图片进行滤镜处理,读者会看到很多有趣的处理效果. 但是,由于FFmpeg滤镜

PS 滤镜算法原理——碎片效果

%%% Fragment %%% 对原图做四个方向的平移.然后对平移的结果取平均 %%% 碎片效果 clc; clear all; Image=imread('4.jpg'); Image=double(Image)/255; [row,col,k]=size(Image); Image1=Image; Image2=Image; Image3=Image; Image4=Image; Offset=5; %%% 左移 Image1(:,1:col-Offset,:)=Image(:,1+Off

【57】android图片印刻,阳刻,素描图效果处理

介绍我参与开发的妙趣剪纸app使用的图片处理相关的技术 关于妙趣剪纸,各大android商店都可以下载,下面贴出小米商店的链接 妙趣剪纸下载 软件效果截图 如何实现上面的图片处理效果呢 1.初始化高斯矩阵 ProcessFactory.IniGauss_2(ProcessFactory.gauss_radius); //初始化高斯矩阵 2.转化为灰度图 Bitmap bmpGrayscale=ProcessFactory.toGray2(activity.imageBmp); //转化为灰度图

tiltShift.js - CSS3 滤镜实现移轴镜头效果

tiltShift.js 是一款很棒的 jQuery 插件,使用 CSS3 图片滤镜来实现照片的移轴镜头效果.使用非常简单,使用 data 属性配置参数.温馨提示:为保证最佳的效果,请在 IE10+.Chrome.Firefox 和 Safari 等现代浏览器中浏览. 效果演示      插件下载 HTML 示例: <img src="url" class="tiltshift" data-position="50" data-blur=&

Atitit 常用比较复杂的图像滤镜 attilax大总结

像素画滤镜 水彩油画滤镜 素描滤镜 梦幻镜 特点是中央集焦,周围景物朦化微带光晕,使人产生如入梦境的感觉.常用于拍摄婚纱.明星照,也用于其它艺术摄影创作.此镜在暗背景下,以及使用长焦距镜头时效果更明显 魔幻镜 又称旋风镜,是以中央集焦,四周呈螺旋形散射状,效果犹如进入神奇的魔幻世界.使用时可采用广角镜头或小光圈.二十五.爆炸镜:又称散射镜,是以中央集焦,向四周产生强烈的辐射(爆炸状)这特点,动感非常明显,背景复杂效果更好.是渲染主体动感效果的滤镜之一.使用时宜用小光 月牙柔朦镜 此镜属朦胧镜一类

纯Python综合图像处理小工具(3)10种滤镜算法

<背景>  滤镜处理是图像处理中一种非常常见的方法.比如photoshop中的滤镜效果,除了自带的滤镜,还扩展了很多第三方的滤镜效果插件,可以对图像做丰富多样的变换:很多手机app实现了实时滤镜功能,最有名的当属Instagram. 滤镜的原理,常见的是针对数字图像的像素矩阵,使用一个nxn的方形矩阵做滤波器(即kernel,常见的如3x3,5x5等),对该像素矩阵进行遍历,遍历后的图像就是输出图像,如果算法经过优化,遍历的速度足够快,那就是实时滤镜(live filter),可以实时预览图像

Python之PIL库

Python PIL PIL (Python Image Library) 库是Python 语言的一个第三方库,PIL库支持图像存储.显示和处理,能够处理几乎所有格式的图片. 一.PIL库简介 1. PIL库主要有2个方面的功能: (1) 图像归档:对图像进行批处理.生产图像预览.图像格式转换等. (2) 图像处理:图像基本处理.像素处理.颜色处理等. 二.安装库函数 pip install pillow 三.使用库函数Image类 —— 基本图像处理 1. 调用Image类 from PIL

iOS开发 滤镜的使用

iOS开发之滤镜的使用技巧(CoreImage) 一.滤镜的内容和效果是比较多并且复杂的 ,学习滤镜需要技巧 如下: 两个输出语句解决滤镜的属性选择问题: 1.查询效果分类中包含什么效果按住command 点击CIFilter 进入接口文件 找到第128行-148行全部都是 效果分类 2.选择其中某一个分类拷贝NSLog -> [CIFilter filterNamesInCategory:刚才拷贝的分类]; -> 打印出来的 是这个分类包含的所有效果 -> 拷贝选择其中的某一个效果 3