PIL库中包含了很多模块,恰当地利用这些模块可以做许多图像处理方面的工作。
下面是我用来生成字母或字符串测试图片而写的类及测试代码。
主要用到的模块:
PIL.Image,PIL.ImageDraw,PIL.ImageFont
PIL.Image用来生成一个空的图片,ImageDraw用来在空图片上画图及写字符,ImageFont则是创建需要使用到的字体
#-*- 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时,如果不知道本身所使用的编码方案也会出错.