python庫介紹-影象處理工具pillow中文文件-手冊(2018 5.*)
概述
Python Imaging Library給Python直譯器增加了影象處理能力。
該庫提供了廣泛的檔案格式支援,高效的內部展現,以及十分強大的影象處理能力。
核心影象庫專為以幾種儲存為基本畫素格式資料的快速訪問而設計。它為通用影象處理工具提供了堅實的基礎。
我們來看看這個庫的用途。
- 影象儲存
PIL適合影象歸檔和影象批量處理,你可以使用它建立縮圖,轉換格式,列印圖片等。
現在的版本可以識別和讀取大量的圖片格式,寫入常用的轉換和表示格式。
- 影象顯示
當前版本包含了Tk PhotoImage 和 BitmapImage 介面, 以及 Windows DIB interface ,可以在PythonWin和其他基於Windows的工具包中使用。許多其他GUI工具包帶有某種型別的PIL支援。
為了方便除錯還提供了show()方法,可以儲存影象到磁碟並呼叫外顯示。它將影象儲存到磁碟,並呼叫外部顯示工具。
- 影象處理
這個庫包含了基本的影象處理功能,包括點操作,使用內建卷積核心過濾,色彩空間轉換。
這個庫還支援更改影象大小、旋轉、任意仿射變換。
直方圖方法允許你統計影象,這可以用於對比度增強和全域性統計分析。
教程
使用 Image 類
PIL最重要的類是 Image , 你可以通過多種方法建立這個類的例項,比如從檔案載入影象,或者處理其他影象, 或者從或從頭開始建立影象。
要從檔案載入影象,請使用: Image 模組中的 open 函式:
>>> from PIL import Image >>> im = Image.open("hopper.ppm")
如果成功,這個函式返回 Image 物件。 您現在可以使用例項屬性來檢查檔案內容:
>>> print(im.format, im.size, im.mode) PPM (512, 512) RGB
format屬為影象來源。如果不是從檔案讀取就是None。size屬性是包含寬度和高度(畫素)的二元組)。模式屬性定義了影象中波段的數量和名稱,以及畫素型別和深度。 常見模式為灰度影象為“L”(亮度),真彩色影象為“RGB”,印刷四色為“CMYK”。
如果檔案無法開啟,則會引發IOError異常。
獲得了Image類的例項,就可以使用此類定義的方法來處理和操作影象。 例如讓我們顯示剛剛載入的影象:
>>> im.show()
注意
show 的標準版本效率不高,因為它將影象儲存到臨時檔案並呼叫xv工具顯示影象。 如果你沒有安裝xv,它甚至不會工作。 它對於除錯和測試非常方便。
下面例項把上述步驟給串起來
pillow_read.py
from PIL import Image im = Image.open("demo.jpg") print(im.format, im.size, im.mode) im.show()
以下各節概述了此庫中提供的不同功能。

image.png
參考資料
- 討論qq群144081101 591302926 567351477 釘釘免費群21745728
- 本文相關書籍下載
- 本文涉及的python測試開發庫 謝謝點贊!
- 英文參考
- 本文最新版本
讀寫影象
PIL庫支援大量圖片格式。使用Image模組的open()函式從磁碟讀取檔案。你不需要知道檔案格式就能開啟它,PIL能夠根據檔案內容自動確定確定檔案格式。
要儲存檔案,使用Image類的save()方法。儲存檔案的時候檔名變得重要了。除非你指定格式,PIL將會以檔名的副檔名作為格式儲存。
轉換檔案為JPEG
import os, sys from PIL import Image for infile in sys.argv[1:]: f, e = os.path.splitext(infile) outfile = f + ".jpg" if infile != outfile: try: Image.open(infile).save(outfile) except IOError: print("cannot convert", infile)
save()方法的第二個引數可以指定檔案格式,如果你使用非標準的副檔名你必須這樣做。
建立 JPEG 縮圖
import os, sys from PIL import Image size = (128, 128) for infile in sys.argv[1:]: outfile = os.path.splitext(infile)[0] + ".thumbnail" if infile != outfile: try: im = Image.open(infile) im.thumbnail(size) im.save(outfile, "JPEG") except IOError: print("cannot create thumbnail for", infile)
需要注意的是,除非真的需要,否則庫不會解碼或載入柵格資料。開啟檔案時,會讀取檔案頭以確定檔案格式並提取解碼檔案所需的模式,大小和其他屬性,但檔案的其餘部分在稍後才能處理。
這意味著開啟影象檔案是快速操作,和檔案大小和壓縮型別無關。比如快速識別影象檔案:
import sys from PIL import Image for infile in sys.argv[1:]: try: with Image.open(infile) as im: print(infile, im.format, "%dx%d" % im.size, im.mode) except IOError: pass
剪下,貼上,合併影象
Image類包含允許您操作影象內區域的方法。要從影象中提取子矩形,請使用crop()方法。
複製影象中的子矩形
box = (100, 100, 400, 400) region = im.crop(box)
該區域由四元組定義,其中座標是(左,上,右,下)。 PIL使用左上角為 (0, 0) 的座標系。另請注意,座標是指畫素之間的位置,因此上例中的區域恰好為300x300畫素。
現在可以以某種方式處理該區域並貼上回來。
處理子矩形並貼上回來
region = region.transpose(Image.ROTATE_180) im.paste(region, box)
當貼上區域時,區域的大小必須完全匹配。但是模式不需要匹配。模式不匹配時會在貼上之前自動轉換。
滾動影象
def roll(image, delta): """Roll an image sideways.""" xsize, ysize = image.size delta = delta % xsize if delta == 0: return image part1 = image.crop((0, 0, delta, ysize)) part2 = image.crop((delta, 0, xsize, ysize)) part1.load() part2.load() image.paste(part2, (0, 0, xsize-delta, ysize)) image.paste(part1, (xsize-delta, 0, xsize, ysize)) return image
呼叫示例:
pillow_roll.py
from PIL import Image def roll(image, delta): """Roll an image sideways.""" xsize, ysize = image.size delta = delta % xsize if delta == 0: return image part1 = image.crop((0, 0, delta, ysize)) part2 = image.crop((delta, 0, xsize, ysize)) part1.load() part2.load() image.paste(part2, (0, 0, xsize-delta, ysize)) image.paste(part1, (xsize-delta, 0, xsize, ysize)) return image im = Image.open("demo.jpg") im = roll(im,100) im.show()

