Python PIL創建文字圖片


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到統一大小,代碼中的字符圖像類生成的圖像其實會根據字體大小自動設定)

image

當然,生成這種測試圖像也不一定就非得用PIL或者python,matlab中應該也可以,其實也就是先生成一個空的圖像矩陣,然后調用寫字符的函數在這個空圖像上以特定的字體寫上字符串罷了。

使用漢字字體時要注意的問題:

一般的做法是在文件開頭的位置加上#-*- coding:gb2312 -*- 指定使用中文編碼。這樣一般不會有錯。但有時可能我們需要對部分字符串轉換編碼,這時我們可利用字符對象的encode、decode方法。encode是對當前字符使用指定的編碼方案重新編碼。decode是使用指定的編碼方案進行解碼。兩者都是碼制的轉換,但使用時往往容易弄錯。encode其實是對本身為unicode的字符使用指定的編碼方案進行編碼,而decode則是使用指定編碼將字符解碼為unicode編碼。所以在使用encode時,如果本身不是unicode碼就會出錯,在使用decode時,如果不知道本身所使用的編碼方案也會出錯.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM