python計算機視覺學習筆記——PIL庫的用法

如果需要處理的原圖及代碼,請移步小編的GitHub地址

  傳送門:請點擊我

  如果點擊有誤:https://github.com/LeBron-Jian/ComputerVisionPractice

  這個是之前的筆記,自己看到了就順帶發出來,也是溫習一下,內容可能不太全,算是入門貼吧。

前言:PIL

   圖像處理是計算機視覺領域中不可或缺的一部分,而PIL(Python Imaging Library)庫和OpenCV(Open Source Computer Vision Library)是兩個常用的工具。今天這裏主要學習以下PIL庫,PIL 是一個用於圖像處理的 Python 庫,提供了豐富的圖像處理功能。它包含了處理圖像的各種工具和算法,可以進行圖像的打開、保存、剪裁、旋轉、縮放等操作。

  PIL(Python Imaging Library)和 OpenCV 都是用於圖像處理的強大庫,它們各自有着不同的優勢和適用場景。以下是一些導致 PIL 仍然被使用的原因:

1,PIL的優點

  1. 易用性:PIL庫的API設計得非常簡潔明瞭,即使是編程新手也能快速上手。例如,你只需要一行代碼就可以打開一個圖像文件,然後再用一行代碼就可以將圖像保存到新的文件中。
  2. 功能強大:PIL庫提供了豐富的圖像處理功能,包括基本的圖像操作(如裁剪、旋轉、縮放等),圖像濾鏡,以及更高級的功能(如圖像增強、色彩空間轉換等)。
  3. 支持多種圖像格式:PIL庫支持多種常見的圖像格式,包括JPEG、PNG、BMP、GIF、PPM、TIFF等。這意味着你可以使用PIL庫來處理幾乎所有類型的圖像文件。
  4. 文字和繪圖功能:PIL允許在圖像上添加文字、繪製幾何圖形和繪製曲線,這對於圖像註釋和標記非常有幫助。
  5. 擴展功能:PIL還支持各種擴展功能,如圖像濾波、直方圖均衡化和顏色空間轉換等。

 

2,PIL 的缺點

  1. 性能:雖然PIL庫的功能強大,但是它的性能並不是最優的。如果你需要處理大量的圖像,或者進行復雜的圖像處理操作,可能會發現PIL庫的速度不盡如人意。
  2. 不支持一些高級功能:雖然PIL庫提供了豐富的圖像處理功能,但是它並不支持一些高級的圖像處理操作,如特徵檢測、圖像分割等。如果你需要進行這些操作,可能需要使用其他的圖像處理庫,如OpenCV。

 

3,PIL 庫和OpenCV的區別

  1. 編程語言:PIL庫是用純Python編寫的,而OpenCV主要是用C++編寫的,並提供了Python的接口。如果您更熟悉Python,並且希望使用Python進行圖像處理,那麼PIL可能更適合您。並且PIL 的接口相對較爲簡單,特別適合一些簡單的圖像處理任務。對於一些不需要太多高級功能的應用,PIL 提供了直觀的方法和易於使用的 API。
  2. 功能和算法:OpenCV提供了更豐富和先進的圖像處理算法和函數,涵蓋了從基本操作到高級計算機視覺任務的各個方面。而PIL 在功能上相對輕量,適合一些小型項目或者只需要進行基本圖像處理的場景。如果你的需求主要是一些簡單的圖像操作,PIL 可能是更輕便的選擇。
  3. 性能:由於OpenCV是用C++編寫的,因此在處理大型圖像和複雜計算任務時具有較高的性能優勢。PIL庫在處理大型圖像時可能效率稍低。
  4. 生態系統:OpenCV擁有龐大的社區支持和豐富的文檔資源,可以幫助您解決問題和學習。而PIL庫的社區活動相對較少,文檔資源相對較少。

 

4,如何使用PIL庫

  首先是安裝,比較簡單:

pip install pillow

  

  下面是一個簡單的示例,演示瞭如何使用PIL庫來打開一個圖像文件,然後將圖像轉換爲灰度圖,並保存到新的文件中:

from PIL import Image

# 打開圖像文件
img = Image.open('input.jpg')

# 將圖像轉換爲灰度圖
img_gray = img.convert('L')

# 保存圖像到新的文件
img_gray.save('output.jpg')

  

  雖然 OpenCV 在計算機視覺和更復雜的圖像處理任務中表現得非常強大,但選擇使用哪個庫通常取決於具體的需求和項目特點。在一些情況下,PIL 可能更爲合適,而在其他情況下,特別是涉及到計算機視覺領域的任務,OpenCV 可能更具優勢。

   總體來說,網上開源的一些計算機視覺中也使用PIL加載圖像,所以有不得不學習的理由,話不多說,開幹:

一:pillow模塊的基本概念

  Pillow的官網地址:https://pillow.readthedocs.io/en/stable/,其實打開後,什麼都有,只是都是英文,對於部分同學不方面而已。

 

  PIL:Python Imaging Library,已經是Python平臺上的圖像處理標準庫了。由於PIL僅支持到Python2.7 ,加上年久失修,於是一羣志願者在PIL的基礎上創建了兼容的版本,名字叫Pillow,支持最新版本的Python3.X,又加了許多新特性。因此,我們可以直接安裝使用Pillow。

  PIL中所涉及的基本概念有如下幾個:通道(bands)、模式(mode)、尺寸(size)、座標系統(coordinate system)、調色板(palette)、信息(info)和濾波器(filters)。

1.1  通道——Image.getbands

  每張圖片都是由一個或者多個數據通道構成。PIL允許在單張圖片中合成相同維數和深度的多個通道。

  以RGB圖像爲例,每張圖片都是由三個數據通道構成,分別爲R、G和B通道。而對於灰度圖像,則只有一個通道。

  對於一張圖片的通道數量和名稱,可以通過方法getbands()來獲取。方法getbands()是Image模塊的方法,它會返回一個字符串元組(tuple)。該元組將包括每一個通道的名稱。

  Python的元組與列表類似,不同之處在於元組的元素不能修改,元組使用小括號,列表使用方括號,元組創建很簡單,只需要在括號中添加元素,並使用逗號隔開即可。

  方法getbands()的使用如下:

from PIL import Image
im = Image.open("test.png")
print(im.getbands())
輸出:
('R', 'G', 'B')

 

1.2  模式——Image.mode

  圖像的模式定義了圖像的類型和像素的位寬。當前支持如下模式:

1:1位像素,表示黑和白,但是存儲的時候每個像素存儲爲8bit。

L:8位像素,表示黑和白。

P:8位像素,使用調色板映射到其他模式。

RGB:3x8位像素,爲真彩色。

RGBA:4x8位像素,有透明通道的真彩色。

CMYK:4x8位像素,顏色分離。

YCbCr:3x8位像素,彩色視頻格式。

I:32位整型像素。

F:32位浮點型像素。

PIL也支持一些特殊的模式,包括RGBX(有padding的真彩色)和RGBa(有自左乘alpha的真彩色)。

  可以通過mode屬性讀取圖像的模式。其返回值是包括上述模式的字符串。

  屬性mode的使用如下:

from PIL import Image
im = Image.open("test.png")
print(im.mode)
輸出:
'RGB'

  

1.3  尺寸——Image.size

  通過size屬性可以獲取圖片的尺寸。這是一個二元組,包含水平和垂直方向上的像素數。

  屬性mode的使用如下:

from PIL import Image
im = Image.open("test.png")
print(im.size)
輸出:
(670, 502)

  

1.4  座標系統

  在PIL(或Pillow)中,圖像的座標系統遵循常見的數學座標系,其中左上角是原點(0, 0),x軸向右增長,y軸向下增長。這意味着圖像的左上角具有座標 (0, 0),而右下角的座標是 (width-1, height-1)

  以下是一個簡單的示例說明PIL的座標系統:

from PIL import Image, ImageDraw


# 創建一個白色背景的圖像
width, height = 200, 100
image = Image.new("RGB", (width, height), "yellow")

# 創建一個ImageDraw對象,即獲取圖像的繪製對象
draw = ImageDraw.Draw(image)

# 在圖像中心繪製一個紅色矩形
rect_width, rect_height = 50, 30
left = 0
top = (height - rect_height) // 2
right = left + rect_width
bottom = top + rect_height

draw.rectangle([left, top, right, bottom], fill="red")

# 保存圖像
# image.save("coordinate_example.png")

# 顯示圖像
image.show()


# 顯示座標系
print(f"左上角座標:(0, 0)")
print(f"右下角座標:({width-1}, {height-1})")


# 輸出結果
# 左上角座標: (0, 0)
# 右下角座標:( 199, 99)

  輸出圖像:

 

1.5  調色板——Image.palette

  在PIL(Python Imaging Library)中,調色板(Palette)是一種用於存儲和管理顏色映射的機制。調色板通常與圖像的索引顏色模式一起使用,這意味着圖像的每個像素值不直接表示顏色,而是作爲索引來查找調色板中的實際顏色。

  以下是有關調色板的一些重要概念和說明:

  1. 索引顏色模式:

    • 在索引顏色模式中,圖像的每個像素值都是一個索引,該索引對應於調色板中的顏色。
    • 通常,索引顏色模式用於節省存儲空間,特別是對於包含有限顏色集的圖像。
  2. 調色板的組成:

    • 調色板是一個包含顏色信息的數據結構,通常由顏色元組組成。顏色元組可以是RGB(紅、綠、藍)格式,也可以是其他顏色表示格式。
    • 對於每個索引,調色板中都有一個與之對應的顏色。
  3. 使用調色板的圖像格式:

    • 一些常見的使用調色板的圖像格式包括GIF和PNG-8。這些格式在保存圖像時使用調色板,而不是直接存儲每個像素的完整顏色信息。
  4. 圖像的調色板屬性:

    • PIL中的圖像對象具有調色板屬性,通過該屬性可以獲取和設置圖像的調色板。
    • 使用 image.getpalette() 方法可以獲取圖像的調色板,而 image.putpalette() 方法可以設置調色板。

  以下是一個簡單的示例,演示如何使用PIL中的調色板:

from PIL import Image

# 創建一個調色板
palette = [255, 0, 0,  # Red
           0, 255, 0,  # Green
           0, 0, 255]  # Blue

# 創建一個8x8的圖像,使用調色板和索引顏色模式
image = Image.new("P", (8, 8))
image.putpalette(palette)

# 設置圖像的像素值(索引)
pixels = [0, 1, 2, 0, 1, 2, 0, 1,
          1, 2, 0, 1, 2, 0, 1, 2,
          2, 0, 1, 2, 0, 1, 2, 0,
          0, 1, 2, 0, 1, 2, 0, 1,
          1, 2, 0, 1, 2, 0, 1, 2,
          2, 0, 1, 2, 0, 1, 2, 0,
          0, 1, 2, 0, 1, 2, 0, 1,
          1, 2, 0, 1, 2, 0, 1, 2]

image.putdata(pixels)

# 顯示圖像
image.show()

  這個例子創建了一個調色板,然後使用索引顏色模式創建了一個8x8的圖像,並通過設置像素值(索引)來使用調色板中的顏色。

1.6  信息——Image.info

  使用info屬性可以爲一張圖片添加一些輔助信息。這個是字典對象。加載和保存圖像文件時,多少信息需要處理取決於文件格式。

屬性info的使用如下:

from PIL import Image
im = Image.open("test.jpg")
print(im.info)
輸出:
{'jfif': 257, 'jfif_version': (1, 1), 'jfif_unit': 0, 'jfif_density': (1, 1)}

  

1.7  濾波器

  對於將多個輸入像素映射爲一個輸出像素的幾何操作,PIL提供了四個不同的採樣濾波器。

NEAREST:最近濾波。從輸入圖像中選取最近的像素作爲輸出像素。它忽略了所有其他的像素。

BILINEAR:雙線性濾波。在輸入圖像的2x2矩陣上進行線性插值。
注意:PIL的當前版本,做下采樣時該濾波器使用了固定輸入模板。

BICUBIC:雙立方濾波。在輸入圖像的4x4矩陣上進行立方插值。
注意:PIL的當前版本,做下采樣時該濾波器使用了固定輸入模板。

ANTIALIAS:平滑濾波。這是PIL 1.1.3版本中新的濾波器。對所有可以影響輸出像素
的輸入像素進行高質量的重採樣濾波,以計算輸出像素值。在當前的PIL版本中,這個濾
波器只用於改變尺寸和縮略圖方法。
注意:在當前的PIL版本中,ANTIALIAS濾波器是下采樣(例如,將一個大的圖像轉換爲
小圖)時唯一正確的濾波器。BILIEAR和BICUBIC濾波器使用固定的輸入模板,用於固
定比例的幾何變換和上採樣是最好的。

  Image模塊中的方法 resize() 和 thumbnail()用到了濾波器。

  方法resize() 的使用如下:

方法resize()的定義爲:resize(size, filter=None)=> image
from PIL import Image
im = Image.open("test.png")
print(im.size)
im_resize = im.resize((256,256))
print(im_resize.size)
輸出:
(670, 502)
(256,256)

  對參數filter不賦值的話,方法resize()默認使用NEAREST濾波器。如果要使用其他濾波器可以通過下面的方法來實現:

from PIL import Image
im = Image.open("test.png")
print(im.size)
im_resize0 = im.resize((256,256), Image.BILINEAR)
print(im_resize0.size)
im_resize1 = im.resize((256,256), Image.BICUBIC)
print(im_resize1.size)
im_resize2 = im.resize((256,256), Image.ANTIALIAS)
print(im_resize2.size)

輸出:
(670, 502)
(256,256)
(256,256)
(256,256)

  

 

2,Image對象

2.1  實例化對象

  直接讀取圖片

from PIL import Image

# 導入圖像
img_path = r"book.png"
img = Image.open(img_path)

# 展示圖像
im.show()

  

2.2 格式轉換——save方法

  save方法用於保存圖像,當不指定文件格式時,它會以默認的圖片格式來存儲;如果指定圖片格式,則會以指定的格式存儲圖片,語法如下:

im = PIL.Image.open(r"book.jpg")

# 保存圖片
# fp: 圖片的存儲路徑,包含圖片的名稱,字符串格式
fp = "book_save.jpg"  
# format:可選參數,可以指定圖片的格式
im.save(fp, format=None)  

  

 

2.3  格式轉換——Convert方法

  注意:並非所有的圖片格式都可以用 save() 方法轉換完成,比如將 PNG 格式的圖片保存爲 JPG 格式,如果直接使用 save() 方法就會出現錯誤,引發錯誤的原因是由於 PNG 和 JPG 圖像模式不一致導致的。其中 PNG 是四通道 RGBA 模式,即紅色、綠色、藍色、Alpha 透明色;JPG 是三通道 RGB 模式。因此要想實現圖片格式的轉換,就要將 PNG 轉變爲三通道 RGB 模式。

  Image 類提供的 convert() 方法可以實現圖像模式的轉換。該函數提供了多個參數,比如 mode、matrix、dither 等,其中最關鍵的參數是 mode,其餘參數無須關心

  語法:

im.convert(mode, params)  # 轉換模式
im.save(fp)  # 保存圖片

  

 2.4  圖像縮放

 在圖像處理過程中經常會遇到縮小或放大圖像的情況,Image 類提供的 resize() 方法能夠實現任意縮小和放大圖像

  語法:

im_new = im.resize(size, resample=image.BICUBIC, box=None, reducing_gap=None)  
 
# 縮放後的圖片
im_new.show() 

  

2.5  圖像的分離和合並

  圖像(指數字圖像)由許多像素點組成,像素是組成圖像的基本單位,而每一個像素點又可以使用不同的顏色,最終呈現出了絢麗多彩的圖像 ,而圖像的分離與合併,指的就是圖像顏色的分離和合並

圖像分離:split方法

  示例:

im = PIL.Image.open(r"magic_h03.jpg")

# split 方法使用較簡單,分離通道
r, g, b = im.split()  
r.show()
g.show()
b.show()

  

圖像合併:merge方法

  Image 類提供的 merge() 方法可以實現圖像的合併操作。注意,圖像合併,可以是單個圖像合併,也可以合併兩個以上的圖像

  示例:

im_merge = PIL.Image.merge(mode, bands)
im_merge.show()

  

圖像合併:blend方法

  Image 類也提供了 blend() 方法來混合 RGBA 模式的圖片(PNG 格式)

  語法:

PIL.Image.blend(image1,image2, alpha)

  

2.6  圖像裁剪

  Image 類提供的 crop() 函數允許我們以矩形區域的方式對原圖像進行裁剪

  語法:

im_crop = im.crop(box=None)  # box 代表裁剪區域
im_crop.show()

  box 是一個有四個數字的元組參數 (x_左上,y_左下,x1_右上,y1_右下),分別表示被裁剪矩形區域的左上角 x、y 座標和右下角 x,y 座標。默認 (0,0) 表示座標原點,寬度的方向爲 x 軸,高度的方向爲 y 軸,每個像素點代表一個單位

 

3,代碼實戰

3.1 圖像的屬性的打印示例

  注意:源文件的文件格式。如果是由PIL創建的空圖像,則其文件格式爲None,即 im.format ⇒ string or None

  示例代碼如下:

import PIL.Image

im = PIL.Image.open(r"harden.png")

print(im.size)  # 查看圖片大小, 按照像素數計算。它的返回值爲寬度和高度的二元組(width, height)
print(im.readonly) # 查看是否爲只讀,1爲是,0爲否 print(im.format) # 查看圖片的格式, 輸出爲 'png'
print(im.info) # 查看圖片的相關信息 print(im.mode) # 查看圖片的模式

print(im.mode)  # 表明圖像所使用像素格式, 屬性典型的取值爲“1”,“L”,“RGB”或“CMYK”
print(im.palette)  # 顏色調色板表格。如果圖像的模式是“P”,則返回ImagePalette類的實例;否則,將爲None。

  

 

3.2  使用PIL進行灰度化+二值化

  代碼如下:

from PIL import Image

#  load a color image
im = Image.open('durant.jpg' )

#  convert to grey level image
Lim = im.convert('L' )
Lim.save('grey.jpg' )

#  setup a converting table with constant threshold
threshold = 185
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)

# convert to binary image by the table
bim = Lim.point(table, '1' )

bim.save('durant_grey.jpg' )

  原圖圖片效果展示:

 

  灰度化圖片效果展示:

  二值化圖片效果展示:

 

3.2  圖像轉換示例

  代碼如下:

 

例子1:
from PIL import Image
im1 = Image.open("jing.jpg")
print(im1.mode)
im_c = im1.convert("1")
im_c.save("he.jpg")
print(im_c.mode)
輸出:
注:將“RGB”模式的im01圖像,轉換爲“1”模式的im_c圖像。

 
定義3:im.convert(mode,matrix) ⇒ image
含義3:使用轉換矩陣將一個“RGB”圖像轉換爲“L”或者“RGB”圖像。變量matrix爲4或者16元組。
例子3:下面的例子將一個RGB圖像(根據ITU-R709線性校準,使用D65亮度)轉換到CIE XYZ顏色空間:
from PIL import Image
im1 = Image.open("jing.jpg")
im1.mode
rgb2xyz = (
    0.412453, 0.357580, 0.180423, 0,
    0.212671, 0.715160, 0.072169, 0,
    0.019334, 0.119193, 0.950227, 0 )
im_c3 = im1.convert("L", rgb2xyz)
im_c3.save("he.jpg")
print(im_c3.mode)
輸出:
L

  

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