Pillow快速入門

Pillow快速入門

前言

本教程目的

學習該庫,目的是爲了用python去操作圖像提供更爲全面的選擇。

本庫進階學習

進階學習,首先需要很明確瞭解要對圖像進行什麼操作,然後查詢相關的API

初學思維導圖

在這裏插入圖片描述


接下來就是初學者教程。

使用 Image Class

PIL中,最重要的類就是Image這個和模塊名相同的類。您可以通過多種方式創建該類的實例;要麼從文件中加載圖像,要麼處理其他圖像,要麼從頭創建圖像。

要從文件中加載圖像,請使用圖像模塊中的open()函數:

from PIL import Image
im = Image.open("hopper.ppm")

如果成功,此函數將返回一個圖像對象。你現在可以使用實例屬性來檢查文件內容:

print(im.format, im.size, im.mode)
# PPM (512, 512) RGB

讀寫圖像

Python圖像庫支持多種圖像文件格式。要從磁盤讀取文件,請使用圖像模塊中的open()函數。你不必知道打開一個文件的格式。庫根據文件的內容自動確定格式。

保存目標格式的圖像

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:
            with Image.open(infile) as im:
              	# 核心是im.save()
                im.save(outfile)
        except IOError:
            print("cannot convert", infile)

創建縮略圖

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:
            with Image.open(infile) as im:
                #此處在緩衝區生成size大小的thumbnail()
                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

裁剪、複製、拼接圖像

從圖像中複製子矩形

box = (100, 100, 400, 400)
region = im.crop(box)

區域由一個4元組定義,其中的座標是(左、上、右、下)。Python圖像庫使用左上角的座標系統(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))
    image.paste(part1, (xsize-delta, 0, xsize, ysize))
    image.paste(part2, (0, 0, xsize-delta, ysize))

    return image

對於更高級的技巧,paste方法還可以將透明蒙版作爲可選參數。

在這個掩碼中,值255表示粘貼後的圖像在那個位置是不透明的(即,應該按原樣使用粘貼後的圖像)。值0表示粘貼的圖像是完全透明的。中間值表示不同的透明度級別。例如,粘貼RGBA圖像並將其用作掩碼將粘貼圖像的不透明部分,但不粘貼其透明的背景。

Python圖像庫還允許您處理多波段圖像的單個波段,例如RGB圖像。分割方法創建一組新圖像,每個圖像包含原始多頻帶圖像中的一個頻帶。merge函數接受一個模式和一個圖像元組,並將它們組合成一個新圖像。下面的例子交換了一個RGB圖像的三個波段:

分割和融合波段信息

r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))

注意,對於單波段圖像,split()返回圖像本身。要使用單獨的顏色帶,您可能需要首先將圖像轉換爲“RGB”。

幾何變換

PIL.Image。Image類包含調整()和旋轉()圖像的方法。前者採用一個元組提供新的大小,而後者採用逆時針角度。

簡單的幾何變換

out = im.resize((128, 128))
out = im.rotate(45) # degrees counter-clockwise

要將圖像旋轉90度,可以使用rotate()方法或轉置()方法。後者也可以用來翻轉圖像的水平或垂直軸。

翻轉圖像

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)

transpose(ROTATE)操作也可以和rotate進行相同的操作。

如果expandTrue則原圖像做相應的修改。

更加通用的操作是通過transform()方法對其進行修改。

顏色(通道)轉換

Python圖像庫允許您使用convert()方法在不同的像素表示之間轉換圖像。

模式之間的轉換

from PIL import Image
with Image.open("hopper.ppm") as im:
    im = im.convert("L")

該庫支持在每個支持模式與“L”和“RGB”模式之間進行轉換。要在其他模式之間進行轉換,您可能必須使用中間圖像(通常是“RGB”圖像)。

圖象增強

Python圖像庫提供了許多可以用來增強圖像的方法和模塊。

濾波

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)

注意用於創建掩碼的語法:

imout = im.point(lambda i: expression and 255)

圖像增強

對於更高級的圖像增強,您可以使用ImageEnhance模塊中的類。從圖像創建後,可以使用增強對象快速嘗試不同的設置。

你可以通過這種方式調整對比度、亮度、色彩平衡和銳度。

from PIL import ImageEnhance

enh = ImageEnhance.Contrast(im)
enh.enhance(1.3).show("30% more contrast")

圖像序列

Python圖像庫包含對圖像序列(也稱爲動畫格式)的一些基本支持。支持的序列格式包括FLI/FLC、GIF和一些實驗格式。TIFF文件也可以包含一個以上的幀。

當你打開一個序列文件時,PIL會自動加載序列中的第一幀。你可以使用查找和告訴方法在不同的幀之間移動:

序列讀取

from PIL import Image

with Image.open("animation.gif") as im:
    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

使用ImageSequence迭代器類

from PIL import ImageSequence
for frame in ImageSequence.Iterator(im):
    # ...do something to frame...

圖像打印

Python圖像庫包括在Postscript打印機上打印圖像、文本和圖形的函數。這裏有一個簡單的例子:

from PIL import Image
from PIL import PSDraw

with Image.open("hopper.ppm") as im:
    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()

關於讀取圖像

我們可以使用上下文管理器去讀取圖像進行一系列的操作:

from PIL import Image
with Image.open("hopper.ppm") as im:
    ...

您可以使用類似文件的對象來代替文件名。該對象必須實現read()、seek()和tell()方法,並以二進制模式打開。

從打開的文件中讀取圖像

from PIL import Image
with open("hopper.ppm", "rb") as fp:
    im = Image.open(fp)

從二進制文件中讀取

要從二進制數據中讀取圖像,使用BytesIO類:

from PIL import Image
import io
im = Image.open(io.BytesIO(buffer))

從壓縮文件中讀取圖像

注意,庫在讀取圖像頭之前會回滾文件(使用seek(0))。此外,在讀取圖像數據時也將使用seek(通過load方法)。如果圖像文件嵌入到更大的文件中,例如tar文件,則可以使用ContainerIOTarIO模塊來訪問它。

from PIL import Image, TarIO

fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
im = Image.open(fp)

控制編碼器

一些解碼器允許您在從文件中讀取圖像時操作圖像。當創建縮略圖(速度通常比質量更重要)和在單色激光打印機上打印(只需要圖像的灰度版本)時,這通常可以用來加快解碼速度。

draft()方法操作打開但尚未加載的圖像,使其儘可能接近給定的模式和大小。這是通過重新配置圖像解碼器實現的。

使用draft()讀取圖像

這隻在JPEGMPO文件情況下適用。此方法操作打開但尚未加載的圖像,使其儘可能接近給定的模式和大小。

from PIL import Image

with Image.open(file) as im:
    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)
"""

注意,生成的圖像可能與請求的模式和大小不完全匹配。要確保圖像不大於給定的大小,請使用縮略圖方法。


Link

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章