首先先总体概述一下训练一个验证码的整体步骤

  • 获取大量的验证码样本
  • 验证码处理、切割
  • 提取验证码切割后的图片特征
  • 基于提取后的图片特征进行训练
  • 根据训练后的模型进行验证码识别

1.获取大量的验证么样本

以我校的课外学分管理为例,下载1000张验证码样本

import requests

if __name__ == '__main__':
yzm_url = 'http://csxyyiban.cn:39005/pages/login/image.jsp'
for i in range(1000):
print(str(i)+"finish")
res = requests.get(yzm_url, stream=True)
with open( 'yzm/'+ str(i) + '.jpg', '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()

2.验证码处理、切割

简单分析一下验证码的处理、切割思路

先将验证码进行灰度化,可以看到连噪点都没有。

将验证码拖到ps中,放大到像素点,根据验证码四个数字的根据进行切割。

def get_crop_imgs(img):
"""
按照图片的特点,进行切割,这个要根据具体的验证码来进行工作. # 见原理图
:param img:
:return:
"""
child_img_list = []
for i in range(4):
x = 6 + i * (8 + 5) # 见原理图
y = 4
child_img = img.crop((x, y, x + 8, y + 12))
child_img_list.append(child_img)
return child_img_list

经过切割后,一张验证码被分割成了4张。此时分割出来的验证码,需要人工标定,分类。

3.提取验证码的特征值

经过切割后,每张大小为8*12。就有20个特征值,保存为data.txt中

这里可能很多人会不明白,明明20个特征值,为什么data.txt文件21会有个特征值呢?多出一列呢?其实这里多出来的一列是前20个特征值所指向的字符。

4.SVM训练

根据特征值进行训练保存训练模型train_model.m

def train():
data = pd.read_csv('data.txt')
clf = OneVsRestClassifier(SVC(kernel='linear'))

X = data.iloc[:, 1:21] # 选取所有行的1-20列
y = np.array(data.iloc[:, 21]).astype(str) # 选取所有行的第21列,类型转换

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
clf.fit(X_train, y_train) # 训练ing
y_pred = clf.predict(X_test) # 测试ing

rf = pd.DataFrame(list(zip(y_pred, y_test)), columns=['predicted', 'actual']) # rf类型是dataframe
rf['correct'] = rf.apply(lambda r: 1 if r['predicted'] == r['actual'] else 0, axis=1)
print(len(rf[rf['correct'] == 1]) / len(rf))
joblib.dump(clf, "train_model") # 保存训练模型

这里的test_size参数表示分组规模,test_size=0.3时表示,表示70%的data拿去训练,30%的data拿去测试。

可以得出准备率还是蛮高的。

5.使用训练模型识别验证码

def verify():
clf = joblib.load("train_model")
image = Image.open("yzm/7.jpg")
image.show()
imgry = image.convert('L') # 转化为灰度图
table = get_bin_table()
out = imgry.point(table, '1')
img_list = get_crop_imgs(out)
result = ''
for x in range(0, 4):
#img_list[x].show()
list = get_feature(img_list[x])
y_pred = clf.predict([list]) # predict接受二维数组参数
#print(y_pred[0])
result += y_pred[0]
return result

大功告成,项目晚点分享哈。


发表评论

电子邮件地址不会被公开。 必填项已用*标注