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 -*-fromPILimportImage,ImageDraw,ImageFont,ImageOpsimportnumpy as npimportrandomclassLetterImage():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)defGenLetterImage(self,letters):'''Generate the Image of letters'''self.letters=letters
(self.letterWidth,self.letterHeight)=self.font.getsize(letters)ifself.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)/2textY0=int(textY0)
textX0= int((self.imgWidth-self.letterWidth+1)/2)PRint'text location:',(textX0,textY0)print'text size (width,height):',self.letterWidth,self.letterHeightprint'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)defSaveImg(self,saveName=''):if''==saveName.strip():
saveName= str(self.letters.encode('gb2312'))+'.png'fileName,file_format= saveName.split('.')
fileName+='_'+str(self.fontsize)+'.'+file_formatprintfileName,file_format
self.img.save(fileName, file_format)defShow(self):
self.img.show()defclearpictures():importos
png=os.listdir(os.curdir)foriinpng:ifos.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= 2svd_u=[]
svd_s=[]
svd_v=[]importcv2
mergeImg= np.zeros((470,444))
npareiImg=[]foriinrange(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])printuDifNorm
vDifNorm= np.linalg.norm(svd_v[0]-svd_v[1])printvDifNorm
sDifNorm= np.linalg.norm(svd_s[0]-svd_s[1])printsDifNorm
ou_norm= np.linalg.norm(np.asarray(npareiImg[0])-np.asarray(npareiImg[1]))printou_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'printstr_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时,如果不知道本身所使用的编码方案也会出错.