附录 A Python 的艺术

“艺术就是艺术,对吧?同样,水就是水!东就是东,西就是西。如果你把越橘炖得像苹果酱一样,那么它尝起来就比大黄更像西梅。”

——Groucho Marx

你可能是个艺术家、抑或是音乐家,或者你只是想尝试一些不同的能激发无限创造力的事情。

前三个附录收录了人们在不同场合、不同领域借助 Python 进行的探索。如果你对其中的某些领域感兴趣,可能会从中获取些许灵感,或产生动手尝试的冲动。

A.1 2D图形

几乎所有的计算机编程语言或多或少都会被应用到图形处理中。尽管本章用到的许多功能强大的平台,出于效率考虑,都是由 C 或 C++ 编写的,但它们大都喜欢用 Python 编写的库来扩展其功能。我们先来看一些 2D 成像库。

A.1.1 标准库

标准库中与图形相关的库并不多,这里介绍其中的两个。

  • imghdr

这个模块用于检测图片文件的文件格式。

  • colorsys

这个模块用于在不同的颜色系统(RGB、YIQ、HSV 以及 HLS)间进行转换。

如果你已经把 O'Reilly 的标志下载到本地并存储为 oreilly.png,可以直接运行下面这段代码:

  1. >>> import imghdr
  2. >>> imghdr.what('oreilly.png')
  3. 'png'

为了在 Python 中对图片进行更高级的处理,我们需要安装一些第三方包。先来看看有哪些包可用。

A.1.1 PIL和Pillow

