PIL庫中包含了很多模塊,恰當地利用這些模塊可以做許多圖像處理方面的工作。
下面是我用來生成字母或字符串測試圖片而寫的類及測試代碼。
主要用到的模塊:
PIL.Image,PIL.ImageDraw,PIL.ImageFont
PIL.Image用來生成一個空的圖片,ImageDraw用來在空圖片上畫圖及寫字符,ImageFont則是創建需要使用到的字體
主要用到的代碼:
#創建一個空的圖片 self.img = Image.new(self.imgMode, self.imgSize, self.bg_color) self.drawBrush = ImageDraw.Draw(self.img)#創建畫刷,用來寫文字到圖片img上 #創建字體,fontFile為字體文件,若非系統字體需加詳細路徑 self.font = ImageFont.truetype(fontFile,fontsize) #使用特定字體寫字,(textX0,textY0)為文字開始的左上角起始位置 self.drawBrush.text((textX0,textY0), self.letters, fill=self.fg_color,font=self.font)
詳細代碼:
#-*- coding:gb2312 -*- from PIL import Image,ImageDraw,ImageFont,ImageOps import numpy as np import random class LetterImage(): def __init__(self,fontFile='',imgSize=(0,0),imgMode='RGB',bg_color=(0,0,0),fg_color=(255,255,255),fontsize=20): self.imgSize = imgSize self.imgMode = imgMode self.fontsize = fontsize self.bg_color = bg_color self.fg_color = fg_color # self.font = ImageFont.load('車牌字體.ttf') if ''==fontFile: self.font = ImageFont.truetype('DIN1451.ttf', fontsize) else: self.font = ImageFont.truetype(fontFile,fontsize) def GenLetterImage(self,letters): '''Generate the Image of letters''' self.letters = letters (self.letterWidth,self.letterHeight) = self.font.getsize(letters) if self.imgSize==(0,0): self.imgSize=(self.letterWidth+2,self.letterHeight+2) self.imgWidth,self.imgHeight=self.imgSize self.img = Image.new(self.imgMode, self.imgSize, self.bg_color) self.drawBrush = ImageDraw.Draw(self.img) textY0 = (self.imgHeight-self.letterHeight+1)/2 textY0 = int(textY0) textX0 = int((self.imgWidth-self.letterWidth+1)/2) print 'text location:',(textX0,textY0) print 'text size (width,height):',self.letterWidth,self.letterHeight print 'img size(width,height):',self.imgSize # if textX0<0 or textY0<0: # raise Exception('size error text location x0:%d,y0:%d'%(textX0,textY0)) self.drawBrush.text((textX0,textY0), self.letters, fill=self.fg_color,font=self.font) def SaveImg(self,saveName=''): if ''==saveName.strip(): saveName = str(self.letters.encode('gb2312'))+'.png' fileName,file_format = saveName.split('.') fileName+='_'+str(self.fontsize)+'.'+file_format print fileName,file_format self.img.save(fileName, file_format) def Show(self): self.img.show() def clearpictures(): import os png = os.listdir(os.curdir) for i in png: if os.path.splitext(i)[1]==".png": os.remove(i) if __name__=='__main__': letterList = [] letterList.append(LetterImage(bg_color=(0,0,255),fontsize=10)) letterList.append(LetterImage(fontFile='',bg_color=(0,0,255),fontsize=400)) letter=[u'u',u'v'] num_letter = 2 svd_u=[] svd_s=[] svd_v=[] import cv2 mergeImg = np.zeros((470,444)) npareiImg =[] for i in range(num_letter): letterList[i].GenLetterImage(letter[i]) # letterList[i].Show() # letterList[i].SaveImg() grayImg = ImageOps.grayscale(letterList[i].img) grayImg = grayImg.resize((222,470),resample=Image.BICUBIC) npareiImg.append( np.asarray(grayImg)) cv2.namedWindow('%s'%i) cv2.imshow('%s'%i, npareiImg[i]) mergeImg[0:470,i*222:(i+1)*222]=npareiImg[i] u,s,v=np.linalg.svd(npareiImg[i]) print 'u and img \'s shape',u.shape,npareiImg[i].shape svd_u.append(u) svd_v.append(v) svd_s.append(s) # mergeImgNp=Image.fromarray(mergeImg)#, mode) # mergeImgNp.show() uDifNorm=np.linalg.norm(svd_u[0]-svd_u[1]) print uDifNorm vDifNorm = np.linalg.norm(svd_v[0]-svd_v[1]) print vDifNorm sDifNorm = np.linalg.norm(svd_s[0]-svd_s[1]) print sDifNorm ou_norm = np.linalg.norm(np.asarray(npareiImg[0])-np.asarray(npareiImg[1])) print ou_norm f=open('record.txt','a') lines=[] lines.append('letters: %s,%s'%(letter[0],letter[1])) lines.append('SVD u diff norm:\t%f'%uDifNorm) lines.append('SVD v diff norm:\t%f'%vDifNorm) lines.append('SVD s diff norm:\t%f'%sDifNorm) lines.append('Ou norm: \t%f'%ou_norm) str_to_write='\n'.join(lines)+'\n' print str_to_write f.write(str_to_write) f.close() cv2.waitKey()
上面的測試后部分是對圖像做SVD變換的一點實驗。
顯示的結果(圖像已經被resize到統一大小,代碼中的字符圖像類生成的圖像其實會根據字體大小自動設定)
當然,生成這種測試圖像也不一定就非得用PIL或者python,matlab中應該也可以,其實也就是先生成一個空的圖像矩陣,然后調用寫字符的函數在這個空圖像上以特定的字體寫上字符串罷了。
使用漢字字體時要注意的問題:
一般的做法是在文件開頭的位置加上#-*- coding:gb2312 -*- 指定使用中文編碼。這樣一般不會有錯。但有時可能我們需要對部分字符串轉換編碼,這時我們可利用字符對象的encode、decode方法。encode是對當前字符使用指定的編碼方案重新編碼。decode是使用指定的編碼方案進行解碼。兩者都是碼制的轉換,但使用時往往容易弄錯。encode其實是對本身為unicode的字符使用指定的編碼方案進行編碼,而decode則是使用指定編碼將字符解碼為unicode編碼。所以在使用encode時,如果本身不是unicode碼就會出錯,在使用decode時,如果不知道本身所使用的編碼方案也會出錯.