PIL(Python Imaging Library)图像处理库教程
- open()函数,该库根据文件的内容自动确定格式,除非确实需要,否则库不会解码或加载栅格数据。
open()将读取文件头以确定文件格式并提取解码文件所需的模式、大小和其他属性等内容,但文件的其余部分直到稍后才会处理。
即open()打开图像文件是一项快速操作,它与文件大小和压缩类型无关。
- save()方法,保存文件时,名称很重要。除非指定格式,否则库将使用文件扩展名来发现要使用的文件存储格式
- show()的标准版本不是很有效,因为它将图像保存到临时文件并调用实用程序来显示图像,依赖于已经安装的其他图片查看工具
- convert()在不同像素表示之间转换图像,图片格式转换,B,G,R,L通道等转换 split merge 通道分离及合并
- thumbnails创建缩略图
- crop(), paste()剪切粘贴合并图像
- transpose()翻转图像
- roll()翻转 图像滚动拼接
- 图像类包含resize()和rotate(),前者采用元组给出新大小,后者采用逆时针方向的角度(以度为单位);
- transpose()翻转平移
- 创建MASK imout = im.point(lambda i: expression and
255)
- ImageEnhance调整对比度,亮度,色彩平衡和清晰度( contrast, brightness, color
balance and sharpness)。
- PIL包含对图像序列(也称为动画格式)的一些基本支持。支持的序列格式包括 FLI/FLC、GIF 和一些实验格式。TIFF文件还可以包含多个帧;
当打开序列文件时,PIL会自动加载序列中的第一帧。可以使用seek和tell不同帧之间移动;
读取动图并遍历每一帧展示,seek,tell或者ImageSequence.Iterator(im)
- 图像文本图形等绘制
- draft()方法操作已打开但尚未加载的图像,使其尽可能接近给定的模式和大小。这是通过重新配置图像解码器来完成的
draft()草稿模式下的阅读仅适用于 JPEG 和 MPO 文件
draft()生成的图像可能与请求的模式和大小不完全匹配。若要确保图像不大于给定大小,请改用缩略图thumbnails方法;
源码
import os
import sys
from pathlib import Path
from urllib.request import urlopen
from PIL import Image, TarIO
from PIL import ImageEnhance
from PIL import ImageFilter
from PIL import ImageSequence
from PIL import PSDraw
def readSave():
im = Image.open("ml.jpg")
url = "https://python-pillow.org/images/pillow-logo.png"
img = Image.open(urlopen(url))
fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
im = Image.open(fp)
print(im.format, im.size, im.mode)
im.show()
def convert(infile):
f, e = os.path.splitext(infile)
outfile = f + ".jpg"
if infile != outfile:
try:
with Image.open(infile) as im:
im.save(outfile)
except OSError:
print("cannot convert", infile)
def thumbnails(infile):
size = (128, 128)
outfile = os.path.splitext(infile)[0] + ".thumbnail"
if infile != outfile:
try:
with Image.open(infile) as im:
im.thumbnail(size)
print("thumbnail =", im.mode, im.size)
im.save(outfile, "JPEG")
im.show()
except OSError:
print("cannot create thumbnail for", infile)
def identify():
print(sys.argv)
print(sys.argv[1:])
for infile in sys.argv[1:]:
try:
with Image.open(infile) as im:
print(infile, im.format, f"{im.size}x{im.mode}")
except OSError:
pass
def crop(infile):
im = Image.open(infile)
box = (100, 100, 400, 400)
region = im.crop(box)
region.show()
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)
im.show()
def roll(im, delta):
"""横向滚动图像"""
xsize, ysize = im.size
print(xsize, ysize)
delta = delta % xsize
print(delta)
if delta == 0:
return im
part1 = im.crop((0, 0, delta, ysize))
part2 = im.crop((delta, 0, xsize, ysize))
im.paste(part1, (xsize - delta, 0, xsize, ysize))
im.paste(part2, (0, 0, xsize - delta, ysize))
im.show()
def merge(im1, im2):
w = im1.size[0] + im2.size[0]
h = max(im1.size[1], im2.size[1])
im = Image.new("RGBA", (w, h))
im.paste(im1)
im.paste(im2, (im1.size[0], 0))
im.show()
def mergeSplit(im):
r, g, b = im.split()
r.show()
g.show()
b.show()
im = Image.merge("RGB", (r, g, b))
im.show()
def geometricalTransform(im):
out = im.resize((128, 128))
out.show()
out = im.transpose(Image.ROTATE_270)
out.show()
l = im.convert("L")
l.show()
def fil(im):
out = im.filter(ImageFilter.DETAIL)
out.show()
out = im.point(lambda i: i * 1.2)
out.show()
def createMask(im):
source = im.split()
R, G, B = 0, 1, 2
mask = source[R].point(lambda i: i < 100 and 255)
mask.show()
out = source[G].point(lambda i: i * 0.7)
out.show()
source[G].paste(out, None, mask)
im = Image.merge(im.mode, source)
im.show()
def enhancement(im):
enh = ImageEnhance.Contrast(im)
enh.enhance(1.3).show("30% more contrast")
def imageSequence(infile):
with Image.open(infile) as im:
im.seek(1)
try:
while 1:
print('--: ', im.tell() + 1)
im.seek(im.tell() + 1)
im.show()
except EOFError:
pass
def readGif(infile):
im = Image.open(infile)
for i, frame in enumerate(ImageSequence.Iterator(im)):
print(i)
frame.show()
def drawPostScript(infile):
with Image.open(infile) as im:
title = "hopper"
box = (1 * 72, 2 * 72, 7 * 72, 10 * 72)
ps = PSDraw.PSDraw()
ps.begin_document(title)
ps.image(box, im, 75)
ps.rectangle(box)
ps.setfont("HelveticaNarrow-Bold", 36)
ps.text((3 * 72, 4 * 72), title)
ps.end_document()
im.show()
im.show()
def compress_image(source_path, dest_path):
with Image.open(source_path) as img:
if img.mode != "RGB":
img = img.convert("RGB")
img.save(dest_path, "JPEG", optimize=True, quality=80)
def batchProcess():
paths = Path(".").glob("*.png")
for path in paths:
compress_image(path, path.stem + ".jpg")
def draft(file):
print(file)
with Image.open(file) as im:
print("original =", im.mode, im.size)
im.draft("L", (100, 100))
print("draft =", im.mode, im.size)
infile = '0_viz_float64.png'
infile = 'ml.jpg'
im = Image.open(infile)
im2 = Image.open('ml.jpg')
convert(infile)
thumbnails(infile)
identify()
crop(infile)
roll(im, 540)
merge(im, im2)
mergeSplit(im)
geometricalTransform(im)
fil(im)
createMask(im)
enhancement(im)
gif = 'detect_bright_spots.gif'
imageSequence(gif)
readGif(gif)
drawPostScript(infile)
draft(infile)
参考
- https://pillow.readthedocs.io/en/stable/handbook/tutorial.html