PIL:Python Imaging Library,已經是Python平台上的圖像處理標准庫了。PIL功能非常強大,但API卻非常簡單易用,因此廣受開發人員的使用。它提供了廣泛的文件格式支持、強大的圖像處理能力、主要包括圖像儲存、圖像顯示、格式轉換以及基本的圖像處理操作等。
pip install pillow
1、圖像處理的基本知識
1.1圖像的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)
1.2 像素陣列
像素(pixel,簡寫px):是數碼感光元件上最小的感光單位,也是數字圖片上最小的不可再分割的元素。例如,我們通常說的照片長1920、寬1080,是指橫向1920個像素,縱向1080個像素(總計2073600個像素)。而每一個像素包含RGB三種顏色,也就是說1個像素包含3個字節的信息:(R,G,B) 。假如這個像素是紅色,則信息是:(255,0,0)。那么,理論上我們只要操作每個點的這三個數字,就能夠實現任何推行。一幅畫上所有的像素點的信息就完全可以采用矩陣表示。通過矩陣的運算實現更加復雜的操作。
2、pillow使用
2.1 導入pillow庫
Pillow庫安裝成功后,導包時要用PIL來導入,而不能用pillow或Pillow,導入相應的包:
import PIL
from PIL import image # 導入PIL第三方庫中的image模塊
在Pillow庫中,有二十多個模塊,還支持非常多的插件。其中最常用的是Image模塊中同名的Image類,其他很多模塊都是在Image模塊的基礎上對圖像做進一步的特殊處理。
2.2 使用pillow庫中的Image模塊
Image類
-
打開照片 Image.open(fp,mode='r'),如果加載傳給則會返回一個Image對象,fp是照片路徑,mode是模式。圖像的對象屬性由:filename源文件的文件名或路徑,format圖片的格式,size圖片大小,以像素為單位,mode照片模式,width圖像寬度,height圖片高度,palete調色板表等。
-
新建圖像 new(mode,sizemcolor=0):在Image模塊中,可以使用new()新建圖像。mode值圖片模式。size表示圖片尺寸,是使用寬和高兩個元素構成元組。color默認顏色。
-
保存照片 save(fp,format=None,* *params):保存圖像到給定的文件名下,如果沒有指定格式則可以使用文件擴展名來確定要使用的格式,無返回值。fp是文件名或路徑,format可選的格式覆蓋。
-
顯示照片 show():顯示這個圖像,這方法主要是調試目的。
1、基本操作
對原本的照片進行一些基本操作,獲取該照片的信息,例如:照片格式,照片大小,打印照片等等基本操作。
from PIl import Image # 導入PIL庫中的image模塊
img=Image.open('2045435.jpg') # 打開照片
img.show() # 顯示照片
print('照片的格式:',img.format) # 輸出:jpg 照片的格式是jpg
print(img.size)
# 輸出:(1920,1080),以元組的形式進行展現,輸出照片的長和寬,可以在后面增加[0]表示元組的第一個數
print(img.height) # 輸出:1080,只輸出照片的長
print(img.width) # 輸出:1920,只輸出照片的寬
print('獲取(100,100)處像素值:',img.getpixel((100,100))) #輸出:(143, 163, 190)
Image.new(mode='RGB',size=img.size,color=(255,0,0)).show() #新建一個和img一樣大的紅色照片

