十四个Python极客项目编程

一、解析iTunes播放列表

该项目在iTunes播放列表文件中查找重复的乐曲音轨,并绘制各种统计数据,如音轨长度和评分。你可以从查看iTunes播放列表格式开始,然后学习如何用Python提取这些文件的信息。为了绘制这些数据,要用到matplotlib库。

在这个项目中,我们将学习以下主题:

  • XML和属性列表(p-list)文件;
  • Python列表和字典;
  • 使用Python的set对象;
  • 使用numpy数组;
  • 直方图和散点图;
  • 用matplotlib库绘制简单的图;
  • 创建和保存数据文件。

所需模块:

import re, argparse
import sys
from matplotlib import pyplot
import plistlib
import numpy as np

二、万花斥资

我们可以用万花尺玩具(如图2-1所示)来绘制数学曲线。这种玩具由两个不同尺寸的塑料齿轮组成,一大一小。小的齿轮有几个孔。把钢笔或铅笔放入一个孔,然后在较大齿轮(内部有齿)内旋转里面的小齿轮,保持笔与外轮接触,可以画出无数复杂而奇妙的对称图案。

在这个项目中,我们将用Python来创建动画,像万花尺一样绘制曲线。我们的spiro.py程序将用Python和参数方程来描述程序的万花尺齿轮的运动,并绘制曲线(我称之为螺线)。我们可以将完成的画图保存为PNG图像文件,并用命令行选项来指定参数或生成随机螺线。

在这个项目中,我们将学习如何在计算机上绘制螺线。还将学习以下几点:

  • 用turtle模块创建图形;
  • 使用参数方程;
  • 利用数学方程来生成曲线;
  • 用线段来画曲线;
  • 用定时器来生成图形动画;
  • 将图形保存为图像文件。
import sys, random, argparse
import numpy as np
import math
import turtle
import random
from PIL import Image
from datetime import datetime
from fractions import gcd

三、Conway生命游戏

这个项目将创建一个N×N的细胞网格,通过应用Conway生命游戏的规则,模拟系统随时间的演进。你将显示每个时间段的游戏状态,并提供一些方式将输出保存到文件。你会设置系统的初始状态,要么是随机分布,要么是预先设计的图案。

该模拟由以下几部分组成:

在一维或两维空间中定义的属性;
在模拟中的每一步,改变这种属性的数学规则;
随着系统的演进,显示或记录系统状态的方式。
在Conway生命游戏中的细胞可以处于ON或OFF状态。游戏从一个初始状态开始,其中每个细胞分配一个状态,数学规则决定其状态如何随时间而改变。Conway生命游戏中令人惊奇的是,只有4个简单的规则,系统演进会产生行为极其复杂的图案,仿佛它们是活的。图案包括“滑翔机”,即在网格上滑动,“眨眼”,即闪烁ON和OFF,甚至还有复制图案。

当然,这个游戏的哲学意义也很重要,因为它们表明,复杂的结构可以根据简单的规则演进,不必遵循任何一种预设的模式。

下面是该项目包含的一些主要概念:

  • 利用matplotlib imshow来展示数据的二维网格;
  • 利用matplotlib生成动画;
  • 使用numpy数组;
  • 将%运算符用于边界条件;
  • 设置值的随机分布。

因为生命游戏建立在9个方格的网格中,每个细胞有8个相邻细胞,如图3-1所示。模拟中的给定细胞(i, j)用二维数组[i][j]来存取,其中i和j分别是行和列的下标。在给定时间段,给定细胞的值取决于前一时间段它的邻居的状态。Conway生命游戏有4个规则。

1.如果一个细胞为ON,邻居中少于两个为ON,它变为OFF。
2.如果一个细胞为ON,邻居中有两个或3个为ON,它保持为ON。
3.如果一个细胞为ON,邻居中超过3个为ON,它变为OFF。
4.如果一个细胞为OFF,邻居中恰好有3个为ON,它变为ON。

所需模块:

import sys, argparse
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

四、用Karplus-Strong算法产生音乐泛音

