目录

【图像处理】Image类基础使用方法

前言

修改自CSDN博客,完整内容见:

Python图像库PIL的类Image及其方法介绍

Image类介绍

Image类是PIL中的核心类,你有很多种方式来对它进行初始化,比如从文件中加载一张图像,处理其他形式的图像,或者是从头创造一张图像等。Image模块操作的基本方法都包含于此模块内。

使用Image类的注意事项

Pillow

由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此,我们可以直接安装使用Pillow。

如果安装了Anaconda,Pillow就已经可用了。否则,需要在命令行下通过pip安装: $ pip install pillow

调用方法

# python2
import Image
# python3
from PIL import Image

智能补全问题

python是动态强类型语言,IDE无法判断Image.open(“file.png”)的返回值类型,无法根据参数类型自动补全。

这个问题有以下解决方法:

  • 类型注释:加上# type: Image.Image
    img = Image.open('file.png') # type: Image.Image
    
  • 使用isinstance进行指定
    img = Image.open('file.png')
    assert isinstance(img, Image.Image)
    
  • 指定类型
    img = Image.open('f15.png')
    """:type: Image.Image"""
    

Image类属性

size

size记录图像的尺寸,按照像素数计算。它的返回值为宽度和高度的二元组(width, height)

<imname>.size -> (width,height)

im = Image.open("3d.jpg")
print(im.size) # 打印图像尺寸

format

format属性标识了图像来源格式,如果图像没有读取文件,它的值就是None

<imname>.format -> string or None

im = Image.open("3d.jpg")
print(im.format) # 打印出格式信息

mode

mode标识图像的模式。

<imname>.mode -> string

im = Image.open("3d.jpg")
print(im.mode) # 打印出模式信息

常见的图像模式如下表:

Modes Description
1 1位像素,黑白图像,存成8位像素
L 8位像素,黑白
P 9位像素,使用调色板映射到任何其他模式
RGB 3*8位像素,真彩
RGBA 4*8位像素,真彩+透明通道
CMYK 4*8位像素,印刷四色模式或彩色印刷模式
YCbCr 3*8位像素,色彩视频格式
I 32位整型像素
F 33位浮点型像素

palette

palette记录颜色调色板表格。如果图像的模式是“P”,则返回Image Palette类的实例;否则,将为None。

<imname>.palette -> palette or None

info

info存储图像相关数据的字典。

文件句柄使用该字典传递从文件中读取的各种非图像信息。大多数方法在返回新的图像时都会忽略这个字典;因为字典中的键并非标准化的,对于一个方法,它不知道自己的操作如何影响这个字典。如果用户需要这些信息,需要在方法open()返回时保存这个字典。

<imname>.info -> dictionary

Image类方法

new

new()使用给定的变量mode和size生成新的图像。

Image.new(mode,size) -> image

Image.new(mode, size,color) -> image

size是给定的宽/高二元组,这是按照像素数来计算的。

对于单通道图像,变量color只给定一个值;对于多通道图像,变量color给定一个元组(每个通道对应一个值)。

在版本1.1.4及其之后,用户也可以用颜色的名称,比如给变量color赋值为"red"。如果没有对变量color赋值,图像内容将会被全部赋值为0(为黑色)。

如果变量color是空,图像将不会被初始化,即图像的内容全为0。这对向该图像复制或绘制某些内容是有用的。

# 创建128*128全红图像
n_im= Image.new("RGB", (128, 128), "#FF0000")

open

要从文件加载图像,使用open()函数:

Image.open(file) -> image

Warning
This is a lazy operation; this function identifies the file, but the file remains open and the actual image data is not read from the file until you try to process the data.
from PIL import Image
im = Image.open('./3d.jpg') # 打开当前路径下的3d.jpg文件
im.show() # 显示图片

save

save()方法可以用于保存文件,使用给定的文件名保存图像:<imname>.save(outfile,format,options)

如果变量format缺省,如果可能的话,则从文件名称的扩展名判断文件的格式。该方法返回为空。

关键字options为文件编写器提供一些额外的指令。如果编写器不能识别某个选项,它将忽略它。用户可以使用文件对象代替文件名称。在这种情况下,用户必须指定文件格式。

文件对象必须实现了seek()tell()write()方法,且其以二进制模式打开。如果方法save()因为某些原因失败,这个方法将产生一个异常(通常为IOError异常)。如果发生了异常,该方法也有可能已经创建了文件,并向文件写入了一些数据。如果需要的话,用户的应用程序可以删除这个不完整的文件。

# save()可以用于转换文件类型
im = Image.open("3d.jpg")
im.save("3d.png") # 将"3d.jpg"保存为3d.png"

getpixel

getpixel()返回给定位置的像素值。

<imname>.getpixel(xy) -> value or tuple

如果图像为多通道,则返回一个元组。该方法执行比较慢;如果用户需要使用python处理图像中较大部分数据,可以使用像素访问对象load(),或者方法getdata()

im = Image.open("3d.jpg")
print(im.getpixel((0,0)))

load

