跳至內容

Python/Image

維基教科書,自由的教學讀本

在Python 2使用PIL包,在Python 3使用pillow包。後者是前者的衍生版本。採用相同的包名導入:

from PIL import Image

Image類

[編輯]
  • im=Image.open(filename,mode)(打開一張圖像)
  • im.show()
  • im.size
  • im.format #JPEG,PNG等格式
  • im.mode #RGB,HSV,L,CMYK
  • im.save(filename,format)(保存指定格式的圖像)
  • im.thumbnail(size,resample)(創建縮略圖)
  • im.crop( (left,top,right,down) )
  • im.transpose(method)(圖像翻轉或者旋轉)
  • img.rotate(45)#逆時針旋轉45度
  • im.paste(anotherImg,box,mask)(將一個圖像粘貼到另一個圖像)
  • r,g,b = im.split() 顏色通道分離
  • im_merge = Image.merge("RGB",[b,r,g]) 顏色通道合併
  • im.resize(size,resample,box) size是轉換之後的大小,resample是重新採樣使用的方法,仍然有Image.BICUBIC,PIL.Image.LANCZOS,PIL.Image.BILINEAR,PIL.Image.NEAREST這四種採樣方法,默認是PIL.Image.NEAREST,box是指定的要resize的圖像區域
  • im.convert(mode,matrix,dither,palette,colors) 可以改變圖像的mode,一般是在'RGB'(真彩圖)、'L'(灰度圖)、'CMYK'(壓縮圖)之間轉換
  • im.filter(filter) filter是過濾器函數,在PIL.ImageFilter函數中定義了大量內置的filter函數,比如BLUR(模糊操作),GaussianBlur(高斯模糊),MedianFilter(中值過濾器),FIND_EDGES(查找邊)等
  • im.point(lut,mode)(對圖像像素操作)lut是對單個像素點操作的函數。 mode是返回的圖像的模式,默認是和原來圖像的mode是一樣

mode:

  • · 1 (1-bit pixels, black and white, stored with one pixel per byte)
  • · L (8-bit pixels, black and white)
  • · P (8-bit pixels, mapped to any other mode using a colour palette)
  • · RGB (3x8-bit pixels, true colour)
  • · RGBA (4x8-bit pixels, true colour with transparency mask)
  • · CMYK (4x8-bit pixels, colour separation)
  • · YCbCr (3x8-bit pixels, colour video format)
  • · I (32-bit signed integer pixels)
  • · F (32-bit floating point pixels)

ImageEnhance類

[編輯]

用於圖像增強,比如增加亮度(Brightness),增加對比度(Contrast)等。

from PIL import ImageEnhance
brightness = ImageEnhanBce.Brightness(im)
im_brightness = brightness.enhance(1.5)
im_brightness.show()
im_contrast = ImageEnhance.Contrast(im)
im_contrast.enhance(1.5) 
im_contrast.enhance(1.5).show()

ImageSequence

[編輯]

下面的代碼可以遍歷gif圖像中的所有幀,並分別保存為圖像

>>> from PIL import ImageSequence
>>> from PIL import Image 
>>> gif = Image.open("pipixia.gif")
>>> for i,frame in enumerate(ImageSequence.Iterator(gif),1):
...     if frame.mode == 'JPEG':
...         frame.save("%d.jpg" %i)
...     else:
...         frame.save("%d.png" % i)

除了上面使用迭代器的方式以外,還可以一幀一幀讀取gif,比如下面的代碼:

>>> index = 0
>>> while 1:
...     try:
...         gif.seek(index)
...         gif.save("%d.%s" %(index,'jpg' if gif.mode == 'JPEG' else 'png'))
...         index += 1
...     except EOFError:
...         print("Reach the end of gif sequence!")
...         break

上面的代碼在讀取到gif的最後一幀之後,會throw 一個 EOFError,所以我們只要捕獲這個異常就可以了。

添加文字水印

[編輯]
from PIL import Image, ImageDraw,ImageFont
im = Image.open("d:/pic/lena.jpg").convert('RGBA')
txt=Image.new('RGBA', im.size, (0,0,0,0))
fnt=ImageFont.truetype("c:/Windows/fonts/Tahoma.ttf", 20)
d=ImageDraw.Draw(txt)
d.text((txt.size[0]-80,txt.size[1]-30), "cnBlogs",font=fnt, fill=(255,255,255,255))
out=Image.alpha_composite(im, txt)
out.show()

#添加小图片水印
from PIL import Image
im = Image.open("d:/pic/lena.jpg")
mark=Image.open("d:/logo_small.gif")
layer=Image.new('RGBA', im.size, (0,0,0,0))
layer.paste(mark, (im.size[0]-150,im.size[1]-60))
out=Image.composite(layer,im,layer)
out.show()

PIL Image 圖像互轉 numpy 數組

[編輯]
im_array = np.array(im)
# 也可以用 np.asarray(im) 区别是 np.array() 是深拷贝,np.asarray() 是浅拷贝

#numpy 查看图片信息,可用如下的方法
print img.shape  
print img.dtype 

#将 numpy 数组转换为 PIL 图片
#这里采用 matplotlib.image 读入图片数组,注意这里读入的数组是 float32 型的,范围是 0-1,而 PIL.Image 数据是 uinit8 型的,范围是0-255,所以要进行转换:
import matplotlib.image as mpimg
from PIL import Image
lena = mpimg.imread('lena.png') # 这里读入的数据是 float32 型的,范围是0-1
im = Image.fromarray(np.uinit8(lena*255))
im.show()

#PIL image 查看图片信息,可用如下的方法
print type(img)
print img.size  #图片的尺寸
print img.mode  #图片的模式
print img.format  #图片的格式
print(img.getpixel((0,0))[0])#得到像素:
#img读出来的图片获得某点像素用getpixel((w,h))可以直接返回这个点三个通道的像素值

讀取指定文件夾下的所有圖像

[編輯]
'''
Load the image files form the folder
input:
    imgDir: the direction of the folder
    imgName:the name of the folder
output:
    data:the data of the dataset
    label:the label of the datset
'''
def load_Img(imgDir,imgFoldName):
    imgs = os.listdir(imgDir+imgFoldName)
    imgNum = len(imgs)
    data = np.empty((imgNum,1,12,12),dtype="float32")
    label = np.empty((imgNum,),dtype="uint8")
    for i in range (imgNum):
        img = Image.open(imgDir+imgFoldName+"/"+imgs[i])
        arr = np.asarray(img,dtype="float32")
        data[i,:,:,:] = arr
        label[i] = int(imgs[i].split('.')[0])
    return data,label

圖像打印

[編輯]

Python映像庫包括用於在Postscript打印機上打印圖像、文本和圖形的函數

from PIL import Image
from PIL import PSDraw

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