任何乐音的主要特点是它的音调,即频率。这是每秒的振动数,单位是赫兹(Hz)。例如,从原声吉他的第三根弦产生音符D,频率是146.83赫兹。可以在计算机上创建频率为146.83 Hz的正弦波,来模拟这种声音,如图4-1所示。

遗憾的是,如果在计算机上播放这个正弦波,听起来不会像吉他或钢琴。播放相同的音符时,是什么让计算机的声音与乐器如此不同呢?

在吉他上拨弦时,乐器产生了不同强度的混合频率,如图4-2的频谱图所示。刚拨弦时声音最强,强度随着时间推移而逐渐消失。拨动吉他D弦听到的主要频率称为基本频率,是146.83赫兹,但也会听到该频率的一些倍数,称为泛音。任何乐器的声音都由这种基本频率和泛音组成,正是这种组合,让吉他听起来像吉他。

如你所见,在计算机上模拟拨弦乐器的声音,要能同时生成基本频率和泛音。诀窍是利用Karplus-Strong算法。

这个项目使用Karplus-Strong算法,产生5个类似吉他的音符,它们属于一个音阶(一系列相关的音符)。我们会让产生这些音符的算法可视化,并将声音保存为WAV文件。我们还会创建一种方式,随机演奏它们,并学习如何做到以下几点:

  • 用Python的deque类实现环形缓冲区;
  • 使用numpy数组和ufuncs;
  • 用pygame播放WAV文件;
  • 用matplotlib绘图;
  • 演奏五声音阶。

所需模块:

import sys, os
import time, random
import wave, argparse, pygame
import numpy as np
from collections import deque
from matplotlib import pyplot as plt

五、类鸟群:仿真鸟群

仔细观察一群鸟或一群鱼,你会发现,虽然群体由个体生物组成,但该群体作为一个整体似乎有它自己的生命。鸟群中的鸟在移动、飞越和绕过障碍物时,彼此之间相互定位。受到打扰或惊吓时会破坏编队,但随后重新集结,仿佛被某种更大的力量控制。

1986年,Craig Reynolds创造鸟类群体行为的一种逼真模拟,称为“类鸟群(Boids)”模型。关于类鸟群模型,值得注意的是,只有3个简单的规则控制着群体中个体间的相互作用,但该模型产生的行为类似于真正的鸟群。类鸟群模型被广泛研究,甚至被用来制作群体的计算机动画,如电影“蝙蝠侠归来(1992)”中的行军企鹅。

本项目将利用Reynolds的3个规则,创建一个类鸟群,模拟N只鸟的群体行为,并画出随着时间的推移,它们的位置和运动方向。我们还会提供一个方法,向鸟群中添加一只鸟,以及一种驱散效果,可以用于研究群体的局部干扰效果。类鸟群被称为“N体模拟”,因为它模拟了N个粒子的动态系统,彼此之间施加作用力。

所需模块:

import sys, argparse
import math
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from scipy.spatial.distance import squareform, pdist, cdist
from numpy.linalg import norm

六、ASCII文本图形

在20世纪90年代,电子邮件占据着统治地位,图形处理能力很有限,常见的做法是在电子邮件中包含一个签名,它是由文本制作的图形,一般称为ASCII文本图形(ASCII是一个简单的字符编码方案)。图6-1展示了两个例子。尽管因特网已经让共享图像容易很多,但出身卑微的文本图形还没有消失。

ASCII文本图形的源头是19世纪后期出现的打字机文本图形。在20世纪60年代,计算机有了较弱的图形处理硬件,ASCII被用于表示图形。今天,ASCII文本图形继续作为因特网上的一种表现形式,你可以在网上找到各种创意的例子。

这个项目用Python创建一个程序,从图像生成ASCII文本图形。该程序让你指定输出(文本列数)的宽度,并设置垂直比例因子。它也支持两种灰度值到ASCII字符的映射:稀疏的10级映射和更精细校正的70级映射。

要从图像生成ASCII文本图形,需要学习如何做到以下几点:

  • 用Pillow将彩色图像转换成灰度图像,它是Python的图像库(PIL)的一个分支;
  • 使用numpy计算灰度图像的平均亮度;
  • 用一个字符串作为灰度值的快速查找表。

