版本5和6间的区别
于2006-01-08 18:44:06修订的的版本5
大小: 15399
编辑: czk
备注:
于2006-01-08 18:45:57修订的的版本6
大小: 15469
编辑: czk
备注:
删除的内容标记成这样。 加入的内容标记成这样。
行号 316: 行号 316:
{{{#!python
行号 337: 行号 337:

=== 更多关于读取图像 ===
}}}

== 更多关于读取图像 ==
行号 341: 行号 342:
{{{#!python
行号 343: 行号 344:
}}}
行号 348: 行号 349:
{{{#!python
行号 351: 行号 352:
}}}
行号 354: 行号 355:
{{{#!python
行号 358: 行号 359:
}}}
行号 361: 行号 362:
{{{#!python
行号 366: 行号 367:
}}}

Python Imaging Library 中文手册 (2003 版)

这是PIL的官方手册,2003年9月17日发布。这个版本涵盖 PIL 1.1.4的全部内容,同时也包括部分1.1.5新增的内容。

原版出处:http://www.pythonware.com/library/pil/handbook/

TableOfContents

Python Imaging Library 概述

  • PIL 1.1.4 | 2003年9月17日 | Fredrik Lundh, Matthew Ellis

1. 介绍

  • Python Imaging Library 为Python解释器提供了图像处理的功能。 这个库提供了广泛的文件格式支持、高效的内部表示以及相当强大的图像处理功能。 图像处理库的核心被设计成能够快速访问以几种基本像素类型表示的图像数据。它为通用图像处理工具提供了一个坚实基础。 让我们来看一些这个库的用途:

2. 图像归档处理

  • Python Imaging Library适合编写图像归档和批处理应用程序。使用这个库可以创建缩略图、转换文件格式、打印图像等。 当前版本的库能够识别和读取大量的图像格式。而能够输出的格式被特意限制在一些最常用以交换和展示的格式上。

3. 图像显示

  • 当前版本的库包括Tk的PhotoImage BitmapImage 接口,也包括Windows的DIB接口(需要同PythonWin一起使用)。对于在X和Mac上显示,可以使用Jack Jansen的img 库。

    • 为了调试方便,Unix版本的库提供了一个 show 方法,它会调用 xv 来显示图像。

4. 图像处理

这个库提供了基本的图像处理功能,包括点操作、内建滤波核滤波操作以及颜色空间变换操作。

  • 这个库也支持图像的缩放、旋转及任何仿射(affine)变换。 库中包含一个直方图方法,可以从图像中提取某些统计特征。用它可以实现自动的对比度增强以及全局统计分析功能。

入门导引

1. 使用 Image 类

Python Imaging Library中最重要的类是Image 类,定义在与它同名的模块中。有多种创建这个类的对象的方法:或者从文件中读取得到,或者从其他图像经处理得到,或者从头创建。

要从文件读取图像,可以使用Image 模块提供的open 函数。

   1 >>> import Image
   2 >>> im = Image.open("lena.ppm")

如果成功,这个函数返回一个Image 对象。可以使用这个对象的属性来检查文件的内容。

   1 >>> print im.format, im.size, im.mode
   2 PPM (512, 512) RGB

format 属性表示图像的原始格式。如果图像不是从文件中读取的,则它被设置成 None。size 属性是一个2-tuple,表示图像的宽度和高度 (以像素为单位)。mode 属性定义图像的通道的数量与名字,同时也包括像素的类型和颜色深度信息。通常来说,灰度图像的mode是"L" (luminance),真彩色图像的mode是 "RGB" ,pre-press图像的mode是"CMYK"。

如果文件不能打开,会抛出一个IOError 异常。

如果已经创建好了一个Image 类的对象,接下来就可以使用这个类定义的方法来处理和操作图像了。比如说,显示刚才打开的文件:

  • >>> im.show()

(show 的标准实现不是很高效,它先将图像保存成一个临时文件,然后调用 xv 程序来显示图像。如果你没有安装xv ,它甚至不能工作。然而如果它可用,它将是非常方便的测试和除错的工具。)

