本文目錄一覽:
python怎麼生成隨機圖形驗證碼
1.安裝pillow模塊
pip install pillow
2.pillow模塊的基本使用
1.創建圖片
from PIL import Image
#定義使用Image類實例化一個長為400px,寬為400px,基於RGB的(255,255,255)顏色的圖片
img1=Image.new(mode=”RGB”,size=(400,400),color=(255,255,255))
#把生成的圖片保存為”pic.png”格式
with open(“pic.png”,”wb”) as f:
img1.save(f,format=”png”)
#顯示圖片
img1.show()
運行程序,程序會在py文件的同級下生成一個名為”pic.png”的小圖片,圖片長為400px,寬為400px,顏色為白色.
2.創建畫筆
#創建畫筆,用於在圖片上生成內容
draw1=ImageDraw.Draw(img1,mode=”RGB”)
3.在圖片上生成點
#在(100,100)坐標上生成一個紅點,指定的坐標不能超過圖片的尺寸
draw1.point([100,100],pill=”red”)
#在(80,80)坐標上生成一個黑點,指定的坐標不能超過圖片的尺寸
draw1.point([80,80],fill=(0,0,0))
4.在圖片上畫線
#第一個括號裏面的參數是坐標,前兩個數為開始坐標,後兩個數為結束坐標
#括號里的第二個參數指定顏色,可以直接指定,也可以用RGB來表示顏色
draw1.line((100,100,100,300),fill=”red”)
draw1.line((100,200,200,100),fill=”blue”)
運行程序,畫筆會在(100,100)到(100,300)坐標之間畫一條紅色的豎線,在(100,200)到(200,100)坐標之間畫一根藍色的斜線
5.在圖片在畫圓
#括號里的第一個參數是坐標,前兩個數為起始坐標,後兩個為結束坐標
#用這兩個坐標之間的正方形區域生成一個圓,大括號里的第二個參數為圓的開始角度
#第三個參數為圓的結束角度,0到360表示所畫的是一個完整的圓形,
#也可以指定的數字來生成一段為圓弧,最後一個參數表示顏色,也可以用RGB來表示想要的顏色
draw1.arc((100,100,300,300),0,360,fill=”red”)
draw1.arc((0,0,300,300),0,90,fill=”blue”)
6.在圖片在寫文本
#使用畫筆的text方法在圖片上生成文本
#第一個參數為坐標,第二個參數為所有生成的文本的內容
#第三個參數為文本的顏色
draw1.text([0,0],”python”,”blue”)
7.在圖片在生成指定字體的文本
#先實例化一個字體對象,第一個參數表示字體的路徑,第二個參數表示字體大小
font1=ImageFont.truetype(“One Chance.ttf”,28)
#在圖片上生成字體
#第一個括號里的參數表示坐標,第二個參數表示寫入的內容
#第三個參數表示顏色,第四個參數表示使用的字體對象
draw1.text([200,200],”linux”,”red”,font=font1)
圖片驗證碼的實例
#導入random模塊
import random
#導入Image,ImageDraw,ImageFont模塊
from PIL import Image,ImageDraw,ImageFont
#定義使用Image類實例化一個長為120px,寬為30px,基於RGB的(255,255,255)顏色的圖片
img1=Image.new(mode=”RGB”,size=(120,30),color=(255,255,255))
#實例化一支畫筆
draw1=ImageDraw.Draw(img1,mode=”RGB”)
#定義要使用的字體
font1=ImageFont.truetype(“One Chance.ttf”,28)
for i in range(5):
#每循環一次,從a到z中隨機生成一個字母或數字
#65到90為字母的ASCII碼,使用chr把生成的ASCII碼轉換成字符
#str把生成的數字轉換成字符串
char1=random.choice([chr(random.randint(65,90)),str(random.randint(0,9))])
#每循環一次重新生成隨機顏色
color1=(random.randint(0,255),random.randint(0,255),random.randint(0,255))
#把生成的字母或數字添加到圖片上
#圖片長度為120px,要生成5個數字或字母則每添加一個,其位置就要向後移動24px
draw1.text([i*24,0],char1,color1,font=font1)
#把生成的圖片保存為”pic.png”格式
with open(“pic.png”,”wb”) as f:
img1.save(f,format=”png”)
python怎麼批量提交驗證碼
現在的網頁中,為了防止機械人提交表單,圖片驗證碼是很常見的應對手段之一。這裡就不詳細介紹了,相信大家都遇到過。
現在就給出用Python的PIL庫實現驗證碼圖片的代碼。代碼中有詳細注釋。
#!/usr/bin/env python
#coding=utf-8
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
_letter_cases = “abcdefghjkmnpqrstuvwxy” # 小寫字母,去除可能干擾的i,l,o,z
_upper_cases = _letter_cases.upper() # 大寫字母
_numbers = ”.join(map(str, range(3, 10))) # 數字
init_chars = ”.join((_letter_cases, _upper_cases, _numbers))
def create_validate_code(size=(120, 30),
chars=init_chars,
img_type=”GIF”,
mode=”RGB”,
bg_color=(255, 255, 255),
fg_color=(0, 0, 255),
font_size=18,
font_type=”ae_AlArabiya.ttf”,
length=4,
draw_lines=True,
n_line=(1, 2),
draw_points=True,
point_chance = 2):
”’
@todo: 生成驗證碼圖片
@param size: 圖片的大小,格式(寬,高),默認為(120, 30)
@param chars: 允許的字符集合,格式字符串
@param img_type: 圖片保存的格式,默認為GIF,可選的為GIF,JPEG,TIFF,PNG
@param mode: 圖片模式,默認為RGB
@param bg_color: 背景顏色,默認為白色
@param fg_color: 前景色,驗證碼字符顏色,默認為藍色#0000FF
@param font_size: 驗證碼字體大小
@param font_type: 驗證碼字體,默認為 ae_AlArabiya.ttf
@param length: 驗證碼字符個數
@param draw_lines: 是否劃干擾線
@param n_lines: 干擾線的條數範圍,格式元組,默認為(1, 2),只有draw_lines為True時有效
@param draw_points: 是否畫干擾點
@param point_chance: 干擾點出現的概率,大小範圍[0, 100]
@return: [0]: PIL Image實例
@return: [1]: 驗證碼圖片中的字符串
”’
width, height = size # 寬, 高
img = Image.new(mode, size, bg_color) # 創建圖形
draw = ImageDraw.Draw(img) # 創建畫筆
def get_chars():
”’生成給定長度的字符串,返回列表格式”’
return random.sample(chars, length)
def create_lines():
”’繪製干擾線”’
line_num = random.randint(*n_line) # 干擾線條數
for i in range(line_num):
# 起始點
begin = (random.randint(0, size[0]), random.randint(0, size[1]))
#結束點
end = (random.randint(0, size[0]), random.randint(0, size[1]))
draw.line([begin, end], fill=(0, 0, 0))
def create_points():
”’繪製干擾點”’
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]
for w in xrange(width):
for h in xrange(height):
tmp = random.randint(0, 100)
if tmp 100 – chance:
draw.point((w, h), fill=(0, 0, 0))
def create_strs():
”’繪製驗證碼字符”’
c_chars = get_chars()
strs = ‘ %s ‘ % ‘ ‘.join(c_chars) # 每個字符前後以空格隔開
font = ImageFont.truetype(font_type, font_size)
font_width, font_height = font.getsize(strs)
draw.text(((width – font_width) / 3, (height – font_height) / 3),
strs, font=font, fill=fg_color)
return ”.join(c_chars)
if draw_lines:
create_lines()
if draw_points:
create_points()
strs = create_strs()
# 圖形扭曲參數
params = [1 – float(random.randint(1, 2)) / 100,
0,
0,
0,
1 – float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500
]
img = img.transform(size, Image.PERSPECTIVE, params) # 創建扭曲
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 濾鏡,邊界加強(閾值更大)
return img, strs
if __name__ == “__main__”:
code_img = create_validate_code()
code_img.save(“validate.gif”, “GIF”)
最後結果返回一個元組,第一個返回值是Image類的實例,第二個參數是圖片中的字符串(比較是否正確的作用)。
最後結果返回一個元組,第一個返回值是Image類的實例,第二個參數是圖片中的字符串(比較是否正確的作用)。
需要提醒的是,如果在生成ImageFont.truetype實例的時候拋出IOError異常,有可能是運行代碼的電腦沒有包含指定的字體,需要下載安裝。
生成的驗證碼圖片效果:
這時候,細心的同學可能要問,如果每次生成驗證碼,都要先保存生成的圖片,再顯示到頁面。這麼做讓人太不能接受了。這個時候,我們需要使用python內置的StringIO模塊,它有着類似file對象的行為,但是它操作的是內存文件。於是,我們可以這麼寫代碼:
try:
import cStringIO as StringIO
except ImportError:
import StringIO
mstream = StringIO.StringIO()
img = create_validate_code()[0]
img.save(mstream, “GIF”)
這樣,我們需要輸出的圖片的時候只要使用「mstream.getvalue()」即可。比如在Django里,我們首先定義這樣的url:
from django.conf.urls.defaults import *
urlpatterns = patterns(‘example.views’,
url(r’^validate/$’, ‘validate’, name=’validate’),
)
在views中,我們把正確的字符串保存在session中,這樣當用戶提交表單的時候,就可以和session中的正確字符串進行比較。
from django.shortcuts import HttpResponse
from validate import create_validate_code
def validate(request):
mstream = StringIO.StringIO()
validate_code = create_validate_code()
img = validate_code[0]
img.save(mstream, “GIF”)
request.session[‘validate’] = validate_code[1]
return HttpResponse(mstream.getvalue(), “image/gif”)
如何利用Python做簡單的驗證碼識別
1 摘要
驗證碼是目前互聯網上非常常見也是非常重要的一個事物,充當著很多系統的 防火牆 功能,但是隨時OCR技術的發展,驗證碼暴露出來的安全問題也越來越嚴峻。本文介紹了一套字符驗證碼識別的完整流程,對於驗證碼安全和OCR識別技術都有一定的借鑒意義。
然後經過了一年的時間,筆者又研究和get到了一種更強大的基於CNN卷積神經網絡的直接端到端的驗證識別技術(文章不是我的,然後我把源碼整理了下,介紹和源碼在這裏面):
基於python語言的tensorflow的『端到端』的字符型驗證碼識別源碼整理(github源碼分享)
2 關鍵詞
關鍵詞:安全,字符圖片,驗證碼識別,OCR,Python,SVM,PIL
3 免責聲明
本文研究所用素材來自於某舊Web框架的網站 完全對外公開 的公共圖片資源。
本文只做了該網站對外公開的公共圖片資源進行了爬取, 並未越權 做任何多餘操作。
本文在書寫相關報告的時候已經 隱去 漏洞網站的身份信息。
本文作者 已經通知 網站相關人員此系統漏洞,並積極向新系統轉移。
本報告的主要目的也僅是用於 OCR交流學習 和引起大家對 驗證安全的警覺 。
4 引言
關於驗證碼的非技術部分的介紹,可以參考以前寫的一篇科普類的文章:
互聯網安全防火牆(1)–網絡驗證碼的科普
裏面對驗證碼的種類,使用場景,作用,主要的識別技術等等進行了講解,然而並沒有涉及到任何技術內容。本章內容則作為它的 技術補充 來給出相應的識別的解決方案,讓讀者對驗證碼的功能及安全性問題有更深刻的認識。
5 基本工具
要達到本文的目的,只需要簡單的編程知識即可,因為現在的機器學習領域的蓬勃發展,已經有很多封裝好的開源解決方案來進行機器學習。普通程序員已經不需要了解複雜的數學原理,即可以實現對這些工具的應用了。
主要開發環境:
python3.5
python SDK版本
PIL
圖片處理庫
libsvm
開源的svm機器學習庫
關於環境的安裝,不是本文的重點,故略去。
6 基本流程
一般情況下,對於字符型驗證碼的識別流程如下:
準備原始圖片素材
圖片預處理
圖片字符切割
圖片尺寸歸一化
圖片字符標記
字符圖片特徵提取
生成特徵和標記對應的訓練數據集
訓練特徵標記數據生成識別模型
使用識別模型預測新的未知圖片集
達到根據「圖片」就能返回識別正確的字符集的目標
7 素材準備
7.1 素材選擇
由於本文是以初級的學習研究目的為主,要求 「有代表性,但又不會太難」 ,所以就直接在網上找個比較有代表性的簡單的字符型驗證碼(感覺像在找漏洞一樣)。
最後在一個比較舊的網站(估計是幾十年前的網站框架)找到了這個驗證碼圖片。
原始圖:
放大清晰圖:
此圖片能滿足要求,仔細觀察其具有如下特點。
有利識別的特點 :
由純阿拉伯數字組成
字數為4位
字符排列有規律
字體是用的統一字體
以上就是本文所說的此驗證碼簡單的重要原因,後續代碼實現中會用到
不利識別的特點 :
圖片背景有干擾噪點
這雖然是不利特點,但是這個干擾門檻太低,只需要簡單的方法就可以除去
7.2 素材獲取
由於在做訓練的時候,需要大量的素材,所以不可能用手工的方式一張張在瀏覽器中保存,故建議寫個自動化下載的程序。
主要步驟如下:
通過瀏覽器的抓包功能獲取隨機圖片驗證碼生成接口
批量請求接口以獲取圖片
將圖片保存到本地磁盤目錄中
這些都是一些IT基本技能,本文就不再詳細展開了。
關於網絡請求和文件保存的代碼,如下:
def downloads_pic(**kwargs):
pic_name = kwargs.get(‘pic_name’, None)
url = ‘httand_code_captcha/’
res = requests.get(url, stream=True)
with open(pic_path + pic_name+’.bmp’, ‘wb’) as f: for chunk in res.iter_content(chunk_size=1024): if chunk: # filter out keep-alive new chunks f.write(chunk)
f.flush()
f.close()
循環執行N次,即可保存N張驗證素材了。
下面是收集的幾十張素材庫保存到本地文件的效果圖:
8 圖片預處理
雖然目前的機器學習算法已經相當先進了,但是為了減少後面訓練時的複雜度,同時增加識別率,很有必要對圖片進行預處理,使其對機器識別更友好。
針對以上原始素材的處理步驟如下:
讀取原始圖片素材
將彩色圖片二值化為黑白圖片
去除背景噪點
8.1 二值化圖片
主要步驟如下:
將RGB彩圖轉為灰度圖
將灰度圖按照設定閾值轉化為二值圖
image = Image.open(img_path)
imgry = image.convert(‘L’) # 轉化為灰度圖table = get_bin_table()
out = imgry.point(table, ‘1’)
上面引用到的二值函數的定義如下:
1234567891011121314 def get_bin_table(threshold=140): “”” 獲取灰度轉二值的映射table :param threshold: :return: “”” table = [] for i in range(256): if i threshold: table.append(0) else: table.append(1) return table
由PIL轉化後變成二值圖片:0表示黑色,1表示白色。二值化後帶噪點的 6937 的像素點輸出後如下圖:
1111000111111000111111100001111100000011
1110111011110111011111011110111100110111
1001110011110111101011011010101101110111
1101111111110110101111110101111111101111
1101000111110111001111110011111111101111
1100111011111000001111111001011111011111
1101110001111111101011010110111111011111
1101111011111111101111011110111111011111
1101111011110111001111011110111111011100
1110000111111000011101100001110111011111
如果你是近視眼,然後離屏幕遠一點,可以隱約看到 6937 的骨架了。
8.2 去除噪點
在轉化為二值圖片後,就需要清除噪點。本文選擇的素材比較簡單,大部分噪點也是最簡單的那種 孤立點,所以可以通過檢測這些孤立點就能移除大量的噪點。
關於如何去除更複雜的噪點甚至干擾線和色塊,有比較成熟的算法: 洪水填充法 Flood Fill ,後面有興趣的時間可以繼續研究一下。
本文為了問題簡單化,乾脆就用一種簡單的自己想的 簡單辦法 來解決掉這個問題:
對某個 黑點 周邊的九宮格裏面的黑色點計數
如果黑色點少於2個則證明此點為孤立點,然後得到所有的孤立點
對所有孤立點一次批量移除。
下面將詳細介紹關於具體的算法原理。
將所有的像素點如下圖分成三大類
頂點A
非頂點的邊界點B
內部點C
種類點示意圖如下:
其中:
A類點計算周邊相鄰的3個點(如上圖紅框所示)
B類點計算周邊相鄰的5個點(如上圖紅框所示)
C類點計算周邊相鄰的8個點(如上圖紅框所示)
當然,由於基準點在計算區域的方向不同,A類點和B類點還會有細分:
A類點繼續細分為:左上,左下,右上,右下
B類點繼續細分為:上,下,左,右
C類點不用細分
然後這些細分點將成為後續坐標獲取的準則。
主要算法的python實現如下:
def sum_9_region(img, x, y): “””
9鄰域框,以當前點為中心的田字框,黑點個數
:param x:
:param y:
:return: “””
# todo 判斷圖片的長寬度下限
cur_pixel = img.getpixel((x, y)) # 當前像素點的值
width = img.width
height = img.height if cur_pixel == 1: # 如果當前點為白色區域,則不統計鄰域值
return 0 if y == 0: # 第一行
if x == 0: # 左上頂點,4鄰域
# 中心點旁邊3個點
sum = cur_pixel \ + img.getpixel((x, y + 1)) \ + img.getpixel((x + 1, y)) \ + img.getpixel((x + 1, y + 1)) return 4 – sum elif x == width – 1: # 右上頂點
sum = cur_pixel \ + img.getpixel((x, y + 1)) \ + img.getpixel((x – 1, y)) \ + img.getpixel((x – 1, y + 1)) return 4 – sum else: # 最上非頂點,6鄰域
sum = img.getpixel((x – 1, y)) \ + img.getpixel((x – 1, y + 1)) \ + cur_pixel \ + img.getpixel((x, y + 1)) \ + img.getpixel((x + 1, y)) \ + img.getpixel((x + 1, y + 1)) return 6 – sum elif y == height – 1: # 最下面一行
if x == 0: # 左下頂點
# 中心點旁邊3個點
sum = cur_pixel \ + img.getpixel((x + 1, y)) \ + img.getpixel((x + 1, y – 1)) \ + img.getpixel((x, y – 1)) return 4 – sum elif x == width – 1: # 右下頂點
sum = cur_pixel \ + img.getpixel((x, y – 1)) \ + img.getpixel((x – 1, y)) \ + img.getpixel((x – 1, y – 1)) return 4 – sum else: # 最下非頂點,6鄰域
sum = cur_pixel \ + img.getpixel((x – 1, y)) \ + img.getpixel((x + 1, y)) \ + img.getpixel((x, y – 1)) \ + img.getpixel((x – 1, y – 1)) \ + img.getpixel((x + 1, y – 1)) return 6 – sum else: # y不在邊界
if x == 0: # 左邊非頂點
sum = img.getpixel((x, y – 1)) \ + cur_pixel \ + img.getpixel((x, y + 1)) \ + img.getpixel((x + 1, y – 1)) \ + img.getpixel((x + 1, y)) \ + img.getpixel((x + 1, y + 1)) return 6 – sum elif x == width – 1: # 右邊非頂點
# print(‘%s,%s’ % (x, y))
sum = img.getpixel((x, y – 1)) \ + cur_pixel \ + img.getpixel((x, y + 1)) \ + img.getpixel((x – 1, y – 1)) \ + img.getpixel((x – 1, y)) \ + img.getpixel((x – 1, y + 1)) return 6 – sum else: # 具備9領域條件的
sum = img.getpixel((x – 1, y – 1)) \ + img.getpixel((x – 1, y)) \ + img.getpixel((x – 1, y + 1)) \ + img.getpixel((x, y – 1)) \ + cur_pixel \ + img.getpixel((x, y + 1)) \ + img.getpixel((x + 1, y – 1)) \ + img.getpixel((x + 1, y)) \ + img.getpixel((x + 1, y + 1)) return 9 – sum
Tips:這個地方是相當考驗人的細心和耐心程度了,這個地方的工作量還是蠻大的,花了半個晚上的時間才完成的。
計算好每個像素點的周邊像素黑點(注意:PIL轉化的圖片黑點的值為0)個數後,只需要篩選出個數為 1或者2 的點的坐標即為 孤立點 。這個判斷方法可能不太準確,但是基本上能夠滿足本文的需求了。
經過預處理後的圖片如下所示:
對比文章開頭的原始圖片,那些 孤立點 都被移除掉,相對比較 乾淨 的驗證碼圖片已經生成。
9 圖片字符切割
由於字符型 驗證碼圖片 本質就可以看着是由一系列的 單個字符圖片 拼接而成,為了簡化研究對象,我們也可以將這些圖片分解到 原子級 ,即: 只包含單個字符的圖片。
於是,我們的研究對象由 「N種字串的組合對象」 變成 「10種阿拉伯數字」 的處理,極大的簡化和減少了處理對象。
9.1 分割算法
現實生活中的字符驗證碼的產生千奇百怪,有各種扭曲和變形。關於字符分割的算法,也沒有很通用的方式。這個算法也是需要開發人員仔細研究所要識別的字符圖片的特點來制定的。
當然,本文所選的研究對象盡量簡化了這個步驟的難度,下文將慢慢進行介紹。
使用圖像編輯軟件(PhoneShop或者其它)打開驗證碼圖片,放大到像素級別,觀察其它一些參數特點:
可以得到如下參數:
整個圖片尺寸是 40*10
單個字符尺寸是 6*10
左右字符和左右邊緣相距2個像素
字符上下緊挨邊緣(即相距0個像素)
這樣就可以很容易就定位到每個字符在整個圖片中佔據的像素區域,然後就可以進行分割了,具體代碼如下:
def get_crop_imgs(img): “””
按照圖片的特點,進行切割,這個要根據具體的驗證碼來進行工作. # 見原理圖
:param img:
:return: “””
child_img_list = [] for i in range(4):
x = 2 + i * (6 + 4) # 見原理圖
y = 0
child_img = img.crop((x, y, x + 6, y + 10))
child_img_list.append(child_img) return child_img_list
然後就能得到被切割的 原子級 的圖片元素了:
9.2 內容小結
基於本部分的內容的討論,相信大家已經了解到了,如果驗證碼的干擾(扭曲,噪點,干擾色塊,干擾線……)做得不夠強的話,可以得到如下兩個結論:
4位字符和40000位字符的驗證碼區別不大
純字母
不區分大小寫。分類數為26
區分大小寫。分類數為52
純數字。分類數為10
數字和區分大小寫的字母組合。分類數為62
純數字 和 數字及字母組合 的驗證碼區別不大
在沒有形成 指數級或者幾何級 的難度增加,而只是 線性有限級 增加計算量時,意義不太大。
10 尺寸歸一
本文所選擇的研究對象本身尺寸就是統一狀態:6*10的規格,所以此部分不需要額外處理。但是一些進行了扭曲和縮放的驗證碼,則此部分也會是一個圖像處理的難點。
11 模型訓練步驟
在前面的環節,已經完成了對單個圖片的處理和分割了。後面就開始進行 識別模型 的訓練了。
整個訓練過程如下:
大量完成預處理並切割到原子級的圖片素材準備
對素材圖片進行人為分類,即:打標籤
定義單張圖片的識別特徵
使用SVM訓練模型對打了標籤的特徵文件進行訓練,得到模型文件
12 素材準備
本文在訓練階段重新下載了同一模式的4數字的驗證圖片總計:3000張。然後對這3000張圖片進行處理和切割,得到12000張原子級圖片。
在這12000張圖片中刪除一些會影響訓練和識別的強幹擾的干擾素材,切割後的效果圖如下:
13 素材標記
由於本文使用的這種識別方法中,機器在最開始是不具備任何 數字的觀念的。所以需要人為的對素材進行標識,告訴 機器什麼樣的圖片的內容是 1……。
這個過程叫做 「標記」。
具體打標籤的方法是:
為0~9每個數字建立一個目錄,目錄名稱為相應數字(相當於標籤)
人為判定 圖片內容,並將圖片拖到指定數字目錄中
每個目錄中存放100張左右的素材
一般情況下,標記的素材越多,那麼訓練出的模型的分辨能力和預測能力越強。例如本文中,標記素材為十多張的時候,對新的測試圖片識別率基本為零,但是到達100張時,則可以達到近乎100%的識別率
14 特徵選擇
對於切割後的單個字符圖片,像素級放大圖如下:
從宏觀上看,不同的數字圖片的本質就是將黑色按照一定規則填充在相應的像素點上,所以這些特徵都是最後圍繞像素點進行。
字符圖片 寬6個像素,高10個像素 ,理論上可以最簡單粗暴地可以定義出60個特徵:60個像素點上面的像素值。但是顯然這樣高維度必然會造成過大的計算量,可以適當的降維。
通過查閱相應的文獻 [2],給出另外一種簡單粗暴的特徵定義:
每行上黑色像素的個數,可以得到10個特徵
每列上黑色像素的個數,可以得到6個特徵
最後得到16維的一組特徵,實現代碼如下:
def get_feature(img): “””
獲取指定圖片的特徵值,
1. 按照每排的像素點,高度為10,則有10個維度,然後為6列,總共16個維度
:param img_path:
:return:一個維度為10(高度)的列表 “””
width, height = img.size
pixel_cnt_list = []
height = 10 for y in range(height):
pix_cnt_x = 0 for x in range(width): if img.getpixel((x, y)) == 0: # 黑色點
pix_cnt_x += 1
pixel_cnt_list.append(pix_cnt_x) for x in range(width):
pix_cnt_y = 0 for y in range(height): if img.getpixel((x, y)) == 0: # 黑色點
pix_cnt_y += 1
pixel_cnt_list.append(pix_cnt_y) return pixel_cnt_list
然後就將圖片素材特徵化,按照 libSVM 指定的格式生成一組帶特徵值和標記值的向量文
請教生成如圖驗證碼的python算法
def gene_text():
source = list(string.letters)
for index in range(0,10):
source.append(str(index))
return ”.join(random.sample(source,number))#number是生成驗證碼的位數
然後我們要創建一個圖片,寫入字符串,需要說明的這裏面的字體是不同系統而定,如果沒有找到系統字體路徑的話,也可以不設置
def gene_code():
width,height = size #寬和高
image = Image.new(‘RGBA’,(width,height),bgcolor) #創建圖片
font = ImageFont.truetype(font_path,25) #驗證碼的字體和字體大小
draw = ImageDraw.Draw(image) #創建畫筆
text = gene_text() #生成字符串
font_width, font_height = font.getsize(text)
draw.text(((width – font_width) / number, (height – font_height) / number),text,
font= font,fill=fontcolor) #填充字符串
接下來,我們要在圖片上畫幾條幹擾線
#用來繪製干擾線
def gene_line(draw,width,height):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill = linecolor)
最後創建扭曲,加上濾鏡,用來增強驗證碼的效果。
image = image.transform((width+20,height+10), Image.AFFINE, (1,-0.3,0,-0.1,1,0),Image.BILINEAR) #創建扭曲
image = image.filter(ImageFilter.EDGE_ENHANCE_MORE) #濾鏡,邊界加強
image.save(‘idencode.png’) #保存驗證碼圖片
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/250762.html