load()为图像分配内存并从文件中加载它(或者从源图像)。正常情况下,用户不需要调用这个方法,因为在第一次访问图像时,Image类会自动地加载打开的图像。

目前的版本,方法load()返回一个用于读取和修改像素的像素访问对象。 这个访问对象像一个二维队列,如:

pix = im.load()
print(pix[x, y]) # 读取pix中的像素
pix[x, y] = value # 修改pix中的像素

getdata

getdata()以包含像素值的sequence对象形式返回图像的内容。

<imname>.getdata() -> sequence

这个sequence对象是扁平的,以便第一行的值直接跟在第零行的值后面,等等。

这个方法返回的sequence对象是PIL内部数据类型,它只支持某些sequence操作,包括迭代和基础sequence访问。使用list(im.getdata()),将它转换为普通的sequence。

sequence对象的每一个元素对应一个像素点的R、G和B三个值。

im = Image.open("3d.jpg")
sequ = im.getdata()
l_sequ = list(sequ)

corp

corp()从当前的图像中返回一个矩形区域的拷贝。

变量box是一个四元组,定义了左、上、右和下的像素坐标,用来表示在原始图像中截取的位置坐标。

box = (100,100,200,200)就表示在原始图像中以左上角为坐标原点,截取一个100*100(像素为单位)的图像,为方便理解,如下为示意图box = (b1,a1,b2,a2)

/pypic/corp.png

im = Image.open("3d.jpg")
box = (20, 30, 300, 200) # 确定拷贝区域大小
region = im.crop(box) # 将im表示的图片对象拷贝到region中,大小为box

copy

copy()可以拷贝这个图像。如果用户想粘贴一些数据到这张图,可以使用这个方法,但是原始图像不会受到影响。

<imname>.copy() -> image

# im_copy和im完全相同
im = Image.open("3d.jpg")
im_copy = im.copy()

paste

paste()将一张图粘贴到另一张图像上。

<imname>.paste(image,box)

变量box或者是一个给定新图片中插入图像所在区域的左上角坐标的2元组,或者是定义了左,上,右和下像素坐标的4元组,或者为空(与(0,0)一样)。

如果给定4元组,被粘贴的图像的尺寸必须与区域尺寸一样。如果模式不匹配,被粘贴的图像将被转换为当前图像的模式。

im = Image.open("3d.jpg")
box=[0,0,100,100]
im_crop = im.crop(box)
im.paste(im_crop, (100,100)) #(100,100)为im用于粘贴im_corp的区域的左上角像素坐标
im.paste(im_crop, (400,400,500,500))

convert

convert()将当前图像转换为其他模式,并且返回新的图像。

<imname>.convert(mode) -> image

当从一个调色板图像转换时,这个方法通过这个调色板来转换像素。如果不对变量mode赋值,该方法将会选择一种模式,在没有调色板的情况下,使得图像和调色板中的所有信息都可以被表示出来。

<imname>.convert(mode,matrix) -> image使用转换矩阵将一个“RGB”图像转换为“L”或者“RGB”图像。变量matrix为4或者16元组。

# 使用P模式转换图像
im = Image.open("3d.jpg")
new_im = im.convert('P')
# 使用自定义矩阵转换图像
im = Image.open("3d.jpg")
rgb2xyz = (0.412453,0.357580, 0.180423, 0,
           0.212671,0.715160, 0.072169, 0,
           0.019334,0.119193, 0.950227, 0 )
new_im = im.convert("L", rgb2xyz)

blend

blend()使用给定的两张图像及透明度变量alpha,插值出一张新的图像。这两张图像必须有一样的尺寸和模式。

Image.blend(image1,image2, alpha) -> image

合成公式为:$out = image1 (1.0 - alpha) + image2 (alpha)$

若变量alpha为0.0,返回第一张图像的拷贝。若变量alpha为1.0,将返回第二张图像的拷贝。对变量alpha的值无限制。

from PIL import Image
im1 = Image.open("3d.jpg")
im2 = Image.open("3dd.jpg")
im = Image.blend(im1, im2, 0.40)

fliter

fliter()返回一个使用给定滤波器处理过的图像的拷贝。

<imname>.filter(filter) -> image

fliter()具体参考图像滤波在ImageFilter模块的应用。在该模块中,预先定义了很多增强滤波器,可以通过filter()函数使用。

预定义滤波器包括:BLUR、CONTOUR、DETAIL、EDGE_ENHANCE、EDGE_ENHANCE_MORE、EMBOSS、FIND_EDGES、SMOOTH、SMOOTH_MORE、SHARPEN。其中BLUR就是均值滤波,CONTOUR找轮廓,FIND_EDGES边缘检测,使用该模块时,需先导入。

from PIL import Image
from PIL import ImageFilter # 调取ImageFilter
imgF = Image.open("3d.jpg")
bluF = imgF.filter(ImageFilter.BLUR) # 均值滤波
conF = imgF.filter(ImageFilter.CONTOUR) # 找轮廓
edgeF = imgF.filter(ImageFilter.FIND_EDGES) # 边缘检测