接下来的内容将对库中提供的一些功能进行一个概述。

2. 读写图像

Python Imaging Library 支持很广泛的图象文件格式。要从磁盘上读取文件,使用 Image 模块提供的open 函数。你不必了解你要打开的文件的格式,库会自动根据文件的内容来确定图像的格式。

要保存文件,使用Image 类的save 方法。保存文件时,文件名是非常重要的。除非你制定了格式,否则库会根据文件扩展名来决定使用哪种格式存储。

2.1. 将文件转换成 JPEG

import os, sys import Image

for infile in sys.argv[1:]:

  • f, e = os.path.splitext(infile) outfile = f + ".jpg" if infile != outfile:
    • try:
      • Image.open(infile).save(outfile)
      except IOError:
      • print "cannot convert", infile

save 方法可以带第二个参数,用来显式指定文件的格式。如果要使用非标准的扩展名,就必须这样指定文件格式:

2.2. 创建 JPEG 缩略图

import os, sys import Image

size = 128, 128

for infile in sys.argv[1:]:

  • outfile = os.path.splitext(infile)[0] + ".thumbnail" if infile != outfile:
    • try:
      • im = Image.open(infile) im.thumbnail(size) im.save(outfile, "JPEG")
      except IOError:
      • print "cannot create thumbnail for", infile

有一点非常重要的需要注意的是,除非到了迫不得已的时候,库不会装载或者解码光栅数据。当打开一个文件的时候,库会读取文件头以获得文件格式、颜色模式、图像大小等属性,但是文件剩余的部分不会马上处理。

这意味着,文件打开操作是很快的,它与文件的大小、压缩的类型没有关系。这里是一个快速识别一系列图像文件的简单例子:

2.3. 识别图像文件

import sys import Image

for infile in sys.argv[1:]:

  • try:
    • im = Image.open(infile) print infile, im.format, "%dx%d" % im.size, im.mode
    except IOError:
    • pass

3. 裁剪、粘贴和合并图像

Image 类提供一些对图像中的区域进行处理的方法。要从图像中提取一块子矩形区域,使用 crop 方法。

3.1. 从图像中拷贝一块子矩形区域

  • box = (100, 100, 400, 400) region = im.crop(box)

区域由4元组定义,表示为 (left, upper, right, lower)。 Python Imaging Library 使用左上角为 (0, 0)的坐标系统。同时要注意,坐标指向像素之间的位置,因此上述例子中描述的区域的大小为300x300像素。

区域图像能够经过某些特定的处理并粘回原处。

3.2. 处理一块子矩形区域,并粘回原处

  • region = region.transpose(Image.ROTATE_180) im.paste(region, box)

当把区域粘回原处时,指定的区域大小必须和区域图像的大小相同。此外,区域不能超出图像的边界。然而,原始图像的模式和区域图像的模式不必相同。如果不相同,区域图像的模式在粘贴时会被自动转换 (细节请查看后面有关颜色变换 的章节)。

这里有另一个例子:

3.3. 滚动一幅图像

def roll(image, delta):

  • "Roll an image sideways" xsize, ysize = image.size delta = delta % xsize if delta == 0: return image part1 = image.crop((0, 0, delta, ysize)) part2 = image.crop((delta, 0, xsize, ysize)) image.paste(part2, (0, 0, xsize-delta, ysize)) image.paste(part1, (xsize-delta, 0, xsize, ysize)) return image

更高级的技巧是,paste方法可以带一个透明掩模作为可选参数。在这个掩模中,像素值255 代表被粘贴的图像在那个位置上是不透明的。 (就是说,此处显示被粘贴的图像上的值。)像素值 0 表示被粘贴的图像是完全透明的。在它们之间的值表示不同程度的透明度。

