Python图像处理库PIL的基本操作 & 利用PIL进行图像格式转换

计算机视觉 专栏收录该内容
7 篇文章 0 订阅

一:基本概念

1.1 颜色与RGBA值

       计算机通常将图像表示为RGB值,或者再加上alpha值(通透度,透明度),称为RGBA值。

       在Pillow中,RGBA的值表示为由4个整数组成的元组,分别是R、G、B、A。整数的范围0~255。RGB全0就可以表示黑色,全255代表黑色。可以猜测(255, 0, 0, 255)代表红色,因为R分量最大,G、B分量为0,所以呈现出来是红色。但是当alpha值为0时,无论是什么颜色,该颜色都不可见,可以理解为透明。

from PIL import ImageColor
print(ImageColor.getcolor('red', 'RGBA'))
# 也可以只以RBG的方式查看
print(ImageColor.getcolor('black', 'RGB'))
(255, 0, 0, 255)
(0, 0, 0)

1.2 图像的坐标表示

       图像中左上角是坐标原点(0, 0),这和平常数学里的坐标系不太一样。这样定义的坐标系意味着,X轴是从左到右增长的,而Y轴是从上到下增长。

        在Pillow中如何使用上述定义的坐标系表示一块矩形区域?许多函数或方法要求提供一个矩形元组参数。元组参数包含四个值,分别代表矩形四条边的距离X轴或者Y轴的距离。顺序是(左,顶,右,底)。右和底坐标稍微特殊,表示直到但不包括。可以理解为[左, 右)[顶, 底)这样左闭右开的区间。比如(3, 2, 8, 9)就表示了横坐标范围[3, 7];纵坐标范围[2, 8]的矩形区域。


二:Pillow的安装

pip install Pillow

 

三:Pillow(PIL)简单的图像操作

3.1 使用Pillow操作图像

from PIL import Image

im_path = r'F:\Jupyter Notebook\csv_time_datetime_PIL\rabbit.jpg'
im = Image.open(im_path)
width, height = im.size
# 宽高
print(im.size, width, height)
# 格式,以及格式的详细描述
print(im.format, im.format_description)

im.save(r'C:\Users\Administrator\Desktop\rabbit_copy.jpg')
im.show()
(1920, 1080) 1920 1080
JPEG JPEG (ISO 10918)

    im.size返回一个元组,分别是宽和高。

    show()方法会调用系统默认图像查看软件,打开并显示。

    im.format可查看图像的格式。

    save()可保存处理后的图片,如果未经处理,保存后的图像占用的空间(字节数)一般也与原图像不一样,可能经过了压缩。

3.2新建图像

     Pillow也可以新建空白图像, 第一个参数是mode即颜色空间模式,第二个参数指定了图像的分辨率(宽x高),第三个参数是颜色。

  • 可以直接填入常用颜色的名称。如'red'
  • 也可以填入十六进制表示的颜色,如#FF0000表示红色。
  • 还能传入元组,比如(255, 0, 0, 255)或者(255, 0, 0)表示红色。
# 通常使用RGB模式就可以了
newIm= Image.new('RGB', (100, 100), 'red')
newIm.save(r'C:\Users\Administrator\Desktop\1.png')

# 也可以用RGBA模式,还有其他模式查文档吧
blcakIm = Image.new('RGB',(200, 100), 'red')
blcakIm.save(r'C:\Users\Administrator\Desktop\2.png')
# 十六进制颜色
blcakIm = Image.new('RGBA',(200, 100), '#FF0000')
blcakIm.save(r'C:\Users\Administrator\Desktop\3.png')
# 传入元组形式的RGBA值或者RGB值
# 在RGB模式下,第四个参数失效,默认255,在RGBA模式下,也可只传入前三个值,A值默认255
blcakIm = Image.new('RGB',(200, 100), (255, 255, 0, 120))
blcakIm.save(r'C:\Users\Administrator\Desktop\4.png')

3.3 裁剪图像

  Image有个crop()方法接收一个矩形区域元组(上面有提到)。返回一个新的Image对象,是裁剪后的图像,对原图没有影响。

im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
cropedIm.save(r'C:\Users\Administrator\Desktop\cropped.png')

3.4 复制与粘贴图像到另一个图像

    Imagecopy函数如其名会产生一个原图像的副本,在这个副本上的任何操作不会影响到原图像。paste()方法用于将一个图像粘贴(覆盖)在另一个图像上面。谁调用它,他就在该Image对象上直接作修改。

im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
im.paste(cropedIm, (0, 0))
im.show()
im.save(r'C:\Users\Administrator\Desktop\paste.png')

  im.show()显示图像发现这时im(即原图)已经被改变。

     这如果之后还会用到原图的信息,由于信息被改变就很麻烦。所以paste前最好使用copy()复制一个副本,在此副本操作,不会影响到原图信息。虽然在程序里原图信息已改变,但由于保存文件时用的其他文件名,相当于改变没有生效,所以查看的时候原图还是没有改变的。

im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))
copyIm = im.copy()
copyIm.paste(cropedIm, (0, 0))
im.show()
copyIm.save(r'C:\Users\Administrator\Desktop\paste.png')
im = Image.open(im_path)
cropedIm = im.crop((700, 100, 1200, 1000))

crop_width, crop_height = cropedIm.size
width, height = im.size

copyIm = im.copy()
for left in range(0, width, crop_width):
    for top in range(0, height, crop_height):
        copyIm.paste(cropedIm, (left, top))

copyIm.save(r'C:\Users\Administrator\Desktop\dupli-rabbit.png')

      以裁剪后的图像宽度和高度为间隔,在循环内不断粘贴在副本中,这有点像是在拍证件照。

3.5 调整图像的大小

   resize方法返回指定宽高度的新Image对象,接受一个含有宽高的元组作为参数。宽高的值得是整数。

im = Image.open(im_path)
width, height = im.size
resizedIm = im.resize((width, height+(1920-1080)))
resizedIm.save(r'C:\Users\Administrator\Desktop\resize.png')

     resize不是等比例缩放的。图像可能有宽度或者高度的压缩。

3.6 旋转和翻转图像

   rotate()返回旋转后的新Image对象, 保持原图像不变。逆时针旋转。

im = Image.open(im_path)
im.rotate(90).save(r'C:\Users\Administrator\Desktop\rotate90.png')
im.rotate(270).save(r'C:\Users\Administrator\Desktop\rotate270.png')
im.rotate(180).save(r'C:\Users\Administrator\Desktop\rotate180.png')
im.rotate(20).save(r'C:\Users\Administrator\Desktop\rotate20.png')
im.rotate(20, expand=True).save(r'C:\Users\Administrator\Desktop\rotate20_expand.png')

  由上到下,分别是旋转了90°,180°, 270°、普通的20°,加了参数expand=True旋转的20°。

im90 = Image.open(r'C:\Users\Administrator\Desktop\rotate90.png')
im270 = Image.open(r'C:\Users\Administrator\Desktop\rotate270.png')
# 宽高信息并没有改变
print(im90.size, im270.size)
(1920, 1080) (1920, 1080)

       图像的镜面翻转。transpose()函数可以实现,必须传入Image.FLIP_LEFT_RIGHT或者Image.FLIP_TOP_BOTTOM,第一个是水平翻转,第二个是垂直翻转。

im = Image.open(im_path)
im.transpose(Image.FLIP_LEFT_RIGHT).save(r'C:\Users\Administrator\Desktop\transepose_lr.png')
im.transpose(Image.FLIP_TOP_BOTTOM).save(r'C:\Users\Administrator\Desktop\transepose_tb.png')

3.7 图像过滤

     Pillow使用ImageFilter可以简单做到图像的模糊、边缘增强、锐利、平滑等常见操作。

from PIL import Image, ImageFilter

im = Image.open(im_path)
# 高斯模糊
im.filter(ImageFilter.GaussianBlur).save(r'C:\Users\Administrator\Desktop\GaussianBlur.jpg')
# 普通模糊
im.filter(ImageFilter.BLUR).save(r'C:\Users\Administrator\Desktop\BLUR.jpg')
# 边缘增强
im.filter(ImageFilter.EDGE_ENHANCE).save(r'C:\Users\Administrator\Desktop\EDGE_ENHANCE.jpg')
# 找到边缘
im.filter(ImageFilter.FIND_EDGES).save(r'C:\Users\Administrator\Desktop\FIND_EDGES.jpg')
# 浮雕
im.filter(ImageFilter.EMBOSS).save(r'C:\Users\Administrator\Desktop\EMBOSS.jpg')
# 轮廓
im.filter(ImageFilter.CONTOUR).save(r'C:\Users\Administrator\Desktop\CONTOUR.jpg')
# 锐化
im.filter(ImageFilter.SHARPEN).save(r'C:\Users\Administrator\Desktop\SHARPEN.jpg')
# 平滑
im.filter(ImageFilter.SMOOTH).save(r'C:\Users\Administrator\Desktop\SMOOTH.jpg')
# 细节
im.filter(ImageFilter.DETAIL).save(r'C:\Users\Administrator\Desktop\DETAIL.jpg')

    另外,若是要进行图案、文字的绘制,可使用ImageDraw。

 

    Pillow还有其他强大功能,就不一一列举了。其实,Pillow只是个基础的图像处理库。若不深入图像处理,已经够用。专业人士使用opencv是更好地选择。


 

