Python圖像處理庫PIL中圖像格式轉換(一)

在數字圖像處理中,針對不同的圖像格式有其特定的處理算法。所以,在做圖像處理之前,我們需要考慮清楚自己要基於哪種格式的圖像進行算法設計及其實現。本文基於這個需求,使用python中的圖像處理庫PIL來實現不同圖像格式的轉換。

對於彩色圖像,不管其圖像格式是PNG,還是BMP,或者JPG,在PIL中,使用Image模塊的open()函數打開後,返回的圖像對象的模式都是“RGB”。而對於灰度圖像,不管其圖像格式是PNG,還是BMP,或者JPG,打開後,其模式爲“L”。

通過之前的博客對Image模塊的介紹,對於PNGBMPJPG彩色圖像格式之間的互相轉換都可以通過Image模塊的open()save()函數來完成。具體說就是,在打開這些圖像時,PIL會將它們解碼爲三通道的“RGB”圖像。用戶可以基於這個“RGB”圖像,對其進行處理。處理完畢,使用函數save(),可以將處理結果保存成PNGBMPJPG中任何格式。這樣也就完成了幾種格式之間的轉換。同理,其他格式的彩色圖像也可以通過這種方式完成轉換。當然,對於不同格式的灰度圖像,也可通過類似途徑完成,只是PIL解碼後是模式爲“L”的圖像。

這裏,我想詳細介紹一下Image模塊的convert()函數,用於不同模式圖像之間的轉換。

Convert()函數有三種形式的定義,它們定義形式如下:

im.convert(mode) image

im.convert(“P”, **options) image

im.convert(mode, matrix) image

使用不同的參數,將當前的圖像轉換爲新的模式,併產生新的圖像作爲返回值。

通過博客“Python圖像處理庫PIL的基本概念介紹”,我們知道PIL中有九種不同模式。分別爲1LPRGBRGBACMYKYCbCrIF

本文我採用的示例圖像是圖像處理中經典的lena照片。分辨率爲512x512lena圖片如下:

一、模式“RGB”轉換爲其他不同模式

1、 模式“1

模式“1”爲二值圖像,非黑即白。但是它每個像素用8bit表示,0表示黑,255表示白。下面我們將lena圖像轉換爲“1”圖像。

例子:


>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena.mode

'RGB'

>>> lena.getpixel((0,0))

(197, 111, 78)

>>> lena_1 = lena.convert("1")

>>> lena_1.mode

'1'

>>> lena_1.size

(512, 512)

>>>lena_1.getpixel((0,0))

255

>>> lena_1.getpixel((10,10))

255

>>>lena_1.getpixel((10,120))

0

>>>lena_1.getpixel((130,120))

255

 

圖像lena_1的模式爲“1”,分辨率爲512x512,如下:

2、 模式“L

模式“L”爲灰色圖像,它的每個像素用8bit表示,0表示黑,255表示白,其他數字表示不同的灰度。在PIL中,從模式“RGB”轉換爲“L”模式是按照下面的公式轉換的:

L = R * 299/1000 + G * 587/1000+ B * 114/1000

下面我們將lena圖像轉換爲“L”圖像。

例子:

>>> from PIL importImage

>>> lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena.mode

'RGB'

>>> lena.getpixel((0,0))

(197, 111, 78)

>>> lena_L =lena.convert("L")

>>> lena_L.mode

'L'

>>> lena_L.size

(512, 512)

>>>lena.getpixel((0,0))

(197, 111, 78)

>>>lena_L.getpixel((0,0))

132

對於第一個像素點,原始圖像lena(197, 111, 78),其轉換爲灰色值爲:

197 *299/1000 + 111 * 587/1000 + 78 * 114/1000 = 132.952PIL中只取了整數部分,即爲132

轉換後的圖像lena_L如下:

3、 模式“P

模式“P”爲8位彩色圖像,它的每個像素用8bit表示,其對應的彩色值是按照調色板查詢出來的。

下面我們使用默認的調色板將lena圖像轉換爲“P”圖像。

例子:


>>> from PIL importImage

>>> lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena.mode

'RGB'

>>> lena.getpixel((0,0))

(197, 111, 78)

>>> lena_P =lena.convert("P")

>>> lena_P.mode

'P'

>>>lena_P.getpixel((0,0))

62

 

轉換後的圖像lena_P如下:

4、 模式“RGBA

模式“RGBA”爲32位彩色圖像,它的每個像素用32bit表示,其中24bit表示紅色、綠色和藍色三個通道,另外8bit表示alpha通道,即透明通道。

下面我們將模式爲“RGB”的lena圖像轉換爲“RGBA”圖像。

例子: 

                                                                                                                              

>>> from PIL import Image

>>>lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>>lena.mode

'RGB'

>>>lena.getpixel((0,0))

(197,111, 78)

>>>lena_rgba = lena.convert("RGBA")

>>>lena_rgba.mode

'RGBA'

>>>lena_rgba.getpixel((0,0))

(197,111, 78, 255)

>>>lena_rgba.getpixel((0,1))

(196,110, 77, 255)

>>>lena.getpixel((0,0))

(197,111, 78)

>>>lena.getpixel((0,1))

(196,110, 77)

 

從實例中可以看到,使用當前這個方式將“RGB”圖像轉爲“RGBA”圖像時,alpha通道全部設置爲255,即完全不透明。

轉換後的圖像lena_rgba如下:

5、 模式“CMYK

模式“CMYK”爲32位彩色圖像,它的每個像素用32bit表示。模式CMYK”就是印刷四分色模式,它是彩色印刷時採用的一種套色模式,利用色料的三原色混色原理,加上黑色油墨,共計四種顏色混合疊加,形成所謂“全綵印刷”。

四種標準顏色是:CCyan = 青色,又稱爲‘天藍色’或是‘湛藍’MMagenta = 品紅色,又稱爲‘洋紅色’;YYellow = 黃色;KKey Plate(blacK) = 定位套版色(黑色)。

下面我們將模式爲“RGB”的lena圖像轉換爲“CMYK”圖像。

例子:


>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena_cmyk =lena.convert("CMYK")

>>> lena_cmyk.mode

'CMYK'

>>>lena_cmyk.getpixel((0,0))

(58, 144, 177, 0)

>>> lena_cmyk.getpixel((0,1))

(59, 145, 178, 0)

>>>lena.getpixel((0,0))

(197, 111, 78)

>>>lena.getpixel((0,1))

(196, 110, 77)

 

從實例中可以得知PIL中“RGB”轉換爲“CMYK”的公式如下:

C = 255 - R
M = 255 - G
Y = 255 - B
K = 0

由於該轉換公式比較簡單,轉換後的圖像顏色有些失真。

轉換後的圖像lena_cmyk如下:

6、 模式“YCbCr

模式“YCbCr”爲24位彩色圖像,它的每個像素用24bit表示。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

下面我們將模式爲“RGB”的lena圖像轉換爲“YCbCr”圖像。

例子:


>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena_ycbcr =lena.convert("YCbCr")

>>>lena_ycbcr.mode

'YCbCr'

>>>lena_ycbcr.getpixel((0,0))

(132, 97, 173)

>>>lena.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”的轉換。

轉換後的圖像lena_ycbcr如下:

7、 模式“I

模式“I”爲32位整型灰色圖像,它的每個像素用32bit表示,0表示黑,255表示白,(0,255)之間的數字表示不同的灰度。在PIL中,從模式“RGB”轉換爲“I”模式是按照下面的公式轉換的:

I = R * 299/1000 + G * 587/1000 + B * 114/1000

下面我們將模式爲“RGB”的lena圖像轉換爲“I”圖像。

例子:


>>> from PIL import Image

>>>lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>>lena.getpixel((0,0))

(197,111, 78)

>>>lena.getpixel((0,1))

(196,110, 77)

>>> lena_I =lena.convert("I")

>>> lena_I.mode

'I'

>>>lena_I.getpixel((0,0))

132

>>>lena_I.getpixel((0,1))

131

>>> lena_L =lena.convert("L")

>>>lena_L.getpixel((0,0))

132

>>>lena_L.getpixel((0,1))

131

 

從實驗的結果看,模式“I”與模式“L”的結果是完全一樣,只是模式“L”的像素是8bit,而模式“I”的像素是32bit

8、 模式“F

模式“F”爲32位浮點灰色圖像,它的每個像素用32bit表示,0表示黑,255表示白,(0,255)之間的數字表示不同的灰度。在PIL中,從模式“RGB”轉換爲“F”模式是按照下面的公式轉換的:

F = R * 299/1000+ G * 587/1000 + B * 114/1000

下面我們將模式爲“RGB”的lena圖像轉換爲“F”圖像。

例子:


>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>>lena.getpixel((0,0))

(197, 111, 78)

>>>lena.getpixel((0,1))

(196, 110, 77)

>>> lena_F =lena.convert("F")

>>> lena_F.mode

'F'

>>>lena_F.getpixel((0,0))

132.95199584960938

>>>lena_F.getpixel((0,1))

131.95199584960938

 

模式“F”與模式“L”的轉換公式是一樣的,都是RGB轉換爲灰色值的公式,但模式“F”會保留小數部分,如實驗中的數據。

(未完待續)

發佈了58 篇原創文章 · 獲贊 156 · 訪問量 70萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章