2、縮放照片
(1)thumbnail(size,resample=3):指定照片的像素,size是大小,resample是重采樣濾波器,可以是Image。NEARST、Image.BILINEAR、Image.BICUBIC或者Image.LANCZOS,默認為image.BICUBIC。
from PIL import Image # 導入pillow庫中的Image模塊
img=Image.open('2045435.jpg') # 打開照片
print(img.size) # 輸出:(1920, 1080) 原照片的大小
img.thumbnail((300,300),resample=Image.BILINEAR)
# 將照片縮小為300,300,需要注意的是照片還是按照比例縮小,但是以最長的那條邊為基准
print(img.size) # 輸出:(300, 169) 縮小后照片的大小
img.save('1.jpg') # 保存照片
img.show() # 顯示照片
(2)eval(image,fun):其中image表示輸入的圖片,fun表示給輸入圖片的每一個像素應用此函數,fun()函數只允許接受一個整型參數,,如果一個圖片含有多個通道,則每個通道都會應用這個函數。
from PIL import Image
img=Image.open('2045435.jpg') # 打開照片
Image.eval(img,lambad i :i*2).show() #所有像素值*2
縮放前后的照片對比


3、旋轉照片
rotate(angle,resample=0,expand=0,center=None,translate=None):旋轉圖片的方向,返回旋轉后的圖像副本,一個Image對象。angle角度、逆時針旋轉、resample從采樣濾波器、expand是否展開、center旋轉中心(坐標點)、translate旋轉后。
旋轉和翻轉照片 transpose(method):旋轉或翻轉圖像、返回旋轉或者翻轉后的圖像副本,一個Image對象。method可以是Image.FLIP_LEFT_RIGHT(左右翻轉)、Image.FLIP_TOP_BOTTOM(上下翻轉)、Image.ROTATE_90、Image.ROTATE_180、Image.ROTATE_270、Image.TRANSPOSE或者Image.TRANSVERSE。
from PIL import Image
img=Image.open('2045435.jpg')
print(img.size)
img.show()
img.rotate(90,fillcolor=None).resize((1000,1000)).show() # 將照片進行旋轉90
img.transpose(Image.FLIP_LEFT_RIGHT).resize((1000,1000))show() # 將照片左右互調位置
旋轉照片如下

左右翻轉照片如下

4、圖片混合
blend(img1,img2,alpha):將兩個照片進行混合,其中img1、img2值參與混合的圖片1和圖片2,alpha指混合透明度,取值是0-1.通過使用這個函數blend(),可以將兩幅照片(相同的尺寸)以一定的透明度進行混合,混合的過程是(img1*(1-alpha)+img2 *aplha)。當混合透明度是0時,顯示img1原圖;混合透明度時1時,顯示是img2原圖。
from PIL import Image
img=Image.open('2045435.jpg') # 原照片
img1=Image.new('RGB',size=img.size,color=(200,200,100))
# 和原照片一樣的長度的橙色圖像
img3=Image.blend(img,img1,alpha=0.3).show() # 兩個相互結合

5、照片復制和粘貼、剪切
復制圖片 Image.copy():
復制指定的圖片,這樣可以用於在處理或粘貼時需要持有的照片
from PIL import Image
img=Image.open('2045435.jpg')
img2=img.copy().show() # 復制原照片
粘貼圖片 Image.paste():Image.paste(im,box=None,mask=None),其中im表示原圖或者像素值;box表示粘貼的區域,若為(x1,y1)將原圖左上角對齊(x1,y1)點,其他超出被粘貼圖像的區域被拋棄。若為(x1,y1,x2,y2)原圖和此區域一致。若為None,原圖和被粘貼的照片大小一致。
剪切圖片 Image.crop():
Image.crop(box=None),參數box時一個四元組,分別定義剪切區域的左、上、右、下四個坐標。
from calendar import c
from PIL import Image
img=Image.open('2045435.jpg')
img1=img.copy() # 復制照片
img2=img1.crop((100,100,200,500)) # 剪切照片
img3=Image.new('RGB',[300,300],color=(0,225,225)) # 新建一個圖像,400*400的白色圖像
img1.paste(img3,(200,200)) # 將img3的內容粘貼到img1上,從x=200和y=200開始粘貼
img1.show() # 展現照片