Python Imaging Library 还允许对一幅多通道图像(比如RGB图像)的单个通道进行操作。split方法能够创建一组新的图像,每一幅都是原来多通道图像的一个通道。merge函数以一个模式和一组图像的元组为参数,把这些图像组成一幅新图像。下面的例子实现交换一幅RGB图像的三个通道:

3.4. 分离与合并通道

r, g, b = im.split() im = Image.merge("RGB", (b, g, r))

4. 几何变换

Image 类包含resize 和 rotate 方法来缩放和旋转图像。前者带一个tuple类型的参数来表示新的图像大小,后者带一个逆时针旋转的角度值作为参数。

4.1. 简单的几何变换

out = im.resize((128, 128)) out = im.rotate(45) # degrees counter-clockwise

如果要将图像旋转90度的整数倍,可以使用rotate 或者transpose 方法。后者还可以用来水平或者垂直镜像一幅图像。

4.2. transpose图像

out = im.transpose(Image.FLIP_LEFT_RIGHT) out = im.transpose(Image.FLIP_TOP_BOTTOM) out = im.transpose(Image.ROTATE_90) out = im.transpose(Image.ROTATE_180) out = im.transpose(Image.ROTATE_270)

There's no difference in performance or result between transpose(ROTATE) and corresponding rotate operations.

一个更通用的变换方法是 transform,在参考手册中有对它的详细叙述。

5. 颜色变换

Python Imaging Library提供convert函数,可以将图像在不同的像素格式间转换。

5.1. 转换图像颜色模式

  • im = Image.open("lena.ppm").convert("L")

库支持在所有支持的颜色模式和"L"以及"RGB"之间的直接转换。其他颜色模式之间的转换要借助于中间图像模式(通常是"RGB" 模式)。

6. 图像增强

Python Imaging Library提供一系列的函数和模块来进行图像增强。

6.1. 滤波器

ImageFilter 模块中包含一些预定义的增强滤波器,用filter 方法来使用滤波器。

6.1.1. 使用滤波器

import ImageFilter out = im.filter(ImageFilter.DETAIL)

6.2. 点操作

point 方法可以对图像的像素值进行变换(比如对比度变换)。在大多数场合,使用函数对象(带一个参数)作为参数传递给point方法。每一个像素使用这个函数对象进行变换:

6.2.1. 使用点变换

# multiply each pixel by 1.2 out = im.point(lambda i: i * 1.2)

用上面的技巧,你可以对图像用任何简单的表达式进行变换。你还可以结合使用point 和paste 方法来有选择的改变一幅图像:

6.2.2. 处理单个通道

# split the image into individual bands source = im.split()

R, G, B = 0, 1, 2

# select regions where red is less than 100 mask = source[R].point(lambda i: i < 100 and 255)

# process the green band out = source[G].point(lambda i: i * 0.7)

# paste the processed band back, but only where red was < 100 source[G].paste(out, None, mask)

# build a new multiband image im = Image.merge(im.mode, source)

注意用来创建mask的语法:

  • imout = im.point(lambda i: expression and 255)

Python 只计算一个逻辑表达式的一部分,只要能确定表达式的结果其他部分就不进行计算了,并把最后计算得到的值作为表达式的值返回。因此,如果上述expression是false(0),Python就不会检查第二个参数,因此返回0,否则返回255。

6.3. 增强

对于更多更高级的图像增强,可以使用ImageEnhance 模块。一旦从图像上创建了增强对象,你就可以尝试采用各种不同的参数进行快速的增强处理了。

你能通过这样的方法来调整图像的对比度、亮度、色彩平衡和锐度。

6.3.1. 增强图像

import ImageEnhance

enh = ImageEnhance.Contrast(im) enh.enhance(1.3).show("30% more contrast")

7. 图像序列

Python Imaging Library 包含对于图像序列 (也称作动画 格式)的基本支持。支持的序列格式包括 FLI/FLC, GIF, 和一些试验性的格式。TIFF 文件也能包含超过一帧的图像。

当你打开一个序列文件时,PIL 会自动加载序列中的第一帧。你可以使用seek 和tell 方法在不同帧之间移动:

7.1. 读取图像序列

import Image

im = Image.open("animation.gif") im.seek(1) # skip to the second frame

try:

  • while 1:
    • im.seek(im.tell()+1) # do something to im

except EOFError:

  • pass # end of sequence

正如这个例子所示,当序列结束时,你会得到一个EOFError 异常。

注意,当前版本库的绝大多数驱动只允许你移动到下一帧(如上面例子所示)。如果要回到文件的开头,你可能必须重新打开它。

下面的迭代类让你能够使用for循环来迭代图像序列:

7.2. 一个序列迭代类

class ImageSequence:

  • def init(self, im):

    • self.im = im

    def getitem(self, ix):

    • try:
      • if ix:
        • self.im.seek(ix)
        return self.im
      except EOFError:

for frame in ImageSequence(im):

  • # ...do something to frame...

8. Postscript格式打印

Python Imaging Library提供将图像、文字和图形输出到Postscript打印机的功能。这是一个简单的例子:

8.1. Drawing Postscript

   1 import Image
   2 import PSDraw
   3 
   4 im = Image.open("lena.ppm")
   5 title = "lena"
   6 box = (1*72, 2*72, 7*72, 10*72) # in points
   7 
   8 ps = PSDraw.PSDraw() # default is sys.stdout
   9 ps.begin_document(title)
  10  
  11 # draw the image (75 dpi)
  12 ps.image(box, im, 75)
  13 ps.rectangle(box) 
  14 
  15 # draw centered title
  16 ps.setfont("HelveticaNarrow-Bold", 36)
  17 w, h, b = ps.textsize(title)
  18 ps.text((4*72-w/2, 1*72-h), title) 
  19 
  20 ps.end_document()

9. 更多关于读取图像

前面叙述过,Image模块的open函数用来打开一个图像文件。在大多数情况,你只用简单的把文件名传给它就可以了:

   1 im = Image.open("lena.ppm")

如果一切正常,结果是一个Image 对象。否则,会抛出一个IOError 异常。

你可以使用一个类似文件的对象来代替文件名。这个对象必须实现read、 seek 和 tell 方法,并以二进制方式打开。 从一个打开的文件读取

   1 fp = open("lena.ppm", "rb")
   2 im = Image.open(fp)

要从字符串数据中读取一幅图像,可以使用StringIO 类: 从一个字符串读取

   1 import StringIO
   2 
   3 im = Image.open(StringIO.StringIO(buffer))

注意库在读取图像头之前,会先移动到文件头 (用seek(0))。另外,在图像数据被读取 (通过 load 方法)以后,seek方法也会被调用。如果图像文件被嵌在一个更大的文件里面,比如tar文件,你可以使用ContainerIO 或者TarIO 模块来访问它。 从一个tar压缩文档读取

   1 import TarIO
   2 
   3 fp = TarIO.TarIO("Imaging.tar", "Imaging/test/lena.ppm")
   4 im = Image.open(fp)

9.1. 控制解码器

一些解码器允许你在从文件读取图像的同时对图像进行操作。这个特性常常被用来在创建缩略图(创建缩略图的速度通常比缩略图的质量更重要)或者打印到一个黑白激光打印机(只需要图像的灰度信息)时加速图像的解码。

draft 方法能够操作一个没有被载入数据的图像对象,使得它能够尽可能与需要的模式和大小相匹配。这通过重新配置图像解码器来实现。 以草稿方式读取

im = Image.open(file) print "original =", im.mode, im.size

im.draft("L", (100, 100)) print "draft =", im.mode, im.size

这个程序可能会打印出这样的结果:

original = RGB (512, 512) draft = L (128, 128)

注意,最终获得图像可能与要求的模式和大小不完全一致。如果要求生成的图像不能超过给定的大小,可以使用thumbnail方法来代替。

PythonImageLibrary中文手册 (2008-02-23 15:35:12由localhost编辑)

ch3n2k.com | Copyright (c) 2004-2020 czk.