PIL (Python Imaging Library)
Python图像处理库,该库支持多种文件格式,提供强大的图像处理功能。
PIL中最重要的类是Image类,该类在Image模块中定义。
导入PIL模块
from PIL import Image
import numpy as np
1、Image.open 打开一个图像文件
img=Image.open('image.jpg')#Type(Image),Size(550,825)
2、img.show 显示这张图片
img.show()
3、np.array或np.asarray 将图片转化成numpy数组
img_arr=np.array(img) #Type(unit.8),Size(512,512,3)
4、Image.fromarray 将numpy数组转化为图片
new_img=Image.fromarray(img_arr) #Type(Image),Size(512,512)
所以处理图片后如果无法显示,需要转换格式 x.astype(np.unit8) (不是np.int 或 int)
即new_img=Image.fromarray(np.unit8(img_arr))
5、save 存储图片,可以转换为其他格式存储图片
new_img.save('newimagr.png')
对Image模块的介绍,对于PNG、BMP和JPG彩色图像格式之间的互相转换都可以通过Image模块的open()和save()函数来完成。
6、img.format 图像格式
print(img.format)#JPEG
7、 img.mode 图像类型,L为灰度图,RGB为真彩色,RGBA含有透明度通道。
print(img.mode)#RGB
对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”。
8、img.size 返回的是图像的宽高(w,h),不包含通道
print(img.size)#(512,512)
9、ROI操作,数组的切片操作
roi = img[100:300,30:350,:]
10、split,merge分离和合并图像通道
b,g,r = cv2.split(img) #通道分离
merge_img = cv2.merge((b,g,r))
11、im.getbands通道
img_bands=img.getbands()
print(img_bands)#(R,G,B)
print(len(img_bands))#3
print(img_bands[0])#R
print(img_bands[1])#G
print(img_bands[2])#B
每张图片都是由一个或者多个数据通道构成。PIL允许在单张图片中合成相同维数和深度的多个通道。
以RGB图像为例,每张图片都是由三个数据通道构成,分别为R、G和B通道。而对于灰度图像,则只有一个通道。
对于一张图片的通道数量和名称,可以通过方法getbands()来获取。方法getbands()是Image模块的方法,它会返回一个字符串元组(tuple)。该元组将包括每一个通道的名称。
12、img.getpixel图像点的像素值
print(img.getpixel((0,0)))#(197, 111, 78)
在数字图像处理中,针对不同的图像格式有其特定的处理算法。所以,在做图像处理之前,我们需要考虑清楚自己要基于哪种格式的图像进行算法设计及其实现。本文基于这个需求,使用python中的图像处理库PIL来实现不同图像格式的转换。
Image模块的convert()函数,用于不同模式图像之间的转换。
PIL的九种不同模式:1,L,P,RGB,RGBA,CMYK,YCbCr,I,F
图像的模式定义了图像的类型和像素的位宽。当前支持如下模式:
模式 | 描述 |
1 | 1位像素,表示黑和白,但是存储的时候每个像素存储为8bit。 |
L | 8位像素,表示黑和白。 |
P | 8位像素,使用调色板映射到其他模式。 |
RGB | 3x8位像素,为真彩色。 |
RGBA | 4x8位像素,有透明通道的真彩色。 |
CMYK | 4x8位像素,颜色分离。 |
YCbCr | 3x8位像素,彩色视频格式。 |
I | 32位整型像素。 |
F | 32位浮点型像素。 |
本文我采用的示例图像是图像处理中经典的lena照片。分辨率为512x512的lena图片如下:
1、模式“1”
为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。
img_1 = img.convert("1")
print(lena_1.mode) #'1'
print(img_1.size) #(512, 512)
print(img_1.getpixel((0,0))) #255
print(img_1.getpixel((10,10))) #255
print(img_1.getpixel((10,120))) #0
2、模式“L”
为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:L = R * 299/1000 + G * 587/1000+ B * 114/1000
print(img.mode) #'RGB'
print(img.getpixel((0,0))) #(197, 111, 78)
img_L =img.convert("L")
print(img_L.mode) #'L'
print(img_L.size) #(512, 512)
print(img_L.getpixel((0,0)) #132
3、模式“P”
为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。
print(img.mode) #'RGB'
print(img.getpixel((0,0)) #(197, 111, 78)
img_P =lena.convert("P")
print(img_P.mode) #'P'
print(img_P.getpixel((0,0))) #62
4、模式“RGBA”
为32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。从实例中可以看到,使用当前这个方式将“RGB”图像转为“RGBA”图像时,alpha通道全部设置为255,即完全不透明。
print(img.mode) #'RGB'
print(img.getpixel((0,0))) #(197,111, 78)
img_rgba = img.convert("RGBA")
print(img_rgba.mode) #'RGBA'
print(img_rgba.getpixel((0,0))) #(197,111, 78, 255)
print(img_rgba.getpixel((0,1))) #(196,110, 77, 255)
print(img.getpixel((0,0))) #(197,111, 78)
print(img.getpixel((0,1))) #(196,110, 77)
5、模式“CMYK”
为32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。
四种标准颜色是:C:Cyan =青色,又称为‘天蓝色’或是‘湛蓝’M:Magenta =品红色,又称为‘洋红色’;Y:Yellow =黄色;K:Key Plate(blacK) =定位套版色(黑色)。
img_cmyk =img.convert("CMYK")
print(img_cmyk.mode) #'CMYK'
print(img_cmyk.getpixel((0,0))) #(58, 144, 177, 0)
print(img_cmyk.getpixel((0,1))) #(59, 145, 178, 0)
print(img.getpixel((0,0))) #(197, 111, 78)
print(img.getpixel((0,1))) #(196, 110, 77)
从实例中可以得知PIL中“RGB”转换为“CMYK”的公式如下:
C = 255 - R
M = 255 - G
Y = 255 - B
K = 0
由于该转换公式比较简单,转换后的图像颜色有些失真。
6、模式“YCbCr”
为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。
模式“RGB”转换为“YCbCr”的公式如下:
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
img_ycbcr =img.convert("YCbCr")
print(img_ycbcr.mode) #'YCbCr'
print(img_ycbcr.getpixel((0,0))) #(132, 97, 173)
print(img.getpixel((0,0))) #(197, 111, 78)
按照公式,Y =0.257*197+0.564*111+0.098*78+16= 136.877
Cb= -0.148*197-0.291*111+0.439*78+128= 100.785
Cr = 0.439*197-0.368*111-0.071*78+128 = 168.097
由此可见,PIL中并非按照这个公式进行“RGB”到“YCbCr”的转换。
7、模式“I”
为32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的:
I = R * 299/1000 + G * 587/1000 + B * 114/1000
print(img.getpixel((0,0))) #(197,111, 78)
print(img.getpixel((0,1))) #(196,110, 77)
img_I =lena.convert("I")
print(img_I.mode) #'I'
print(img_I.getpixel((0,0))) #132
print(img_I.getpixel((0,1))) #131
img_L =lena.convert("L")
print(img_L.getpixel((0,0))) #132
print(img_L.getpixel((0,1))) #131
从实验的结果看,模式“I”与模式“L”的结果是完全一样,只是模式“L”的像素是8bit,而模式“I”的像素是32bit。
8、 模式“F”
模式“F”为32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:
F = R * 299/1000+ G * 587/1000 + B * 114/1000
print(img.getpixel((0,0))) #(197, 111, 78)
print(img.getpixel((0,1))) #(196, 110, 77)
img_F =lena.convert("F")
print(img_F.mode) #'F'
print(img_F.getpixel((0,0))) #132.95199584960938
print(img_F.getpixel((0,1))) #131.95199584960938
img_L =img.convert("L")
print(img_L.mode) #'L'
print(img_L.getpixel((0,0)) #132
模式“F”与模式“L”的转换公式是一样的,都是RGB转换为灰色值的公式,但模式“F”会保留小数部分,如实验中的数据。
img_1 img_L img_P img_rgba
img_cmyk img_ycbcr img
1、缩放(resize)与旋转(rotate)
resize()
函数接受一个元组,指定图像的新大小。 rotate()
函数接受一个角度值,逆时针旋转。
transpose()
和rotate()
函数在性能和结果上没有区别。更通用的图像变换函数为transform()
。
#缩放
img_resize = img.resize((h,w))
#旋转
img_r90 = img.rotate(90) #旋转90度
img_transpose_tb = img.transpose(Image.FLIP_TOP_BOTTOM)#上下翻转
img_transpose_lr = img.transpose(Image.FLIP_LEFT_RIGHT)#左右翻转
2、图像增强
PIL的ImageEnhance类专门用于图像增强处理,可以增强(减弱)图像的亮度、对比度、色度、以及锐度。
亮度(Brightness),色度(Color),对比度(Contrast),锐度(Sharpness)
from PIL import Image
from PIL import ImageEnhance
#原始图像
img = Image.open('image.jpg')
#亮度增强
img_bright = ImageEnhance.Brightness(imag).enhance(3)
image_bright.show()
#色度增强
img_color = ImageEnhance.Color(img).enhance(2)
image_color.show()
#对比度增强
img_contrast = ImageEnhance.Contrast(img).enhance(3)
image_contrast.show()
#锐度增强
img_sharp = ImageEnhance.Sharpness(img).enhance(2)
image_sharp.show()
3、图像滤波
由PIL中的ImageFilter类实现。
from PIL import ImageFilter
#模糊滤波
img_blur = img.filter(ImageFilter.BLUR)
#轮廓滤波
img_contour = img.filter(ImageFilter.CONTOUR)
#细节滤波
img_detail = img.filter(ImageFilter.DETAIL)
#边界增强滤波
img_edge_enhance = img.filter(ImageFilter.EDGE_ENHANCE)
#锐化滤波
img_sharp = img.filter(ImageFilter.SHARPEN)
#高斯模糊滤波
img_gauss = img.filter(ImageFilter.GaussianBlur(radius=2)) # radius指定平滑半径,也就是模糊的程度。
参考博文:
Python图像处理库PIL中图像格式转换(一)
Python的图像库(Opencv、PIL、matplotlib、skimage)的使用(读取、存储、变换、滤波)