四:图像的格式种类以及转换

      PIL中有九种不同模式。分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,F


      对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。

     而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”。


 

五:PIL进行图像转换具体转换

原图像:

5.1 模式“1”---二值图像

    模式“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。下面我们将lena图像转换为“1”图像。  

from PIL import Image

im = Image.open("./g.png")
print(im.mode)  
print(im.size)
print(im.getpixel((0,0)))   #获取指定点处的像素值

im_1 = im.convert("1")
print(im_1.mode)
print(im_1.size)
print(im_1.getpixel((0,0)))
print(im_1.getpixel((140,140)))
im_1.show()
RGB
(286, 289)
(156, 169, 193)
1
(286, 289)
255
0

5.2 模式“L”---灰度图像

     模式“L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:

L = R * 299/1000 + G * 587/1000+ B * 114/1000
im_L = im.convert("L")
RGB
(286, 289)
(156, 169, 193)
L
(286, 289)
167
86   #156*299/1000+169*587/1000+193*114/1000 ---> 46.644+99.203+22.002 ---> 167.849  PIL中只取了整数部分

 

5.3 模式“P”---八位彩色图像,色彩值由调色板查询

     模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。

im_P = im.convert("P")
RGB
(286, 289)
(156, 169, 193)
P
(286, 289)
175
96 

 

5.4 模式“RGBA”---4通道RGB和alpha透明道

       模式“RGBA”为32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。

im_RGBA = im.convert("RGBA")
RGB
(286, 289)
(156, 169, 193)
RGBA
(286, 289)
(156, 169, 193, 255)  #4通道,默认将RGB图像转RGBA时,alpha通道为255
(91, 85, 83, 255) 

 

5.5 模式“CMYK”---印刷四分色模式(C青色M品红Y黄色K黑色)

       模式“CMYK”为32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。

      四种标准颜色是:C:Cyan = 青色,又称为‘天蓝色’或是‘湛蓝’M:Magenta = 品红色,又称为‘洋红色’;Y:Yellow = 黄色;K:Key Plate(blacK) = 定位套版色(黑色)。

im_CMYK = im.convert("CMYK")
RGB
(286, 289)
(156, 169, 193)
CMYK
(286, 289)
(99, 86, 62, 0)
(164, 170, 172, 0)

   转换公式

C = 255 - R
M = 255 - G
Y = 255 - B
K = 0 

由于该转换公式比较简单,转换后的图像颜色有些失真。

5.6 模式“YCbCr”---24位(Y亮度Cb蓝色色度Cr红色色度)

   模式“YCbCr”为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。

Y= 0.257*R+0.504*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128
im_YCbCr = im.convert("YCbCr")
RGB
(286, 289)
(156, 169, 193)
YCbCr
(286, 289)
(167, 142, 119)
(86, 126, 131)

5.7 模式“I”---与上面灰度模式L一致

       模式“I”为32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的

im_I = im.convert("I")
I = R * 299/1000 + G * 587/1000 + B * 114/1000
RGB
(286, 289)
(156, 169, 193)
I
(286, 289)
167
86

模式“I”与模式“L”的结果是完全一样,只是模式“L”的像素是8bit,而模式“I”的像素是32bit。

 

5.8模式“F”---32位浮点灰色图像

      模式“F”为32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:

F = R * 299/1000+ G * 587/1000 + B * 114/1000
im_F = im.convert("F")
RGB
(286, 289)
(156, 169, 193)
F
(286, 289)
167.8489990234375
86.56600189208984

 

 

 模式“F”与模式“L”的转换公式是一样的,都是RGB转换为灰色值的公式,但模式“F”会保留小数部分,如实验中的数据。

 

参考:

1:https://www.cnblogs.com/ssyfj/p/9292062.html#1%E3%80%81%C2%A0%E6%A8%A1%E5%BC%8F%E2%80%9C1%E2%80%9D---%E4%BA%8C%E5%80%BC%E5%9B%BE%E5%83%8F

2:https://www.cnblogs.com/sun-haiyu/p/7127582.html

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值