近來在學慣用Python作些影像處理的工作,不斷被Python開發的高效率所震撼,而且也感覺到了開發人員對運行期效率的重視,不僅在我使用2.5版本時明顯感到比原來的2.4版本效率高,就連PIL的新版本中也針對映像的像素操作效率進行了很大的改善。
PIL中效率的改善主要來自於Image模組中的load函數,這個函數是在PIL 1.1.6版本中新增加的,相比於原來的getpixel與putpixel函數,主要的目的就是通過提供映像的快取作業對象,提高對映像資料讀寫操作的效率。
這裡可以通過一個簡單的樣本對比兩種操作方式的差異,首先開啟一個圖片檔案,同時建立一個相同大小的圖片,然後將原始圖片的資料逐像素的拷貝到新的圖片中,代碼如下。該代碼在我的機器上運行,對於映像解析度為2048*1536的圖片,只需要5秒鐘,而如果採用getpixel與putpixel函數實現(迴圈體中注釋掉的代碼),則需要25秒鐘,可見load函數對於效率改善非常明顯。import Image
import ImageFilter
ima = Image.open('test.jpg')
size = ima.size
imb = Image.new('RGB', size)
pima = ima.load()
pimb = imb.load()
for i in range(size[0]):
for j in range(size[1]):
pimb[i,j] = pima[i,j] #primb.putpixel((i,j), pima.getpixel((i,j)))
imb.save('test.bmp')
此外,需要提到的是,通過load函數實現的對資料讀寫加速的辦法,已經在PIL的內部非常普遍的使用,比如在Image模組算是比較耗時的filter函數,就已經利用資料緩衝對象來提高效率。Image.filter函數的定義如下: def filter(self, filter):
"Apply environment filter to image"
self.load()
from ImageFilter import Filter
if not isinstance(filter, Filter):
filter = filter()
if self.im.bands == 1:
return self._new(filter.filter(self.im))
# fix to handle multiband images since _imaging doesn't
ims = []
for c in range(self.im.bands):
ims.append(self._new(filter.filter(self.im.getband(c))))
return merge(self.mode, ims)