所需模块

import sys, random, argparse
import numpy as np
import math
from PIL import Image

七、照片马赛克

照片马赛克是一张图像,它被分割成长方形的网格,每个长方形由另一张匹配“目标”的图像(最终希望出现在照片马赛克中的图像)替代。换言之,如果从远处看照片马赛克,会看到目标图像;但如果走近,会看到该图像实际上包含许多较小的图像。

这个迷题有解是因为人眼的工作方式。图7-1中的低分辨率块状图像,靠近了很难识别,但如果从远处看,就知道它代表什么,因为看到的细节较少,就使得边缘越光滑。照片马赛克的原理是相似的。从远处看,图像看起来正常,但走近时,秘密揭开了:每“块”都是一个独特的图像!

本项目中,我们将学习如何用Python创建照片马赛克。我们将目标图像划分成较小图像的网格,并用适当的图像替换网格中的每一小块,创建原始图像的照片马赛克。你可以指定网格的尺寸,并选择输入图像是否可以在马赛克中重复使用。

在这个项目中,你将学习如何做到以下几点:

用Python图像库(PIL)创建图像;
计算图像的平均RGB值;
剪切图像;
通过粘贴另一张图像来替代原图像的一部分;
利用平均距离测量来比较RGB值。

所需模块:

import sys, os, random, argparse
from PIL import Image
import imghdr
import numpy as np

八、三维立体画

