马上注册,结交更多好友,享用更多功能,让你轻松玩转新大榭论坛!
您需要 登录 才可以下载或查看,没有账号?注册
x
概述
+ d6 D$ q! J. Q( b' O% T! \) w" `, NPIL库主要用途+ f( |. g! M9 ^0 s) L9 Y& o
- 图像存储
% t/ H) H& G" n4 TPIL适合图像归档和图像批量处理,你可以使用它建立缩略图,转换格式,打印图片等。: n( K; ~* y: M
现在的版本可以识别和读取大量的图片格式,写入常用的转换和表示格式。 - 图像显示6 k/ i! J! ?1 I. w; Q9 i
支持多个其他工具包的展示,提供了show() 方法,可以保存图像到磁盘并调用外显示。它将图像保存到磁盘,并调用外部显示工具。 - 图像处理(重点)" g; A% X) v4 C5 s( z2 s
包含了基本的图像处理功能,包括点操作,使用内置卷积内核过滤,色彩空间转换。
8 M9 p! o0 A0 [7 j支持更改图像大小、旋转、任意仿射变换。3 i% F% C( x5 ?9 `" U2 S5 {$ m8 j
" k) g4 h. y9 }
教程: f+ n5 S1 [. Y1 k
注意:PIL导包是用的 from PIL import Image,但是安装的时候并不是这个库名,小伙伴执行下面的PIL安装命令即可,正确的包名为:Pillow,执行下面语句安装即可,出现版本号表示安装成功: 1. 使用 Image 类
- W' V3 x3 {6 `- uImage 是 PIL 中最重要的类,用于从文件加载图像、处理其他图像、从 scratch 创建图形等:
2 W! I( D: o* q* p* J" @' f* q$ C/ v6 _
1.1 加载图像
' I# A4 J6 o* M. q7 b. t6 L2 J; e4 B从文件加载图像,若打开错误返回 IOError:
6 @2 x& b. _3 ?) C7 j+ ] }- from PIL import Image
5 e- E: s! T4 ]0 y/ I& V - im = Image.open('lena.ppm')
复制代码 从打开的文件中读取- with open("hopper.ppm", "rb") as fp:
( ~% f+ m; x& } N0 W - im = Image.open(fp)
复制代码 如果是从二进制流中读取,则需要先通过 io 转换成文件流,或者使用 StringIO
# g, B( r* F* z# M4 d1 E- import io
3 L! k0 A. U. X' x - im = Image.open(io.BytesIO(buffer))
0 s0 }0 a* n, v: C$ ?$ X - import StringIO$ Z- D9 t1 f/ ^- M: _/ u4 ^7 S
- im = Image.open(StringIO.StringIO(buffer))
复制代码 从tar档案中读取' Z7 a8 n# ^" X9 h
- from PIL import Image, TarIO* q& U0 y6 }4 ^4 @" d7 f0 T
4 I- \; f8 i6 k7 o. T# P( G- fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
* j! { w) v ] - im = Image.open(fp)
复制代码 * o m& I1 T0 L- y
1.2 图片属性
7 Y: e+ e: P4 m9 S# M成功加载后会返回一个 Image 对象,可观察以下属性:/ a$ ~4 R9 G! r+ G! Y0 h! o
format: 判断图片来源,即 ppm/png 等 (若不是从文件读取则返回 None);
0 H! [: f% o% _6 M, v5 qsize: 查看宽度和高度(二元组 tuple,单位是 px );
7 X& r/ }# F5 t6 C/ P, Imode: 定义图像波段数与名称(像素类型和深度),常见有 L 灰度图像,RGP 真彩色图像, CMYK 出版图像) s2 J7 ^ Q7 G
- print(im.format, im.size, im.mode)
% v8 h0 l. h. Y2 j* \1 B* V2 u - # PPM (512, 512) RGB
复制代码 . y, I" D/ v" Z& } S6 P' _
1.3 图片显示- # 自带方法:
6 P- a" \- _! _- I1 s - im.show()
# s ]4 g6 c: t0 p% L - # 使用 matplotlib 显示:
" }' E ?3 n, L1 u( ?* N( Y! a5 j - import matplotlib.pyplot as plt
9 `$ f+ G: F3 X) ~ - plt.imshow(im)
% U, p# ]& F+ s# O9 M - plt.show()
复制代码
* I8 M2 H9 a) v4 y* V1.4 读写图像
. n1 X/ |3 Z5 d2 N! ~, @/ kPIL 库支持大量图片格式。使用 Image 模块的 open() 函数从磁盘读取文件。你不需要知道文件格式就能打开它,PIL 能够根据文件内容自动确定确定文件格式。
4 A1 @0 @" y+ u, H! M; f$ ~2 Y
5 s. ]; B( _' B+ U0 I保存文件时使用 Image 类的 save() 方法。此时文件名就变得重要,除非你指定格式,PIL 将会以文件名的扩展名作为格式保存。save() 方法的第二个参数可以指定文件格式,如果你使用非标准的扩展名你必须这样做。- # 转换文件为JPEG:2 ]8 B4 a/ z8 D6 R
- import os, sys
1 t. N( t) Q( \5 e' k& o! K - from PIL import Image1 y. [! @" L# W6 H5 `
$ G. ?+ L1 b2 _5 I% ~& H- for infile in sys.argv[1:]:9 h, J( ^: }+ p7 O) j5 P2 O
- f, e = os.path.splitext(infile)
" R4 `! c% T5 }( ^4 I2 p - outfile = f + ".jpg"( R `3 K0 h8 \5 K) R# h
- if infile != outfile:, `) G6 z4 r/ J0 V4 w9 N! A
- try:5 J3 Q3 g6 _$ |2 K" O3 }
- Image.open(infile).save(outfile)
! l3 g' F1 r3 @& [; ~# F, z, [ - except IOError:
/ o% S- q* \, R/ N6 ~ - print("cannot convert", infile)
4 i* `5 ]4 A! A8 L& x6 N- E" s! J
9 V4 [8 S1 [/ r$ Q1 G
复制代码 # C, q `9 w, I& y. |
2. 图像处理) U0 G: h4 {: B1 [
2.1 剪切、粘贴、合并图像* j. J0 d7 f5 ?. `! U
crop():从图像中提取子矩形。box 坐标分别是(左,上,右,下)的位置,下例取出的是 300*300 像素的矩阵" T( F j( B. j; e( _: K0 S5 B
- box = (100, 100, 400, 400)
X) _' k2 W. ^ Q' L - region = im.crop(box)
复制代码 paste():粘贴;粘贴区域是大小必须完全匹配,但模式不需要匹配(模式在粘贴时会自动转换)。粘贴时可以选择透明度,0 对应完全透明,255 对应不透明(默认)。
4 W$ f. g e) O% I4 B- region = region.transpose(Image.ROTATE_180) # 旋转180度( k+ D7 c, t2 ~0 _7 @' A
- im.paste(region, box)
复制代码 实例:滚动图像,使图像循环向左滚动(即将左边一小节一直粘贴到图像的右边)$ n% w; C3 \. ^! B
- from PIL import Image3 @) _* n7 n2 h3 k+ E" ~
- ; Z& @ n2 J8 v( o% i4 M
- def roll(image, delta):/ y2 F. _/ r6 ?/ A. d! U
- """Roll an image sideways."""
: C _( q& Y, k3 H5 B3 S- U - xsize, ysize = image.size, E/ {1 w% Z5 O" g; s- p
: y) p" b0 e6 ~( [- delta = delta % xsize# W3 I( ~% R1 t( i. g; }5 }
- if delta == 0: return image
8 ~% k- c |, ?9 |' s o: d6 W
6 N g+ s; f5 K0 j% v7 a, G8 p- part1 = image.crop((0, 0, delta, ysize))
% I+ x2 ^ i* o; E2 Q - part2 = image.crop((delta, 0, xsize, ysize))
6 O) k0 e* s9 P; F5 c q- S - part1.load()
r2 {; l( @8 R* `% V - part2.load()7 H, w9 ^' ~& Q% I
- image.paste(part2, (0, 0, xsize-delta, ysize))1 y+ z3 l5 i, S6 }
- image.paste(part1, (xsize-delta, 0, xsize, ysize))! u# Q0 I7 D0 m' S2 a
e+ Q" V4 W/ F- return image) B' R# n" L. q, H, {
- $ \4 d7 Y l! m: R. c/ `
- im = Image.open("demo.jpg")2 \. K t1 p8 h2 h" [$ @1 F
- im = roll(im,100)
5 ?% p P: Q2 Y; X* O/ L( z - im.show()
复制代码 split():用于对图像进行波段拆分,如针对 RGB 图像,拆分后将生成3幅单波段图像,对单波段图像则返回本身。
: H, W* G: w. j/ y1 ]8 Omerge():用于将多个波段图像合并成新图像。
: ^. Z$ S: c$ e" P- r, g, b = im.split()* ]; B( H5 m( |& |: k& I4 O
- im = Image.merge("RGB", (b, g, r))
复制代码 / i- k* d |) K5 X" G+ j
2.2 几何变换: c2 ~; r) [# o7 G2 Z2 \
resize():给定目标尺寸元组,对图像进行拉伸或压缩
0 x I( K) |* }rotate():给定旋转角度,对图像进行逆时针旋转/ R: t( l: ~! p: \7 s3 |) J
- out = im.resize((128, 128))! [- ]( I( q' o
- out = im.rotate(45) # degrees counter-clockwise
复制代码 transpose():使用一些固定方法对图像进行变换: s/ T* d* g0 J+ \
- out = im.transpose(Image.FLIP_LEFT_RIGHT)' y: n+ {9 F2 ~* C3 Q
- out = im.transpose(Image.FLIP_TOP_BOTTOM)
- U% \) ]3 A8 M# k4 x - out = im.transpose(Image.ROTATE_90)
8 d3 ]! D6 _7 C' ~) l - out = im.transpose(Image.ROTATE_180)
1 i+ T! a9 O3 Q - out = im.transpose(Image.ROTATE_270)
复制代码 : b- V' T9 W' G) x; U: S, d, k3 L w
2.3 颜色模式转换
% H' k5 B* m' X Xconvert():对图像进行不同颜色模型的转换,如常用的 L 与 RGB 之间的转换;
1 S( }* {# `2 V7 i0 d: n- im = Image.open("hopper.ppm").convert("L")
复制代码
* f3 c; w! k7 c6 B$ Q3. 图像增强1 a/ G, A2 `& u* x
3.1 滤波器7 H8 Q( K2 m7 p9 w- M" w
ImageFilter 模块包含许多可以与 filter() 方法一起使用的预定义滤波器
5 M; m5 Q+ F/ U5 [. p+ u- from PIL import ImageFilter& X( b# k9 H* ~( O2 D
- out = im.filter(ImageFilter.DETAIL)
复制代码 可用滤波器一览,具体效果看BLUR:模糊滤波$ `/ a0 |- G/ v3 p
CONTOUR:轮廓滤波# A9 {0 e* r1 [8 t' E
DETAIL:细节滤波
. k, j& S! [0 H6 H5 MEDGE_ENHANCE:边界增强滤波
" Q, S/ f1 H: [1 bEDGE_ENHANCE_MORE:深度边缘增强滤波9 g7 V9 q+ ^- G! i& I6 e
EMBOSS:浮雕滤波% C& @$ s- s5 t: r* r- f
FIND_EDGES:寻找边界滤波(找寻图像的边界信息)' |5 S# u8 k$ h; |4 @+ L
SMOOTH:平滑滤波8 d8 v; y. n0 l* \* Z; k
SMOOTH_MORE:深度平滑滤波
3 U2 \ v l* n8 y* z ESHARPEN:锐化滤波
2 ^( c8 \& i- i) C* qGaussianBlur:高斯模糊- o' a) z: @. {. O) {1 V# n1 d: f* j
UnsharpMask:反锐化掩码滤波
! [0 K5 c) x5 \' b+ c2 r4 x(radius:模糊半径;percent:反锐化强度(百分比);threshold:被锐化的最小亮度)2 e2 G* H) K! i f8 ^, V
Kernel:卷积核滤波
/ c& }: z" M" t% B(size:核的大小;kernel:核权值序列如33的为;scale:缩放因子;offset:偏移量)9 _8 X8 {8 H n5 y g
RankFilter:排序滤波; u, `; j+ X2 r
(size:核的大小;rank:排序序号)
' d7 g2 C" o& ~Kernel:卷积核滤波
7 v4 F! P0 r+ @+ g; q( ^/ C: j(size:核的大小;kernel:核权值序列如33的为;scale:缩放因子;offset:偏移量)0 ?, h2 J# A u+ ^. |$ s
MinFilter:最小值滤波器0 W5 g4 u3 S$ e4 P) R# x0 G3 v
MedianFilter:中值滤波
3 ?) p6 a5 _ T* Z" b3 D: o5 [MaxFilter:最大值滤波% ~. S) ]# V" s! ?
ModeFilter:模式滤波
s; D" x, g0 |# v' Q3.2 点操作
* H/ {; e+ ?8 Q5 _point() : 方法可用于转换图像的像素值(例如图像对比度操作)。在大多数情况下,期望一个参数的函数对象可以传递给此方法。每个像素都根据该功能进行处理:
" E: _2 a4 _: g; J$ N2 G- # multiply each pixel by 1.27 [8 g' E Y$ E; \6 {) n
- out = im.point(lambda i: i * 1.2)
复制代码 实例:处理单个色带:$ K( ]7 N# L$ F0 T q: Q5 P' r/ e
1. 将 red < 100 赋 0 否则 255;! A- c: z6 {: b/ h4 z$ O, T
2. green 变成原来 0.7 倍- # split the image into individual bands
" ^) b- W' Y4 U2 i - source = im.split(): n5 O+ L3 x6 {6 H, U( ~
- * y3 I! f- }3 k3 F) a) l& [
- R, G, B = 0, 1, 2, [& N+ T& }" v2 M% ?1 k( M
- * h) W4 z; V/ o) I, ?/ O5 X
- # select regions where red is less than 100
4 t% W" A+ P% V h - mask = source[R].point(lambda i: i < 100 and 255)
8 O: B# _- A0 g9 H( C - s" z9 Y) a T* J0 z5 A5 ]& R- x; ?
- # process the green band
( f4 @' ?) w9 l; Q8 q0 Y& s: V& g - out = source[G].point(lambda i: i * 0.7)
. S8 w5 S+ }$ m V. s) a; X- ?& [+ D
" D) ^' s; ^& q9 |0 D- # paste the processed band back, but only where red was < 100" z8 Q% g7 a. A9 h5 I
- source[G].paste(out, None, mask)$ z0 @- p) y$ W+ c
, R1 W! ]$ |8 J# t1 [- # build a new multiband image% x9 p% W5 g+ ^8 \; y |4 R( ]5 C
- im = Image.merge(im.mode, source)! q; i$ D( H* f5 q: U7 X3 p
复制代码 . M' ?; S0 `2 s, x- V/ `8 F
3.3 增强- q5 P( \. o. w
对于更高级的图像增强,您可以使用 ImageEnhance 模块中的类。从图像创建后,可以使用增强对象快速尝试不同的设置。您可以用这种方式调整对比度,亮度,色彩平衡和清晰度。- from PIL import ImageEnhance
* m1 ]" j2 U3 C- y - 8 U m3 n+ t8 ]7 V) L
- enh = ImageEnhance.Contrast(im)$ d r) E8 u9 f* c& |: J6 i6 Y
- enh.enhance(1.3).show("30% more contrast")
复制代码 ! s$ d6 ` S. X
4. 图像序列5 w# ^2 o4 j" ~# \+ Q5 a& W; ~
Python图像库包含对图像序列(也称为动画格式)的一些基本支持。支持的序列格式包括FLI/FLC, GIF和一些实验格式。 TIFF文件也可以包含多个帧。1 P& {. c3 Y) ~3 R( D) \+ B, X' \
当你打开一个序列文件时,PIL自动加载序列中的第一帧。您可以使用 seek 和 tell 方法在不同的帧之间移动。注意当前版本库中的大多数驱动程序只允许您寻找下一帧。要倒回文件,您可能必须重新打开它。2 }% q$ M5 v( J) _8 J
读序列:- from PIL import Image3 J$ I/ N& K/ ?& j0 Z: i$ ]8 @
- 4 j( i" {8 l$ K* l& X" ^
- im = Image.open("animation.gif")
' K9 ^9 ^5 p' m - im.seek(1) # skip to the second frame! G: f$ C/ i5 N# v
- % U6 D2 m& o6 v; ?
- try:' E4 e* F$ f' @1 C
- while 1:' U V6 H0 v; Q' e
- im.seek(im.tell()+1)
) }4 T" G1 L& U% B0 x8 d% H - # do something to im
( [; J$ u" Z7 u - except EOFError:) T% M/ d; h6 ]' F$ n7 z
- pass # end of sequence
复制代码 使用 for 遍历:- ~3 E: Z C7 |: }
- from PIL import ImageSequence
( L! |3 @" b9 y$ x - for frame in ImageSequence.Iterator(im):
$ ~8 O. N/ |/ `; c2 r - # ...do something to frame...
复制代码 》》》待续 ~+ q3 L" @/ g1 C
|
|