用PIL實現帶旋轉字元的驗證碼生成

2021-10-10 02:02:53 字數 3778 閱讀 2093

在學習pil中,我們可能會去生成隨機字元驗證碼,新增直線、選字元這些都是比較簡單的操作,但如何將我們隨機生成的字元旋轉起來,是相較複雜一點的。就我目前了解,可以使用numpy的陣列操作,或是直接用opencv解決。本文主要通過pil的模組對字元實現旋轉,主要方法是image.composite(),建議大家可以先了解一下這個方法。

目前,pil中的rotate方法只能針對進行操作,而imagedraw中的text()方法不能控制字元的方向。所以我的思路是,將字元旋轉後的設為rgba模式,將alpha通道設定為比較小的數,以此在合成時,字元以外的背景不會覆蓋之前生成的字元。通過迴圈將旋轉後的字元依次放入一張白色背景的圖,每次生成的旋轉圖作為下一次合成的背景板,這樣我們就得到了一張「rgba」格式的旋轉字元圖。

之後,我們生成一張背景馬賽克圖。

將字元圖轉化為「rgb」模式,將馬賽克背景圖「覆蓋到」字元圖上,效果如下:

詳細**:

from pil import image,imagedraw,imagefont

import numpy as np

import random

defrandomchar()

: a =

chr(random.randint(65,

90)) b =

chr(random.randint(97,

122)

) c =

str(random.randint(0,

9))return random.choice(

[a,b,c]

)def

randomcolor()

:#隨機設定某一背景畫素點的顏色

return

(random.randint(0,

255)

, random.randint(0,

255)

, random.randint(0,

255)

)def

randomcolor2()

:#隨機設定驗證碼字元或干擾直線的顏色

return

(random.randint(80,

255)

, random.randint(80,

255)

, random.randint(80,

255)

)def

randomcolor_light()

:#返回比較亮的顏色

return

(random.randint(

123,

255)

, random.randint(

123,

255)

, random.randint(

123,

255)

)def

randomcolor_dark()

:#返回比較暗的顏色

return

(random.randint(0,

100)

, random.randint(0,

100)

, random.randint(0,

100)

)def

randomline

(img,n)

:#在圖上任意位置畫n條線

draw = imagedraw.draw(img)

for i in

range

(n):

draw.line(

(random.randint(

0,img.width-1)

,random.randint(

0,img.height-1)

, random.randint(

0,img.width-1)

,random.randint(

0,img.height-1)

),fill=randomcolor2(

),width=2)

return img

font = imagefont.truetype(

"msyh.ttc",40

)#設定顯示的字元字型,需要將對應的字型檔案放到同級目錄

mask2 = image.fromarray(np.uint8(np.random.uniform(0,

255,

(214

,214,3

))))

distance =

0mask = image.new(

"rgba",(

240,

240),(

255,

255,

255,0)

)for i in

range(4

):s_background = image.new(

"rgba",(

240,60)

,(255,

255,

255,0)

)#alpha通道設為0,保證透明度

s_draw = imagedraw.draw(s_background)

s_draw.text((5

+distance,5)

,randomchar(

),font=font,fill=randomcolor_dark())

s_rotate = s_background.rotate(random.randint(-60

,60),expand=1)

#影象會轉動隨機的角度

mask.resize(s_rotate.size)

out1 = image.composite(s_rotate, mask, s_rotate)

#第一次復合生成的是旋轉後去黑色背景

mask = out1

distance = distance+random.randint(-30

,30)+

50#修改下次字元繪畫的初始位置

out1 = out1.convert(

"rgb"

)mask2.resize(out1.size)

r,g,b = mask2.split(

)out2 = image.composite(mask2,out1,r)

#將我們生成的隨機馬賽克覆蓋到旋轉字元上去

out2 = randomline(out2,4)

out2.show(

)

總結:單用pil可以,但是存在一些明顯的缺點,1.在合成最終時,馬賽克背景某一顏色通道會消失(存疑),導致最後背景效果不好。2.由於我們用的是composite方法,最後字元上會存留背景的畫素點(機器更難識別?),而且該方法需要我們合成的兩張大小一致,所以整張圖的大小會隨著迴圈的變化而變化,一般情況下,字元不會在同一水平位置,用numpy陣列操作可以改進。3.當字元顏色較亮時,可能會很難識別出驗證碼。

用PHP實現驗證碼功能

我們這裡展示了如何編寫php程式實現驗證碼功能 一 filename authpage.php author hutuworm date 2003 04 28 copyleft hutuworm.org srand double microtime 1000000 驗證使用者輸入是否和驗證碼一致 生...

用PHP實現驗證碼功能

目前,不少 為了防止使用者利用機械人自動註冊 登入 灌水,都採用了 驗證碼技術。所謂驗證碼,就是將一串隨機產生的數字或符號,生成一幅,裡加上一些干擾象素 防止ocr 由使用者肉眼識別其中的驗證碼資訊,輸 入表單提交 驗證,驗證成功後才能使用某項功能。我們這裡展示了如何編寫php程式實現驗證碼功能 一...

用Python實現隨機驗證碼

0.說明 在網路上各種平台上登陸時,都會看到各種各樣的驗證碼,大部分都是字母 數字的隨機驗證碼,下面來主要是通過python生成乙個可以包含大小寫字母和數字的隨機驗證碼。1.思路 在python中,內建函式chr可以將相應的0 255的數字轉換為相應的字元,而ord則可以將字元碼轉換為相應的asci...