盯着图8-1看一分钟。除了随机的点,你还看到别的什么吗?图8-1是一张三维立体画,是制造三维假象的二维图像。 三维立体画通常包含一些重复的图案,仔细观察会被大脑解释为三维。如果你看不到任何图像效果,别担心。我也花了一段时间,做了一些尝试,才能看到(如果你在本书的印刷版本上看不到,请在这里尝试彩色的版本:https://github.com/electronut/pp/images/。标题的脚注提示了你应该看到的图像)。

本项目将用Python创建一张三维立体画。下面是本项目涉及的一些概念:

线性间距和深度知觉;
深度图;
用Pillow创建和编辑图像;
用Pillow绘制图像。
本项目生成的三维立体画设计为用“墙眼”方式观看。看到它们的最好方法,就是让眼睛聚焦在图像后面的点(如墙上)。有点神奇,一旦在这些图案中感知到某样东西,眼睛就会自动将它作为关注的焦点,如果三维图像已“锁定”,你很难对它视而不见的(如果你仍然无法看到图像,请看Gene Levin的文章“How to View Stereograms and Viewing Practice” [1] ,或许有帮助)。

所需模块

import sys, random, argparse
from PIL import Image, ImageDraw

九、理解OpenGL

本项目将创建一个简单的程序,利用OpenGL和GLFW来显示纹理贴图的正方形。OpenGL为图形处理单元(GPU)增加了一个软件接口,而GLFW是一个窗口工具包。我们还将学习如何使用类似C语言的OpenGL着色语言(GLSL)来编写着色器,即在GPU上执行的代码。着色器为OpenGL中的计算带来巨大的灵活性。我会展示如何用GLSL着色器来变换几何图形并上色,创建一个旋转的、带纹理的多边形(如图9-1所示)。

GPU经过优化,以并行的方式对大量数据反复地执行相同的操作,这让它们在做这样的工作时,比中央处理单元(CPU)快得多。除了渲染计算机图形,它们也用于通用计算,现在有一些专门的语言让你用GPU硬件完成这样的工作。本项目将利用GPU、OpenGL和着色器。

Python是一种极好的“胶水”语言。对于其他语言(如C语言)编写的库,有大量的Python绑定,让你在Python中使用它们。本章和第10章、第11章,将使用PyOpenGL,即OpenGL的Python绑定,来创建计算机图形。

OpenGL是一个“状态机”,有点像一个电器开关,有两种状态:开和关。如果从一种状态切换到另一种,开关就保持在这种新状态。然而,OpenGL比简单的电器开关更复杂,它更像一个交换机,有许多开关和表盘。一旦更改特定设置的状态,它就保持为关,直到你打开。如果一个 OpenGL调用绑定到某个对象上了,那随后的相关调用都会发送给这个对象,直到解除绑定。

import OpenGL
from OpenGL.GL import *
import numpy, math, sys, os
import glutils
import glfw

十、粒子系统

在计算机图形世界中,粒子系统是用许多小图元(如点、线、三角形和多边形)来表示的物体,如烟雾、火焰,甚至头发,没有明确的几何形状,因此很难用标准技术来建模。

例如,如何在计算机上制造一次爆炸效果?设想爆炸从空间中的一个点开始,然后向外扩张,作为一个快速扩大的、复杂的三维实体,随时间而改变形状和颜色。不夸张地说,尝试建立数学模型就令人望而生畏。

但现在设想一下,爆炸包含一群细小的粒子,每个粒子有关联的位置和颜色。爆炸开始时,粒子在空间中的一个点上聚成一图。随着时间的推移,它们根据一定的数学规则向外移动,并改变颜色,让你定期绘制所有粒子,从而生成爆炸的动画。利用好的数学模型、大量粒子,以及透明度和公告板(billboarding)这样的渲染技术,可以创建逼真的效果,如图10-1所示。

本项目会制定粒子运动的数学模型,将它表示为时间的函数,并利用图形处理单元(GPU)的着色器进行计算。然后,会设计一种渲染方案,利用一种名为公告板的技术,它让二维图像一直面向观众,从而使二维图像看起来像是三维的,用一种令人信服的方式来绘制这些粒子。还会用OpenGL着色器让粒子旋转,并生成动画场景。你可以通过按键来打开或关闭各种效果,进行比较。

数学模型将设置每个粒子的初始位置和速度,并决定粒子如何随时间运动。你可以让每个纹理的黑色区域透明,利用正方形图像创建火花,保持每个火花面向观众,使它们看起来有立体感。你会生成粒子的动画,定期更新它们的位置,其亮度随着时间的推移逐渐减弱。

下面是将要探索的一些概念:

  • 制定喷泉粒子系统的数学模型;
  • 利用GPU着色器计算;
  • 利用纹理和公告板模拟复杂的三维对象;
  • 利用OpenGL渲染功能,如混合、深度遮掩和Alpha通道,绘制半透明物体;
  • 利用相机模型绘制三维透视图。

十一、体渲染

MRI和CT扫描这样的诊断过程会创建体数据,它由一组二维图像来表示通过三维物体的截面。体绘制是一种计算机图形技术,利用这种类型的体数据来构造三维图像。虽然体绘制通常用于分析医学扫描,但也可以用于地质、考古和分子生物学等学科,生成三维科学可视化效果。

由MRI和CT扫描记录的数据通常采取N x ×N y ×N z 的三维网格形式,或N z 个二维“切片”,其中每个切片是大小为N x ×N y 的图像。体绘制算法采用某种类型的透明度,来展示采集切片数据,并采用各种技术来强调被渲染物体中关注的部分。

本项目将探讨名为“体光线投射(volume ray casting)”的体绘制算法,它充分利用图形处理单元(GPU),用OpenGL着色语言(GLSL)的着色器来进行计算。代码针对屏幕上的每个像素执行,并利用了GPU,其目的是有效地进行并行计算。利用二维图像文件夹中包含的三维数据集切片,用体光线投射算法,构建体渲染图像。我们还会实现一种方法,显示在x、y、z方向上的二维切片数据,以便用户可以通过箭头键来滚动切片。键盘命令让用户在三维渲染和二维切片之间切换。

下面是本项目涉及的一些主题:

  • 用GLSL进行GPU计算;
  • 创建顶点和片段着色器;
  • 表示三维立体数据,并使用体光线投射算法;
  • 用numpy数组表示三维变换矩阵。

12、Arduino简介

13、激光音乐秀

14、基于树莓派的天气监控器


https://github.com/electronut/pp

posted @ 2022-04-19 16:10  Tacey Wong  阅读(1027)  评论(0编辑  收藏  举报