6、圖像像素的分離和合並
分離照片 Image.split():
使用split()函數可以將圖片分割為多個通道列表(分解像素)
合並照片 Image.merge():
使用merge()可以將一個通道的圖像合並到更多通道圖像。語法規則是Image.merge(mode,bands)。其中mode指輸出圖像的模式,bands表示涉及到的像素,一個序列包括單個帶圖通道。
from PIL import Image
img=Image.open(r"C:\Users\踩着上帝的小丑\Pictures\Saved Pictures\1.jpg")
img2=Image.open(r"C:\Users\踩着上帝的小丑\Pictures\Saved Pictures\2045435.jpg").resize(img.size)
# 需要將兩張照片以同一個長寬標准
R1,G1,B1=img.split() # split()將像素區分開來
R2,G2,B2=img2.split()
t=R2,G1,B2 # 重新組合像素,變為一個新的像素t
img3=Image.merge('RGB',bands=t) # 合並像素,組成一張新的圖像

2.3 使用pillow庫中的ImageFilter模塊
2.3.1 濾鏡
在pillow庫中的Image模塊中,使用函數filter()可以對指定的圖片使用濾鏡效果,在pillow庫中可以用的濾鏡保存在ImageFilter模塊中。
Image.Filter
調整濾鏡 filter(filter):給圖片增加濾鏡、返回一個Image對象,filter是過濾器。
| 濾鏡的種類 | 簡寫 |
|---|---|
| 模糊濾鏡 | BLUR |
| 輪廓濾鏡 | CONTOUR |
| 細節濾鏡 | DETAIL |
| 邊界增強濾鏡 | EDGE_ENHANCE |
| 邊界增強加強版濾鏡 | GE_ENHANCE_MORE |
| 浮雕濾鏡 | EMBOSS |
| 尋找邊界濾鏡 | FUND_EDGES |
| 平滑濾鏡 | SMOOTH |
| 平滑濾鏡加強版 | SOOTH_MORE |
| 銳化濾鏡 | SHARPEN |
| 核濾鏡 | Kernel |
| 等級濾波 | RankFilter |
| 最大值濾波 | MaxFilter |
| 最小值濾波 | MinFilter |
| 中值濾波濾鏡 | MedianFilter(size=3) |
| 波形濾鏡 | ModeFilter |
from PIL import Image,ImageFilter # 導入Image和ImageFilter模塊
img=Image.open('2045435.jpg') # 加載照片
t=img.filter(ImageFilter.CONTOUR) # 將照片進行輪廓濾鏡

2.4 使用pillow庫中的ImageDraw模塊
ImageDraw模塊實現了繪圖功能。可以通過圖片的方式來繪制2D圖像;還可以在原有的圖片上進行繪圖,以達到修飾圖片進行注釋的目的。
在ImageDraw模塊繪圖時需要首先創建一個ImageDraw.Draw對象,並且提供指向文件的參數,然后引用創建的Draw對象方法進行繪圖,最后保存或者直接輸出繪圖的圖像。
2.4.1 繪制直線
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表示一系列線之間的聯合類型,可以時曲線。
2.4.2 圖片寫字
text(xy, text, fill, font, spacing, direction)
xy是文字左上角起始位置,text是待編輯文字,fill文字顏色。font是個ImageFont的實例,這個我們后面去講,spacing是字體間距,direction參數是排列的方向,參數值有rtl,ttb兩種。不好記?很好記,right to left, top to button。開頭縮寫而已。
from PIL import Image,ImageDraw,ImageFont
# 調用ImageDraw模塊進行增加文字,ImageFont模塊進行中文處理
img=Image.new('RGB',(200,200),'white') # 創建一個白色背景的圖像
draw=ImageDraw.Draw(img) # 新建一個類似畫板
draw.rectangle((50,50,150,150),fill='blue',outline='red')
# 畫一個矩陣,從50*50到150*150,外部線條為紅色,整體為藍色
font=ImageFont.truetype('simhei',20)
# 格式化處理,處理中文的不可譯的影響
draw.text((70,70),text='張三',font=font,fill='white')
# 在畫布上寫在內容,第一個參數時位置
img.show()