多年以来,尽管 Python 图片库(Python Image Library,PIL,http://effbot.org/imagingbook/pil-index.htm)并不属于 Python 的标准库,但它一直是 Python 中最著名的 2D 图片处理库。由于它在包安装器 pip 之前就已出现,因此我们无法用便捷的 pip 命令进行安装。对此,有人创建了一个友好的项目分支 Pillow(http://pillow.readthedocs.org/)。Pillow 向后兼容 PIL,并且文档更为规范,因此这里我们选择使用 Pillow 作为替代。

安装过程非常简单,在终端中执行下面的命令即可:

  1. $ pip install Pillow

如果你曾经安装过 libjpeglibfreetypezlib 这几个系统包,它们会被 Pillow 检测出来并且直接使用,不再重复安装。你可以在安装页(http://pillow.readthedocs.org/en/latest/installation.html)了解更多安装细节。

打开一个图片文件:

  1. >>> from PIL import Image
  2. >>> img = Image.open('oreilly.png')
  3. >>> img.format
  4. 'PNG'
  5. >>> img.size
  6. (154, 141)
  7. >>> img.mode
  8. 'RGB'

尽管包的名字是 Pillow,但为了让它与旧的 PIL 兼容,我们需要将它引用为 PIL

使用 Image 对象的 show() 方法可以在屏幕上显示图片,但为此你需要先安装 ImageMagick 包。下一小节会介绍这个包,到时候试着运行下面的代码:

  1. >>> img.show()

执行上述代码后,屏幕上会跳出一个新窗口,如图 A-1 所示。(截图是在 Mac OS X 系统下截取的,show() 实际上打开了 Mac 中预览程序来显示图片。不同系统下的图片浏览窗口可能有所不同。)

{%}

图 A-1:使用 Python 库打开的图片

将放入内存中的图片裁剪一下,把结果存储为一个新的对象 img2 并重新显示它。图片总是以水平坐标值(x)和垂直坐标值(y)计量,它们以图片的一角作为参考。这个角被称作原点,它的 x 坐标和 y 坐标都是 0。我们使用的库中,原点(0, 0)定义为图片的左上角,x 向右增加,y 向下增加。想要给 crop() 方法传入 4 个参数:左侧距 x(55)、顶距 y(70)、右侧距 x(85)以及底距 y(100),需要先将它们按顺序封装在元组中。

  1. >>> crop = (55, 70, 85, 100)
  2. >>> img2 = img.crop(crop)
  3. >>> img2.show()

结果如图 A-2 所示。

附录 A Python 的艺术 - 图2

图 A-2:裁剪后的图片

使用 save 方法存储图片。它接收一个文件名参数以及一个可选参数——图片类型。如果文件名中有扩展名,库函数会直接使用这个扩展名作为图片的格式,当然你也可以显式指定使用的格式。执行下面的代码可以将裁剪后的图片存储为 GIF 文件:

  1. >>> img2.save('cropped.gif', 'GIF')
  2. >>> img3 = Image.open('cropped.gif')
  3. >>> img3.format
  4. 'GIF'
  5. >>> img3.size
  6. (30, 30)

我们来美化一下我们的小吉祥物吧。首先将胡须图片(http://www.pinkmoustache.net/wp-content/uploads/2009/12/moustaches.png)下载到本地,存储为 moustaches.png。接着将它加载到内存中,进行适当的裁剪,然后把它置于之前图片的上层:

  1. >>> mustache = Image.open('moustaches.png')
  2. >>> handlebar = mustache.crop( (316, 282, 394, 310) )
  3. >>> handlebar.size
  4. (78, 28)
  5. >>> img.paste(handlebar, (45, 90) )
  6. >>> img.show()

图 A-3 展示了最佳效果。

{%}

图 A-3:全新帅气的吉祥物

如果胡须图片的背景是透明的话效果会更好。不如把这个当作练习吧!如果你想要把上面的例子做到最好,查看一下 Pillow 教程(http://pillow.readthedocs.org/en/latest/handbook/tutorial.html)中关于透明度alpha 值的相关内容,然后自己动手试试吧!

A.1.3 ImageMagick

ImageMagick(http://www.imagemagick.org/script/index.php)是一套用于转换、修改、显示 2D 位图的程序。它已经有 20 余年的历史了。许多第三方 Python 库都会应用到 ImageMagick C 库,其中最近的一个支持 Python 3 的库是 wandhttp://docs.wand-py.org/en/0.4.0/)。执行下面的语句来安装它:

  1. $ pip install Wand

你可以使用 wand 做许多 Pillow 能做到的事情:

  1. >>> from wand.image import Image
  2. >>> from wand.display import display
  3. >>>
  4. >>> img = Image(filename='oreilly.png')
  5. >>> img.size
  6. (154, 141)
  7. >>> img.format
  8. 'PNG'

和 Pillow 类似,下面的语句用于显示图片:

  1. >>> display(img)

wand 包含旋转、调整大小、添加文本、画线、格式转化等强大的功能,这些功能你也可以在 Pillow 中找到。Wand 和 Pillow 的 API 和文档都非常规范好用。

A.2 图形用户界面

GUI 这个名词虽然包括图形这个词,但它的重点更在于用户界面(展示数据用的小控件、输入的方法、菜单、按钮以及包含所有这些的窗口等)上。

GUI 编程(https://wiki.python.org/moin/GuiProgramming)的 wiki 页以及 FAQ(https://docs.python.org/3.3/faq/gui.html)列出了许可用 Python 编写的 GUI。我们从唯一一个内置于标准库的 Tkinter(https://wiki.python.org/moin/TkInter)开始介绍。它功能不多,但可以在所有平台上创建符合接近原生界面的窗口以及控件。

下面是一个极简的 Tkinter 程序,它可以在新建的窗口中显示我们最爱的小吉祥物,它有着曲棍球似的眼睛:

  1. >>> import tkinter
  2. >>> from PIL import Image, ImageTk
  3. >>>
  4. >>> main = tkinter.Tk()
  5. >>> img = Image.open('oreilly.png')
  6. >>> tkimg = ImageTk.PhotoImage(img)
  7. >>> tkinter.Label(main, image=tkimg).pack()
  8. >>> main.mainloop()

注意,上面的代码用到了 PIL/Pillow 中的一些模块。你应该又一次见到了 O'Reilly 的标志,如图 A-4 所示。

{%}

图 A-4:使用 Tkinter 库显示的图片

想要关闭窗口的话只需点击关闭按钮或者关闭 Python 解释器即可。

你可以在 tkinter wiki(http://tkinter.unpythonic.net/wiki/)和 Python wiki(https://wiki.python.org/moin/TkInter)上看到更多关于 Tkinter 的信息。现在来看一些不包含在标准库中的 GUI。

Qt 是一款由挪威 Trolltech 公司开发的专业级 GUI 及应用工具包,已有 20 多年的历史。像著名的 Google Earth、Maya 以及 Skype 都是由 Qt 协助完成的。它还被用于一款桌面版 Linux——KDE 的开发。Qt 有两个主要的 Python 库版本:其中 PySide(http://wiki.qt.io/PySide)是免费的(LGPL 许可),PyQt(http://www.riverbankcomputing.com/software/pyqt/intro)则是基于 GPL 许可付费使用的。你可以在这里看到它们之间的差别(http://wiki.qt.io/Differences_Between_PySide_and_PyQt),可以从 PyPi(https://pypi.python.org/pypi/PySide)或 Qt(http://qt-project.org/wiki/Get-PySide)网站下载 Qt 并阅读相关教程(http://qt-project.org/wiki/PySide_Tutorials),可以在线(http://www.riverbankcomputing.com/software/pyqt/download5)免费下载 Qt 主体。

GTK+ 是 Qt 的一个强劲对手,它也被广泛应用于包括 GIMP 和 Gnome(一款桌面版 Linux)在内的许多应用(http://gtk-apps.org/)的开发。它与 Python 通过 PyGTK(http://www.pygtk.org/)进行绑定。你可以访问 PyGTK 的官网(http://www.pygtk.org/downloads.html)下载代码、阅读相关文档(http://python-gtk-3-tutorial.readthedocs.org/en/latest/)。

用于将 Python 与 WxWidgets(http://www.wxwidgets.org/)进行绑定。WxWidgets 也是一款功能强大的 UI 工具包,你可以从网上(http://wxpython.org/download.php)免费下载。

Kivy 是一个用于搭建跨平台——PC 端(Windows、OS X、Linux)及移动端(Android、 iOS)——多媒体UI的现代库。它包含对于多点触控的支持。你可以从 Kivy 官网(http://kivy.org/#download)下载所有平台对应的库文件。它还提供了不同平台的应用开发教程(http://kivy.org/docs/gettingstarted/intro.html)。

  • 网络

像 Qt 这样的框架依赖的都是本地控件,然而也有一些其他的框架使用的是网络。毕竟网络是一种通用的 GUI,它包含图形(SVG)、文本(HTML)甚至现在还可以包含多媒体(HTML5)。使用 Python 编写的基于网络的 GUI 工具包括 RCTK(Remote Control Toolkit,https://code.google.com/p/rctk/)以及 Muntjac(http://muntiacus.org/)。你可以创建支持任意前端(基于浏览器)和后端(网络服务器)组合的网络程序。在瘦客户端模式下,后端会完成大部分工作。而如果前端起支配作用的话,我们称之为厚客户端、胖客户端或富客户端(最后一个词显然有拍马屁的嫌疑)。端与端之间的通信常使用 RESTful API、AJAX 以及 JSON。

A.3 3D图形和动画

现在几乎每一部电影的片尾字幕里都包含了许多制作特效和动画的人名。许多大型工作室——华特迪士尼动画、ILM、维塔数码、梦工厂、皮克斯——都会雇不少具有 Python 经验的人。你可以上网搜索“python 动画职位”看看,或者到 vfxjobs 上搜索关键词“python”看看有多少职位空缺。

如果你喜欢探索 Python,喜欢 3D、动画、多媒体以及游戏的话,应该试试 Panda3D(http://www.panda3d.org/)。它开源、完全免费,你甚至可以用它搭建商业应用。你可以从 Panda3D 官网(http://www.panda3d.org/download.php?sdk)上下载与你电脑系统对应的版本。如果你想要测试一下它自带的示例程序,需要先将终端的路径切换到 DeveloperExamples/Panda3D。这个目录中的每一个子目录都包含了一个或多个 .py 文件。使用 Panda3D 的 ppython 命令来运行这些示例程序。例如:

  1. $ cd DeveloperExamples/Panda3D
  2. $ cd Ball-in-Maze/
  3. $ ppython Tut-Ball-in-Maze.py
  4. DirectStart: Starting the game.
  5. Known pipe types:
  6. osxGraphicsPipe
  7. (all display modules loaded.)

一个类似图 A-5 的窗口会打开。

附录 A Python 的艺术 - 图5

图 A-5:使用 Panda3D 库显示的图片

你可以使用鼠标来倾斜盒子让球在迷宫中前进。

如果一切运行正常,Panda3D 的环境搭建也一切顺利,那么恭喜你,现在就可以开始使用这个库了。

下面是一个来自于 Panda3D 文档的示例程序,将它保存为 panda1.py:

  1. from direct.showbase.ShowBase import ShowBase
  2. class MyApp(ShowBase):
  3. def __init__(self):
  4. ShowBase.__init__(self)
  5. # 加载环境模型
  6. self.environ = self.loader.loadModel("models/environment")
  7. # 为模型重定父级以渲染
  8. self.environ.reparentTo(self.render)
  9. # 对模型应用尺度和位置变换
  10. self.environ.setScale(0.25, 0.25, 0.25)
  11. self.environ.setPos(-8, 42, 0)
  12. app = MyApp()
  13. app.run()

使用下面的命令运行它:

  1. $ ppython panda1.py
  2. Known pipe types:
  3. osxGraphicsPipe
  4. (all display modules loaded.)

运行后会弹出一个窗口,如图 A-6 所示。当前的石头和树是悬浮在半空中的。点击 Next 按钮,按照教程继续,它会引导你解决这个问题。

附录 A Python 的艺术 - 图6

图 A-6:使用 Panda3D 库显示的适应窗口大小的图片

下面是其他一些可以在 Python 中使用的 3D 包。

Blender 是一个免费的 3D 动画和游戏的生成器。当你从 http://www.blender.org/download/ 下载并安装了它后,它会绑定一个自带的 Python 3。

Maya 是一个商用的 3-D 动画和图形处理系统。它也会绑定一个自带的 Python,目前绑定的是 Python 2.6。Chad Vernon 编写了 Python Scripting for Maya Artists(http://www.chadvernon.com/blog/resources/python-scripting-for-maya-artists/),你可以在网上免费下载。如果你在网上搜索 Python 和 Maya,可以找到许多其他资源,包括一些视频资料,它们有些是免费的,有些可能是付费的。

Houdini 是一个商用系统,但你可以下载它的一个免费版本 Apprentice。和其他动画包一样,它也有自己绑定的 Python(http://www.sidefx.com/docs/houdini13.0/hom/)。

A.4 平面图、曲线图和可视化

Python 是目前绘制平面图、曲线图以及进行数据可视化的最佳解决方法。它在科学研究中尤其受到欢迎,你可以在附录 C 了解相关应用。Python 的官方网站上关于可视化有一些概论性内容(https://wiki.python.org/moin/NumericAndScientific/Plotting)。在这里我想花一点时间做一些额外介绍。

A.4.1 matplotlib

使用下面的命令可以免费安装 matplotlib 2D 绘图库:

  1. $ pip install matplotlib

官网图片库(http://matplotlib.org/gallery.html)中的例子展示了 matplotlib 的应用范围之广。我们使用和之前一样的程序来展示图片(如图 A-7 所示),这里只是为了看看需要编写的代码以及显示结果如何:

  1. import matplotlib.pyplot as plot
  2. import matplotlib.image as image
  3. img = image.imread('oreilly.png')
  4. plot.imshow(img)
  5. plot.show()

附录 A Python 的艺术 - 图7

图 A-7:使用 matplotlib 库显示的图片

你可以在附录 C 中看到更多关于 matplotlib 的内容,它与 NumPy 以及其他一些研究性应用关系十分密切。

A.4.2 bokeh

在网络发展初期,为了在线显示图形,开发者们需要在服务器端将其生成好并给浏览器返回对应的 URL。但如今,JavaScript 的表现能力越来越强,一些像 D3 之类的在客户端生成图形的工具也越发流行。前几页中,我曾提到过可以使用 Python 搭建前 - 后端框架用于展示图形和 GUI。一款名为 bokehhttp://bokeh.pydata.org/en/latest/)的新工具将 Python 的能力(大数据集、易于使用)与 JavaScript(交互性、图形绘制延迟小)结合了起来。它致力于大数据集的快速可视化。

如果你已经安装过 bokeh 所依赖的库(NumPy、Pandas 和 Redis),那么现在可以通过下面一行简单的命令来安装 bokeh

  1. $ pip install bokeh

(你可以在附录 C 看到 NumPy 和 Pandas 的作用。)

或者,你也可以从 Bokeh 官网(http://bokeh.pydata.org/en/latest/docs/quickstart.html)下载并一口气安装所有所需内容。尽管 matplotlib 是运行在服务器上的,bokeh 主要在浏览器上运行,它可以充分利用最近客户端能力的提升。点击官网图片库(http://bokeh.pydata.org/en/latest/docs/gallery.html)中的图片可以进行交互式查看,并查阅实现该效果所用的 Python 代码。

A.5 游戏

Python 非常适合数据处理,在这一附录中,你又发现了 Python 在处理多媒体上的强大功能。那么关于游戏呢?

没错,碰巧 Python 还是一个绝佳的游戏开发平台。使用 Python 开发游戏的书籍不计其数,例如下面两本:

Python 的 wiki 页(https://wiki.python.org/moin/PythonGames)上包含了更多关于使用 Python 开发游戏的讨论。

最著名的 Python 游戏开发平台要数 pygame(http://pygame.org/news.html)了。你可以从 Pygame 官网(http://pygame.org/download.shtml)上下载对应平台的可执行安装包进行安装,并阅读 pummel the chimp 游戏的逐行实例(http://pygame.org/docs/tut/chimp/ChimpLineByLine.html)。

A.6 音频和音乐

Python 还能做什么?音频、音乐?或者让我的猫学会唱 Jingle Bell ?

好吧,其实只有前两个能做到。

标准库的多媒体服务(http://docs.python.org/3/library/mm.html)下有一些基本的音频模块,当然还有其他许多第三方模块(https://wiki.python.org/moin/Audio)可以使用。

下面这些库可以帮你生成音乐:

最后,下面列出的库可以帮助你整理你的音乐集或访问音乐数据: