以Python Imaging Library 進行影像資料處理PIL

來源:互聯網
上載者:User

 

1   影像與圖形資料的處理

 

討論圖形(影像) 本身的處理,而討論的內容將會集中在Python Imaging Library (PIL) 這一套程式庫上。

PIL 是Python 下最有名的影像處理套件,由許多不同的模組所組成,並且提供了許多的處理功能,允許我們在簡單的Python 程式裡進行影像的處理。 使用像PIL 許樣的程式庫套件可以協助我們把精力集中在影像處理的工作本身,避免迷失在底層的演算法裡面。

由於影像處理牽涉到了大量的數學運算,因此PIL 中有許多的模組是用C 語言所寫成的,以提升處理的效率。 不過,在使用的時候,我們當然不必在意這樣的問題,只管放心地用就是了。

1.1   PIL 能為你作的事

PIL 具備(但不限於) 以下的能力:

  • 數十種圖檔格式的讀寫能力。 常見的JPEG, PNG, BMP, GIF, TIFF 等格式,都在PIL 的支援之列。 另外,PIL 也支援黑白、灰階、自訂調色盤、RGB true color、帶有透明屬性的RBG true color、CMYK 及其它數種的影像模式。相當齊全。
  • 基本的影像資料操作:裁切、平移、旋轉、改變尺寸、調置(transpose)、剪下與貼上等等。
  • 強化圖形:亮度、色調、對比、銳利度。
  • 色彩處理。
  • PIL 提供十數種濾鏡(filter)。 當然,這個數目遠遠不能與Photoshop 或GIMP 這樣的專業特效處理軟體相比;但PIL 提供的這些濾鏡可以用在Python 程式裡面,提供批次化處理的能力。
  • PIL 可以在影像中繪圖制點、線、面、幾何形狀、填滿、文字等等。

接下來,我們開始一步一步地對Python/PIL 的影像處理程式設計進行討論。

2   轉換圖檔格式

市面上有許多影像處理程式,一般人最常用它們來處理的工作大概就是圖檔格式轉換了;這是影像處理軟體最基本的功能,PIL 當然也要支援。

假設我們有一個JPG檔案,名字叫作 sample01.jpg,那麼,以下的程式會把這個檔案載入Python:

“”>“匯入映像”>“”(在= Image.open“sample01.jpg”)

im 這個物件是由 Image.open() 方法所產生出來的 Image 物件。 我們可以用 Image 物件內的屬性來查詢關於此檔案的資訊:

“”>“列印im.format,im.size,im.mode的JPEG(2288,1712)的RGB

格式字串放在 format 屬性裡,尺寸放在 size 屬性裡,而(調色盤)模式放在 mode 屬性裡。 從以上的執行結果,可以看出來我們讀的確實是一個JPEG檔案,檔案的尺寸是2288像素寬、1712像素高,調色盤是RGB全彩模式。

既然我們已經把圖檔讀入了Python,要處理它就簡單了。 利用Image類別的 save() 方法,可以把檔案儲存成PIL支援的格式:

“”“im.save(”fileout.png“)

如果圖檔很大,這會花上一點時間。Image.save() 方法會根據欲存檔的副檔名,自動判斷要存圖檔的格式(剛剛我們用的 open() 函式也會這樣作)。

save() 可以指定存檔格式。 在以下的例子裡,我們把存檔格式指定為JPEG:

“”“im.save(”fileout.png“,”JPEG格式“)

這時候副檔名是無所謂的。

只處理一兩個檔案的時候,使用Python 直譯器就相當合適。 然而若要處理一大群檔案,譬如把一整個目錄的JPEG 檔轉換為PNG 檔,那麼寫成一個程式檔會比較方便,例如:

#!/ usr /斌/從來自世界os.path進口映像匯入splitext世界jpglist =全球環境保護的python進口(“python_imaging_pix / *. [JJ] [頁] [千兆]”)在jpglist JPG格式:即時=映像。開放(JPG格式)巴布亞新畿內亞= splitext(JPG格式)[0] +“。巴布亞新畿內亞”im.save(巴新)印刷巴新

只要在一個放了 *.jpg 或 *.JPG 檔案的目錄裡面執行這個指令稿,它就會把所有的JPEG檔轉成PNG檔案:

$。/ convertdir.py file0001.png file0002.png。。file9999.png

既然PIL 會從檔名偵測常用的檔案格式,存檔時我們通常都不會指定存檔格式。

然而,依據檔案格式的不同,save() 方法提供了不同的選項參數。 以JPEG而言,它可以接受 quality (從1到100的整數,預設為75)、optimize (真假值)及 progression (真假值)。 在以下的例子裡,我們以100的 quality 來儲存JPEG檔案:

“”“im.save(”quality100.jpg“,品質= 100)

要訣

PIL 也支援EPS (Encapsulate PostScript) 格式的寫入。 TeX 的使用者可以利用PIL 來簡單地把圖檔轉成EPS 以供TeX compiler 使用。

3   改變影像與製作縮圖

在瞭解了基本的圖檔轉換之後,我們來看看如何對影像進行尺寸方面的修改。 PIL對 Image 物件提供了 resize 方法,以執行影像的縮放工作。 用我們的 sample01.jpg 檔案來當例子:

“”“進出口= Image.open(sample01.jpg ")>>>印刷im.size(2288,1712)”“”寬度= 400“”“浮動的比例=(寬)/ im.size [0]” “”高度=廉政(im.size [1] *比率)“”“它im.resize =((寬,高),Image.BILINEAR)”“>”列印nim.size(400,299)“”“它。儲存(“resized.jpg)

然後我們就會得到比較小的 resized.jpg:

resize() 這個方法會傳回一個新的Image物件,所以舊的Image不會被更動。resize() 接受兩個參數,第一個用來指定變更後的大小,是一個雙元素tuple,分別用以指定影像的寬與高;第二個參數可以省略,是用來指定變更時使用的插入法,預設是 Image.NEAREST (取最近點),這裡我們指定為品質比較好的 Image.BILINEAR。

resize() 可以把影像放大縮小,在使用時一定要傳入寬與高。 上面的程式會先限定新影像的寬,再根據舊影像的長寬比例來算出新影像的高應該是多少,最後把尺寸值傳入 resize() 去。 由此可知,resize() 是允許我們不等比例縮放的:

“”“寬度= 400”“”高度= 100“”“nim2 = im.resize((寬,高),Image.BILINEAR)”“”nim2.save(“resize2wide.jpg”)

會得到形狀奇怪的縮圖:

我們可以任意改變新影像的尺寸值。

另一個常用的操作是旋轉;rotate() 方法可以用來旋轉影像。 它取兩個參數,第一個參數是一個逆時針的度數,第二個參數則也是影像處理時的插入法,可省略:

“”“nim3 = nim.rotate(45歲,Image.BILINEAR)”“”nim3.save(“rotated.jpg”)

rotate() 並不會改變影像的尺寸(dimension),所以你會看到:

出現了黑邊。 如果我們想要連影像尺寸一起變動,得要改用 transpose() 方法:

“”“nim4 = nim.transpose(Image.ROTATE_90)”“”nim4.save(“transposed90.jpg”)

永恒的結果:

transpose() 方法接受 Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_DOWN, ROTATE_90, ROTATE_180, ROTATE_270 等五種參數;其中後三種的旋轉均為逆時針。rotate() 方法會對像素資料進行插入;而 transpose() 則只是轉置像素資料,所以沒有插入參數可以設定,也不會影響影像的品質。

縮放與旋轉是最常用的兩個操作,而在其中,縮圖的製作可能是特別常用的;PIL對縮圖提供了一個方便的thumbnail() 方法。thumbnail() 會直接修改Image物件本身,所以速度能比 resize() 更快,也消耗更少的記憶體。 它不接受指定插入法的參數,而且只能縮小影像,不能放大影像;用法是:

(“”“進出口= Image.open”sample01.jpg ")>>> im.thumbnail((400.100 ))>>> im.save(“thumbnail.jpg ")>>>列印im.size(133,100 )

thumbnail() 在接受尺寸參數的時候,行為與 resize() 不同;resize() 允許我們不等比例進行縮放,但 thumbnail()只能進行等比例縮小,並且是以長、寬中比較小的那一個值為基準。 因此,上面的程式所作出的 thumbnail.jpg 變成了133*100的小圖片:

有了這些操作,我們可以很輕易地執行影像管理的任務。

4   修改圖形內容

除了可以針對圖形的尺寸作變更之外,PIL 更提供我們變更影像內容的能力。 這樣,我們就不只能對影像進行管理,而能更進一步地利用程式來把影像的內容改成我們想要的樣子。

我們從「貼圖」開始:

“”“Baseim = Image.open(”resized.jpg ")>>> floatim = Image.open(“thumbnail.jpg ")>>> baseim.paste(floatim,(150,50 ))>>> baseim。儲存(“pasted.jpg”)

利用 paste() 方法,把之前作的 thumbnail.jpg 貼到 resized.jpg 裡面去:

此種用法的 paste() 方法要求兩個參數,第一是要貼上的Image,第二是要貼上的位置。 第二個參數有三種指定的方式:

  • None:不指定位置與尺寸,那麼 pasted() 會假設要貼上的Image與被貼上的Image的尺寸完全相同。
  • (left, upper):雙元素tuple。pasted() 會把要貼上的Image的左上方對齊在指定的位置。
  • (left, upper, right, lower):四元素tuple。paste()` 除了會把Image的左上方對齊外,也會對齊右下角。 不過基本上這種寫法和上面那一種一樣,因為 paste() 要求要貼上的影像與這裡指定的尺寸一致,所以不可能出現不同的兩組right, lower。

除了「貼圖」之外,我們還可以對影像的內容進行裁切:

“”“進出口= Image.open(sample01.jpg ")>>>它im.crop =((700,300,1500,1300 ))>>> nim.thumbnail((400.400 ))>>>它。儲存(“croped.jpg)

(因為裁切之後的圖形還是大了點,所以再縮圖一次) 得到的結果是:

crop() 接受的 box 參數指定要裁切的左、上、右、下四個邊界值,形成一個矩形。

除了剪貼之外,PIL還可以使用內建的濾鏡(filter)作一些特效處理。 這些濾鏡都放在 ImageFilter 模組裡面,使用前要先匯入這個模組:

>>> import ImageFilter

我們用個例子,對剛剛裁切的"No Riding" 禁止牌作20 次blur (糊化),來看看PIL 濾鏡的效果:

“”“進出口= Image.open(croped.jpg ")>>>它=他們”“”在範圍I(20):它= nim.filter(ImageFilter.BLUR)...>>>它。儲存(“blured.jpg)

你應該看不出來它是"No Riding" 了吧:

使用濾鏡的基本文法是:

newim = im.filter(ImageFilter.FILTERNAME)

其中 FILTERNAME 是PIL中支援的濾鏡名稱,目前有:BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, SMOOTH, SMOOTH_MORE, SHARPEN,此處就不一一介紹了,但建議你可以自己來把每一個濾鏡都試試看。

利用濾鏡,我們可以對同一類的影像進行相同的特效處理。 當然,影像特效需要很精細的調整,在自動化作業中通常只能達到很粗略的效果;但PIL 既然提供了,我們的Bot就擁有更多的工具可以使用。

5 生產的新畫滾動太平

除了對已存在的影像進行編修之外,從零開始建立新影像也是很重要的工作。 PIL中的 ImageDraw 模組提供給我們繪製影像內容的能力。 在使用 ImageDraw 之前,要先建立好空白的新影像:

“”>“匯入ImageDraw”“在Image.new”=(為“RGB”,(400.300 ))>>>提請= ImageDraw.Draw(中)

最後建出來的 draw 是一個 ImageDraw 物件會提供各種繪製影像的方法。 針對幾何圖形,draw 物件提供 arc() (弧線)、chord() (弦)、line() (線段)、ellipse() (橢圓)、point() (點)、rectangle() (矩形)與 polygon () (多邊形)。 不過,我們不準備討論幾何圖形的繪製;相信這些方法的使用對一般人來說應該都很直覺才是。

要訣

你可以在指令行輸入 pydoc ImageDraw.ImageDraw.<<methodname>> 來查詢上述方法(<<methodname>>)的說明,譬如 pydoc ImageDraw.ImageDraw.line。

這裡要介紹的不是幾何圖形,而是文字的繪製。 我們要再介紹一個模組:ImageFont,並且以執行個體來說明如何用PIL 「寫字」:

“”>“匯入映像,ImageDraw,ImageFont”“”字型= ImageFont.truetype(/ ...“/ usr /共用/ fonts /中的TrueType / freefont /”,24)“”“在Image.new FreeMono.ttf =(為“RGB”,(400.300 ))>>>提請= ImageDraw.Draw(中)“”“draw.text((20.20),”文本“,字型=字型)”“”im.save(文本“。 JPG格式“)

這樣就在一個黑色底圖上用白筆寫了"TEXT" 四個大字:

接著一一說明剛剛作的動作。 首先我們用 ImageFont 的 truetype() 函式建立了一個TrueType字型,大小設定為16點。truetype() 函式的第一個參數必須是字型檔的搜尋路徑,第二個參數是字型的點數。 然後依序建立影像物件與draw 物件。 寫字的動作用 draw 物件的 text() 方法來完成,它接受兩個參數,分別是文字的左上方點、字串,另外可以用 font 選項來指定所使用的字型(若不指定,便使用預設字型)。

在1.1.4 版之前,PIL 是只能使用點陣字型的。 現在PIL 加入了TrueType 向量字型的支援,對於要「寫字」的人來說實在是一大福音。 對點陣字來說,想改變字型的大小得要更換字型才作得到,但TrueType 就沒有這個限制。 如果我們想要寫出兩串不同大小的文字,這樣作就可以了:

“”“Largefont = ImageFont.truetype(/ ...”/ usr /共用/ fonts /中的TrueType / freefont / FreeMono.ttf“,48)”“”smallfont ImageFont.truetype =(/ ...“/ usr /共用/ fonts /中的TrueType / freefont /“,24)”“”在Image.new =(“皇家植物園”(400.300 FreeMono.ttf ))>>>提請= ImageDraw.Draw(中)“”“draw.text(( 20:20),“小文”字型= smallfont)“”“draw.text((20.120),”大文字“,字型= largefont)”“”im.save(“multitext.jpg”)

秋之結果:

以上就是在PIL 裡建立文字圖形的方法。

最後,我們要說明如何改變繪製圖形(文字)時的顏色;繪圖時畫筆的顏色是透過 draw 物件的 ink 屬性來改變的:

“”“draw.ink = 0 + 255 * 256 + 0 * 256 * 256

以上會把畫筆設成綠色。ink 值必須要是一個整數,其值由色彩的RGB值算出。 舉幾個 ink 值的例子:

  • 紅色的 ink 值應設為 255(R) + 0(G)*256 + 0(B)*256*256,
  • 藍色的 ink 值應設為 0(R) + 0(G)*256 + 255(B)*256*256,
  • 靛色的 ink 值應設為 0(R) + 255(G)*256 + 255(B)*256*256

所設定的 ink 會影響所有後續的繪圖動作。

6結論

本文介紹了方便好用的PIL 套件,可以讓我們用Python 撰寫影像處理的程式。 我們對圖檔的格式處理、尺寸處理以及內容的編修都作了討論,最後也說明如何從零開始創作一個影像。

對網頁程式來說,動態產生簡單的影像是特別有用的功能,可以用來補足HTML 與CSS 的不足之處。 利用PIL 來執行批次影像處理的工作,更能省去我們許多的操作時間。 相信讀者能從其中發現它所提供的生產力。

在下一期的內容裡,我們要開始介紹Python 的網頁程式設計。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.