在计算机图形学发展史中,真实感绘制一直是主旋律。不过从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

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

  1. 素描滤镜_素描fu自定义键盘快捷键

    素描滤镜 Custom App Shortcuts is a little known, but handy feature of macOS. I use my keyboard instead o ...

  2. 滤镜应用——制作彩虹效果

    滤镜应用--制作彩虹效果 原图: 效果图: 步骤: 1.打开素材图片,新建图层1,选择"矩形选框工具",在图层1上圈出一个矩形选区,选择"渐变工具",选择色谱线 ...

  3. 巧用Photoshop滤镜模拟水粉花卉效果(转)

    巧用Photoshop滤镜模拟水粉花卉效果(转)[@more@] 先看原图 效果图 1.在Photoshop中打开一副图像.单击"滤镜-艺术效果-水彩",设置如图,效果如图. 2. ...

  4. 素描滤镜_素描fu依次导出画板

    素描滤镜 You're working on a new feature for your music app. This feature is called "Add to Playlis ...

  5. 利用Numpy+PIL读取图像实现手绘效果

    读取图像+简单处理 import numpy as np from PIL import Imagepath = "" #图像路径im = np.array(Image.open( ...

  6. PS动作把人物照片变成炭笔素描画效果

    首先我们是用制作炭笔素描静物人物头像效果PS动作而成的,用法也非常简单载入相关预设,然后把软件变成英文等就可以制作出来下图这样的效果了,动作支持CS6至CC 2017版本软件. 01.打开软件载入图案 ...

  7. 【视觉基础篇】12 # 如何使用滤镜函数实现美颜效果?

    说明 [跟月影学可视化]学习笔记. 如何理解像素化? 像素化 所谓像素化,就是把一个图像看成是由一组像素点组合而成的.每个像素点负责描述图像上的一个点,并且带有这个点的基本绘图信息. 像素点是怎么存储 ...

  8. html背景图片加滤镜,滤镜、图像混合效果如何在css 中实现?

    用 Photoshop 的都有用到滤镜来处理图片,那在前端如何用代码来实现呢? 这就得用到 css 滤镜 了. css 滤镜兼容. 背景知识: css 滤镜语法: filter: none | blu ...

  9. 用CSS3实现滤镜——常见九种效果

    特别强调:IE无法实现!!! 复习时看这个提纲进行回忆并持续补充. 文章目录 一.滤镜是什么 二.滤镜操作 1. 模糊效果 2. 亮度 3. 对比度 4. 图像阴影 5. 图像灰度 6. 反转效果 7 ...

最新文章

  1. linux执行命令段错误,Linux运行fortran程序 出现段错误(segmentation fault)
  2. 报名 | AI Time :论道AI安全与伦理
  3. C# 托管资源和非托管资源
  4. Wpf使用Winform控件后Wpf元素被Winform控件遮盖问题的解决
  5. 【Forge】Minecraft 1.7.10 Mod开发研究 - 黑猫背包MOD 【06-给你唱一首岁月的歌】
  6. shell sort
  7. SRAM,SDRAM,网卡
  8. html dl dt dd 标签语法与使用
  9. 帆软按钮控件变查询_JS使用填报页面的控件查询
  10. 虚拟机主机服务器出现SSH已启用,ESXi去掉 SSH已经启用的警告信息
  11. winfrom+Fleck 上传文件
  12. 全网各编程语言的爱心代码合集
  13. 【开发日常】【Java】Java小程序汽车租赁
  14. java合并word_java实现合并多个word文档 且可换页 实例代码(基于docx4j)
  15. Android 服务动态发现 SPA 之 Auto Service
  16. scrapy框架之shell
  17. vue 同局域网访问不到问题
  18. 曲线救国: 使用 Markdown 编辑器来写 Confluence 文档
  19. 高一计算机专业班主任工作总结,【班主任工作总结报告计算机材料】
  20. ArcGIS基础实验操作100例--实验76按格网统计点要素

热门文章

  1. 高级程序员的七大特征,你有几条?
  2. 超强仿QQ自动伸缩窗口
  3. MESI 缓存一致性协议
  4. javascript实现单按钮显示隐藏元素
  5. 哈希算法的原理和用途详解
  6. Android 证书安装流程分析
  7. 中国联通、中国电信、中国移动的3G速度对比!
  8. NSCTF2017-SteinsGate wp
  9. Linux文件类型与文件权限详解(一)
  10. ora-03113 linux,ORA-03113: end-of-file on communication channel 解决方案