image.png
[程式碼地址] https://github.com/china-testing/python-api-tesing/tree/master/python3_libraries/pillow )
請注意貼上時首先呼叫crop(),如果未呼叫則在paste命令中使用影象之前,不會執行裁剪操作。這意味著part1會從第一次貼上已經修改的影象版本中剪下掉。
貼上方法也可以將透明度掩碼作為可選引數。在此掩碼中,值255表示貼上的影象在該位置不透明(即按原樣使用貼上的影象)。值0表示貼上的影象是完全透明的。中間值表示不同級別的透明度。例如,貼上RGBA影象並將其用作蒙版將貼上影象的不透明部分,但不貼上透明背景。
PIL還允許您使用多波段影象的各個波段,例如RGB影象。拆分方法會建立新影象,每個影象都包含原始多波段影象中的一個波段。合併功能採用模式和影象元組,並將它們組合成新影象。以下示例交換RGB影象的三個波段:
分割和合並色帶
r, g, b = im.split() im = Image.merge("RGB", (b, g, r))
注意,對於單波段影象,split()會返回影象本身。要使用單獨的色帶,可能首先要將影象轉換為“RGB”。
幾何變換
PIL.Image.Image類包含調整resize()和rotate()影象的方法。前者需要給出尺寸的元組,後者是逆時針方向的角度。
簡單的幾何變換
out = im.resize((128, 128)) out = im.rotate(45) # degrees counter-clockwise
要以90度的步幅旋轉影象,您可以使用rotate()方法或transpose()方法。後者也可用於翻轉水平或垂直軸周圍的影象。
轉置影象
out = im.transpose(Image.FLIP_LEFT_RIGHT) out = im.transpose(Image.FLIP_TOP_BOTTOM) out = im.transpose(Image.ROTATE_90) out = im.transpose(Image.ROTATE_180) out = im.transpose(Image.ROTATE_270)
如果expand標誌為真,transpose(ROTATE)操作也可以與rotate()操作完全相同,以提供與影象大小相同的更改。
可以通transform()方法執行更常用的影象轉換。
示例:
#!/usr/bin/python3 # -*- coding: utf-8 -*- # Author:xurongzhong#126.com 技術支援qq群:6089740 # CreateDate: 2018-3-27 # rotate.py import glob import os from PIL import Image def rotate(files, dst, value=90): for file_ in files: img = Image.open(file_) img = img.rotate(value) name = "{}{}{}".format(dst, os.sep, os.path.basename(file_)) img.save(name) src = r'/home/andrew/code/tmp_photos' dst = r'/home/andrew/code/tmp_photos2' common = glob.glob('{}{}*.*'.format(src, os.sep)) rotate(common, dst)
顏色轉換
PIL允許您使用convert() 方法在不同的畫素表示之間轉換影象。
模式轉換
from PIL import Image im = Image.open("hopper.ppm").convert("L")
該庫支援每種支援模式和“L”和“RGB”模式之間的轉換。要在其他模式之間轉換,您可能必須使用中間影象(通常是“RGB”)影象。
影象增強
PIL提供了許多可用於增強影象的方法和模組。
- 過濾器
ImageFilter模組包含許多可以與filter()方法一起使用的預定義增強過濾器。
應用過濾器
from PIL import ImageFilter out = im.filter(ImageFilter.DETAIL)
-
點操作
point()方法可用於轉換影象的畫素值(例如影象對比度操作)。在大多數情況下,期望一個引數的函式物件可以傳遞給此方法。每個畫素都根據該功能進行處理:
# multiply each pixel by 1.2 out = im.point(lambda i: i * 1.2)
使用上述技巧,您可以快速將任何簡單表示式應用於影象。你也可以結合point()和paste()方法來選擇性地修改影象:
處理單個色帶
# split the image into individual bands source = im.split() R, G, B = 0, 1, 2 # select regions where red is less than 100 mask = source[R].point(lambda i: i < 100 and 255) # process the green band out = source[G].point(lambda i: i * 0.7) # paste the processed band back, but only where red was < 100 source[G].paste(out, None, mask) # build a new multiband image im = Image.merge(im.mode, source)
Python僅根據確定結果所需的邏輯表示式部分進行評估,並返回檢查的最後值作為表示式的結果。因此,如果上面的表示式為假(0),Python不會檢視第二個運算元,並返回0.否則,返回255。
- 增強
對於更高階的影象增強,您可以使用ImageEnhance模組中的類。從影象建立後,可以使用增強物件快速嘗試不同的設定。
您可以用這種方式調整對比度,亮度,色彩平衡和清晰度。
增強影象
from PIL import ImageEnhance enh = ImageEnhance.Contrast(im) enh.enhance(1.3).show("30% more contrast")
影象序列
Python影象庫包含對影象序列(也稱為動畫格式)的一些基本支援。支援的序列格式包括FLI/FLC, GIF和一些實驗格式。 TIFF檔案也可以包含多個幀。
當你開啟一個序列檔案時,PIL自動載入序列中的第一幀。您可以使用seek和tell方法在不同的幀之間移動:
讀序列
from PIL import Image im = Image.open("animation.gif") im.seek(1) # skip to the second frame try: while 1: im.seek(im.tell()+1) # do something to im except EOFError: pass # end of sequence
正如在這個例子中看到的,當序列結束時,你會得到EOFError異常。
注意當前版本庫中的大多數驅動程式只允許您尋找下一幀(如上例所示)。要倒回檔案,您可能必須重新開啟它。
下面的類讓你使用for語句來遍歷序列:
from PIL import ImageSequence for frame in ImageSequence.Iterator(im): # ...do something to frame...
後記列印
Python影像庫包括在Postscript印表機上列印影象,文字和圖形的功能。這裡有一個簡單的例子:
from PIL import Image from PIL import PSDraw im = Image.open("hopper.ppm") title = "hopper" box = (1*72, 2*72, 7*72, 10*72) # in points ps = PSDraw.PSDraw() # default is sys.stdout ps.begin_document(title) # draw the image (75 dpi) ps.image(box, im, 75) ps.rectangle(box) # draw title ps.setfont("HelveticaNarrow-Bold", 36) ps.text((3*72, 4*72), title) ps.end_document()
更多關於讀圖片
如前所述,Image模組的open() 函式用於開啟影象檔案。在大多數情況下,您只需將檔名作為引數傳遞給它:
from PIL import Image im = Image.open("hopper.ppm")
如果一切順利,結果是一個PIL.Image.Image物件。否則,會引發IOError異常。
您可以使用檔案類物件而不是檔名。該物件必須實現read(), seek()和tell()方法,並以二進位制模式開啟。
從開啟的檔案中讀取
from PIL import Image with open("hopper.ppm", "rb") as fp: im = Image.open(fp)
要從字串資料讀取影象,請使用StringIO類:
從字串中讀取
import StringIO im = Image.open(StringIO.StringIO(buffer))
請注意,在讀取影象標題之前,庫會回滾檔案(使用seek(0))。另外,當讀取影象資料時(通過載入方法),也將使用seek。如果映像檔案嵌入到較大的檔案中,例如tar檔案,則可以使用ContainerIO或TarIO模組訪問它。
從tar檔案中讀取
from PIL import Image, TarIO fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg") im = Image.open(fp)
控制解碼器
某些解碼器允許您在從檔案中讀取影象的同時操作影象。當建立縮圖時(速度通常比質量更重要)和列印到黑白鐳射印表機(只需要灰度版本的影象時)時,通常可以使用此功能來加速解碼。
draft() 方法處理已開啟但尚未載入的影象,以便儘可能匹配給定的模式和大小。這是通過重新配置影象解碼器完成的。
以草稿模式閱讀
這僅適用於JPEG和MPO檔案。
from PIL import Image from __future__ import print_function im = Image.open(file) print("original =", im.mode, im.size) im.draft("L", (100, 100)) print("draft =", im.mode, im.size)
這樣打印出如下內容:
original = RGB (512, 512) draft = L (128, 128)
請注意,生成的影象可能不完全符合請求的模式和尺寸。為確保影象不大於給定大小,請改用縮圖方法。