通过Pillow库,可以方便的使用python程序对图片进行处理,例如常见的尺寸、格式、色彩、旋转等
安装pillow
pip install pillow
图像处理的基本知识
图像的RGB色彩模式
RGB三个颜色通道的变化和叠加得到的各种颜色,其中
-R红色,取值范围 0~255
-G绿色,取值范围0~255
-B蓝色,取值返回0~255
比如,我们常见的黄色就是由红色和绿色叠加起来的
红色的RGB表示(255,0,0) 绿色的RGB表示(0,255,0)
蓝色的RGB表示(0,0,255) 黄色的RGB表示(255,255,0)
像素阵列
数字图像可以看成一个整数阵列,阵列中的元素称为像素(Pixel)
每个点代表1个像素,一个点包含RGB三种颜色。也就是1个像素包含3个字节的信息:(R,G,B)假如这个像素是红色,则信息时:(255,0,0)。那么理论上我们只要操作每个点上的三个数字,就能实现任何图形,一幅图像上的所以偶像素点的信息就完全可以采用矩阵来表示,通过矩阵实现的运算实现跟家复杂的操作
Image模块
打开新建open(fp,mode)
- fp:指打开文件的路径
- mode:可选参数,表示打开文件的方式,通常默认为r | mode(模式) | bands(通道) | 说明 | | —- | —- | —- | | “1” | 1 | 数字1,表示黑白二值图像,每个像素用0或1共1位二进制代码表示 | | “L” | 1 | 灰度图。每个像素用8位二进制代码表示 | | “P” | 1 | 索引图,每个像素用8位二进制代码表示 | | “RGB” | 3 | 24位真彩图,每个像素用3个字节的二进制代码表示 | | “RGBA” | 4 | “RGB”+透明通道表示,每个像素用4个字节的二进制代码表示 | | “CMYK” | 4 | 印刷模式图像,每个像素用4个字节二进制代码表示 | | “YCbCr” | 3 | 彩色视频颜色隔离模式,每个像素用3个字节的二进制代码表示 | | “LAB” | 3 | lab颜色空间,每个像素用3个字节的二进制代码表示 | | “HSV” | 3 | 每一个像素用3个字节的二进制代码表示 | | “I” | 1 | 使用整型形式表示像素,,每个像素用4字节的二进制代码表示 |
![image.png](https://cdn.nlark.com/yuque/0/2022/png/1315343/1653686331424-3c7ad8a6-d4a4-4cd0-8aed-1d3933ea95e0.png#clientId=u29dba2da-3fa1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=401&id=uc8729e52&margin=%5Bobject%20Object%5D&name=image.png&originHeight=501&originWidth=1330&originalType=binary&ratio=1&rotation=0&showTitle=false&size=59213&status=done&style=shadow&taskId=uf45857a0-b9aa-4706-87d1-372d5eec5b6&title=&width=1064)
from PIL import Image
#打开图片
img=Image.open('01.jpg')
#图片显示
img.show()
print('图片格式',img.format)
print('图片的大小',img.size)
print('图片的高度',img.height,'图片宽度',img.width)
print('获取(100,100)像素值:',img.getpixel((100,100)))
混合
透明度混合处理blend(im1,im2,alpha)
其中im1、im2指参与混合的图片1与图片2,alpha指混合透明度,取值是0-1
通过使用函数blend()可以将im1和im2这两幅图片(尺寸相同),以一定的透明度进行混合。
(im1*(1-alpha)+im2*alpha)
当混合透明度为0时,显示im1图片。当混合透明度alpha取值为1时,显示im2原图片
from PIL import Image
img1=Image.open('01.jpg')
img2=Image.new('RGB',img1.size,'red').convert(mode='RGB')
Image.blend(img1,img2,alpha=0.2).show()
from PIL import Image
img1=Image.open('01.jpg')
img2=Image.open('02.jpg')
img1=img1.resize(img2.size)
r,g,b=img2.split()
Image.composite(img1,img2,b).show()
复制和缩放
- 复制图像
在Pillow库和Image模块中,可以使用函数Image.copy()复制指定的图片,用于在处理和粘贴时需要持有源图片
- 缩放像素
在Pillow库中Image模块中,可以使用函数eval()实现像素缩放处理,能够使用函数fun()计算输入图片的每个像素并返回。使用eval()语法格式如下:
eval(image,fun)
其中image表示输入的图片,fun表示给输入的图片每个像素应用次函数,fun()函数只允许接收一个整型参数。如果一个图片含有多个通道,则每个通道都会应用这个函数
from PIL import Image
#按图片缩放图片
img1=Image.open('02.jpg')
Image.eval(img1,lambda x:x*2).show()
- 缩放尺寸
Image.thmbnail(size,resample=3)
粘贴和裁剪
- 粘贴
Image.paste(im,box=None,mask=None)
其中im是源图或元素值,box是粘贴的区域,mask是遮罩。参数box可以分为以下三种情况
- (x1,y1):将源图像左上角对齐(x1,y1)点,其余超出粘贴区域被抛弃
- (x1,y1,x2,y2):源图像与此区域必须一致
- None:源图像与被粘贴的图像大小一致
- 裁剪图像
在Pillow库的Image模块中,函数crop()功能是剪切图片中的box指定的区域
Image.crop(box=None)
参数box是一个四元组,分别定义了剪切区域的左、上、右、下4个坐标
from PIL import Image
img=Image.open('02.jpg')
#复制
imgb=img.copy()
imgc=img.copy()
#剪切
img_crop=imgb.crop((10,10,200,200))
imgc.paste(img_crop,(150,150))
imgc.show()
图像旋转
在pillow库中的Image模块中,函数rotate()功能返回此图像的副本,围绕其中心逆时针旋转给定的度数
Image.rotate(angle,raesample=0,expand=0,center=None,tanslate=None,fillcolor=None)
格式转换
- covert()
在Pillow库中的Image模块中,函数conver()返回模式转换后的图像实例Image.covert(mode=None,matrix=None,dither=None,palette=0,colors=256)
其中mode:转换文件的模式,默认支持的模式有“L”、“RGB”、“CMYK”;matrix:
转使用的矩阵;dither:取值为None切转为黑白图时非0(1-255)像素均为白,也可以设置此参数为FLOYDSTEINBERG
- transpse()
实现图像格式的转化
Image.transpose(method)
转换图像后,返回转换后的图像,“method”的取值有以下几个:
- PIL.Image.FLIP_LEFT_RIGHT:左右镜像
- PIL.Image.FLIP_TOP_BOTTOM:上下镜像
- PIL.Image.ROTATE_90:旋转90
- PIL.Image.ROTATE_180:旋转180
- PIL.Image.ROTATE_270:旋转270
- PIL.Image.TRANSPOSE:颠倒顺序
分离和合并
- 分离
使用split()可以将图片分割为多个通道列表Image.split()
- 合并
使用函数merge()可以将一个通道的图像合并到更多的通道的图像中
Image.merge(mode,bands)
其中mode指定输出图像的模式,bands波段通道,一个序列单个带图通道
from PIL import Image
img1=Image.open('01.jpg')
img2=Image.open('02.jpg')
img2=img2.resize(img1.size)
r1,g1,b1=img1.split()
r2,g2,b2=img2.split()
temp=[r1,g2,b1]
img=Image.merge('RGB',temp)
img.show()
滤镜
在Pillow库中的Image模块中,使用函数filter()可以对指定的图片使用滤镜效果,在Pillow库中可以用的滤镜保存在ImageFilter模块中
Image.filter(filter)
from PIL import Image,ImageFilter
img=Image.open('02.jpg')
w,h=img.size
img_output=Image.new('RGB',(2*w,h))
img_output.paste(img,(0,0))
img.filter=img.filter(ImageFilter.GaussianBlur)
img_output.paste(img.filter,(w,0))
img_output.show()
其他内置模块
常用的属性
- Image.format:源图像格式
- Image.mode:图像模式字符串
- Image.size:图像尺寸
在Pillow库中的Image模块中,其他内置函数如下:
- Image.getbands():获取图像每个通道的 名称列表,例如RGB图像返回[‘R’,‘G’,‘B’]
- Image.getextrema():获取图像最大、最小像素的值
- Image.getpixel(xy):获取像素点值
- Image.histogram(mask=None,extrema=None):获取图像直方图,返回像素计数的列表
- Image.point(function):使用函数修改的每个像素
- Image.putaoha(alpha):添加或替换图像的alpha层
- Image.save(fp,formal=None,**params):保存图片
- Image.show(title=None,command=None):显示图片
- Image.transform(size,method,data=None,resample=0,fill=1):变换图像
- Image.verify():校验文件是否损坏
- Image.close():关闭文件
ImageFilter模块
BLUE:模糊
CONTOUR:轮廓
DETAIL:详情
EDGE_ENHANCE:边缘增强
EDGE_ENHANCE_MORE:边缘更多增强
EMBOSS:浮雕
FIND_EDGES:寻找边缘
SHARPEN:锐化
SMOOTH:平滑
函数名 | 功能 |
---|---|
ImageFilter.GaussianBlur(radius=2) | 高斯模糊 |
ImageFilter.UnsharpMask(radius=2,parcent=150,threshold=3) | 不清晰的掩模滤镜 |
ImageFilter.MinFilter(size=3) | 最小值滤波 |
ImageFilter.MedianFilter(size=3) | 中值滤波 |
ImageFilter.ModeFilter(size=3) | 模式滤波 |
ImageChops模块
pillow库中内置模块ImageChops中包含了用于实现图片合成的函数,这些合成的功能是通过计算通道中的像素值的方式来实现的,其主要用于制作特效、合成图片等操作
- 相加函数add(),功能是对两张图片进行加法运算
ImageChop.add(img1,img2,scale=1.0,offset=0)
在合成后图像中的每个像素值,是两幅图像对应像素值根据下面的公式计算得到的out=((img1+img2)/scale+offset)
- 减法函数subtract()
ImageChop.subtract(img1,img2,scale=1.0,offset=0)
在合成后图像中的每个像素值,是两幅图像对应像素值根据下面的公式计算得到的out=((img1-img2)/scale+offset)
- 变暗函数darker(),功能是比较两个图片的像素,取两张图片中对应的较小值,所以合成时两幅图像中对应位置的暗部分得到保留,而除去亮部分
ImageChops.darker(img1,img2)
计算公式如下:out=min(img1,img2)
- 变亮函数与darker()相反,取亮的部分
ImageChops.lighter(img1,img2)
计算公式如下:out=max(img1,img2)
- 叠加函数multiply(),功能是将两张图片互相叠加,如果用纯黑色与某图片进行叠加操作,就会得到一幅纯黑的图片。如果用纯白色图片叠加则不受影响
ImageChops.multiply(img1,im2)
计算公式如下:
out=image1*image2/MAX
- 屏幕函数screen(),功能是先反色后叠加,实现合成图像的效果。
ImageChops.screen(img1,img2)
计算公式如下out=MAX-((MAX-image1)*(MAX-image2)/MAX)
- 反色函数invert(),类似于集合操作中求补集,最大值为Max,取出反色,在反色时将用255减去一幅图像的每个像素值,从而得到原来图像的反色,表现为“底片”的性质图像
ImageChops.invert(img)
计算公式如下:out=MAX-img
- 比较函数difference(),可以逐像素做减法操作,计算出绝对值。difference()能够两幅图像的对应像素值相减后的图像,对应像素值相同的,则为黑色。
ImageChops.difference(img1,img2)
计算公式如下:out=abs(img1-img2)
ImageEnhance模块
内置ImageEnhance模块包含多个用于增强图像效果的函数,主要用来调整图像的色彩、对比度、亮度和清晰度。
在ImageEnhance中,所有的图片增强对象都实现一个通用接口。这个接口只包含如下一个方法:
方法enhance()会返回一个增强Image对象,参数factor是一个大于0的浮点数,1表示返回原始图片
在Python中使用模块ImageEnhanced增强效果时,需要首先创建对应的增强调整器,然后调用调整器,根据指定的增强系数(小于1表示减弱,大于1表示增强,等于1表示原图不变)进行调整,最后输出调整后的图像
- ImageEnhanced.Color(image)功能是调整图像色彩平衡。
- ImageEnhanced.Brightness(images):功能时调整图像对比度
- ImageEnhancedSharpness(images):调整图像的清晰度,用于锐化/钝化图片
锐化操作的factor时0~2之间的一个浮点数,当factor=0时,返回一个模糊图片对象,当factor=2时,返回一个锐化的图片对象,当factor=1时,返回原始图片对象
from PIL import Image,ImageEnhance
img=Image.open('01.jpg')
w,h=img.size
img_output=Image.new('RGB',(3*w,h))
img_output.paste(img,(0,0))
#获取色彩调整器
img_color=ImageEnhance.Color(img)
imgb=img_color.enhance(1.5)
img_output.paste(imgb,(w,0))
imgc=img_color.enhance(0.3)
img_output.paste(imgc,(2*w,0))
img_output.show()
from PIL import Image,ImageEnhance
img=Image.open('01.jpg')
w,h=img.size
img_output=Image.new('RGB',(3*w,h))
img_output.paste(img,(0,0))
#获取亮度调整器
img_color=ImageEnhance.Brightness(img)
imgb=img_color.enhance(1.5)
img_output.paste(imgb,(w,0))
imgc=img_color.enhance(0.3)
img_output.paste(imgc,(2*w,0))
img_output.show()
from PIL import Image,ImageEnhance
img=Image.open('01.jpg')
w,h=img.size
img_output=Image.new('RGB',(3*w,h))
img_output.paste(img,(0,0))
imgb=img.point(lambda i:i*1.4)
imgc=img.point(lambda i:i*0.3)
img_output.paste(imgb,(w,0))
img_output.paste(imgc,(2*w,0))
img_output.show()
ImageDraw模块
实现绘图功能,可以在创建图片的方式,还可以在原有的图片上进行绘制
drawObject=ImageDraw.Draw(black)
- 绘制直线
drawObject.line([x1,y1,x2,y2],fill=None,width=0,joint=None)
表示以(x1,y1)为起始点,以(x2,y2)为终点画的一条直线,[x1,y1,x2,y2]也可写成(x1,y1,x2,y2)、[(x1,y1),(x2,y2)]等,fill用于设置指定线条颜色,width设置线条的宽度,joint表示一系列之间的联合类型,它可以称为“曲线”
- 绘制圆弧
drawObject.arc([x1,y1,x2,y2],start,end,fill=None,width=0)
在左上坐标(x1,y1),右下角坐标为(x2,y2)的矩形区域内,满员O内,以start为起始角度,以end为终止角度,截取园O的一部分圆弧并画出来。如果[x1,y1,x2,y2]区域不是正方形,则在该区域内的最大椭圆中根据角度截取片段
参数fill和width与line方法相同
- 绘制椭圆
drawObject.ellipse([x1,y1,x2,y2],fill=None,outline=None,width=0)
outline规定圆的颜色
- 绘制弦
drawObject.chord([x1,y1,x2,y2],start,end,fill=None,outline=None,width=0)
fill表示弦与圆弧之间空间指定颜色填满,设置outline表示只规定弦线的颜色
- 绘制扇形
drawObject.pieslice([x1,y1,x2,y2],start,end,fill=None,outline=None,width=0)
- 绘制矩形
drawObject.rectangle([x1,y1,x2,y2],start,end,fill=None,outline=None,width=0)
- 绘制文字
drawObject.text(position,text,fill=None,font=None,anchor=None,sapacing=0,align="left",direction=None,features=None,language=None)
- 绘制点
drawObject.point(xy,fill=None)
from PIL import Image,ImageDraw,ImageFont
img=Image.new('RGB',(300,200),'white')
draw_obj=ImageDraw.Draw(img)
draw_obj.rectangle((50,50,150,150),fill='blue',outline='red')
font=ImageFont.truetype('SIMLI.TTF',20)
draw_obj.text((100,100),'aaa',fill='white',font=font)
img.show()
from PIL import Image,ImageDraw
img=Image.open('01.jpg')
width,height=img.size
draw_obj=ImageDraw.Draw(img)
draw_obj.arc((0,0,width-1,height-1),0,360,fill='blue')
img.show()
ImageFont模块
对字体和字型做处理
- load(),从指定文件中加载一种字体,该函数返回对应的字体对象。如果函数运行失败,那么将产生IOerror异常
ImageFont.load(文件名)
- load_path():和load()一样,如果没有指定当前路径,就会从文件sys.path开始查找指定的字体文字
ImageFont.load_path(文件名)
- truetype()有两种定义格式,第1种格式功能是加载一个TrueType或者OpenType字体文件,并且创建一个字体对象
ImageFont.trueType(file,size)
第2种是加载一个TrueType或者OpenType字体文件,并创建一个字体对象。通常编码方式是“unic”(Unicode)、“symb”(MicroSoftSymbol)、“ADOB”(Adobe Standard)、“ADBE”(Adobe Expert)和“armn”(Apple Roman)ImageFont.trueType(file,encoding=value)
- load_default(),加载一种默认的字体
ImageFont.load_default()
- getsize()返回给定文本的宽度和高度,返回值是一个二元组
ImageFont.getsize
from PIL import Image,ImageFont,ImageDraw
img=Image.open('01.jpg')
draw_obj=ImageDraw.Draw(img)
font=ImageFont.load_default()
font=ImageFont.truetype('SIMYOU.TTF',80)
draw_obj.text((30,30),'wefwdef',font=font,fill='black')
img.show()
from PIL import Image,ImageDraw
img=Image.open('01.jpg')
draw_obj=ImageDraw.Draw(img)
w,h=img.size
draw_obj.line((0,0,w,h),fill=(255,255,0),width=3)
draw_obj.line((0,h,w,0),fill=(255,255,0),width=3)
img.show()
from PIL import Image,ImageDraw,ImageFont
import random
width,height=100,100
img=Image.new('RGB',(width,height),(255,255,255))
#获取draw_obj对象
draw_obj=ImageDraw.Draw(img)
def get_color():
return (random.randint(200,255),random.randint(200,255),random.randint(200,255))
for x in range(height):
for y in range(height):
draw_obj.point((x,y),fill=get_color())
def get_char():
return chr( random.randint(65,97))
font=ImageFont.truetype('simsun.ttc',36)
for i in range(4):
draw_obj.text((10+i*20,40),get_char(),font=font,fill=(255,0,0))
draw_obj.line((0,0,100,100),fill='green',width=5)
img.show()
from PIL import Image,ImageDraw
width,height=300,300
img=Image.new('RGB',(width,height),(255,255,255))
draw_obj=ImageDraw.Draw(img)
def get_color(x,y):
a=x//100+y//100
if a==0:
return (255,0,0)
elif a==1:
return (255,255,0)
elif a==2:
return (255,255,255)
elif a==3:
return (0,0,255)
elif a==4:
return (0,255,255)
else:
return (0,0,0)
for x in range(width):
for y in range(height):
draw_obj.point((x,y),fill=get_color(x,y))
img.show()