python机器学习识别正方教务系统验证码
环境
python 3.7.3
Pycharm
依赖库
requests库
Pillow库
sklearn库
其他库应为python自带库,若无法运行,请安装对应的库
步骤
1.验证码图片预处理与分割
图片预处理:主要消除验证码图片的噪点,让图片的验证码清晰地显示以便提取相关特征。而正方教务系统的验证码主要包括一些噪点,没有其他曲线,而且字母和数字为深蓝色,并且没有很严重的变形,如下图所示。
预处理与分割操作主要包括灰度处理、二值化和裁剪
灰度处理:主要将彩色图片变为灰度图片。彩色图片每个像素点包括rgb三层颜色,而灰度图片每个像素点只有一层颜色。直接使用Pillow库的相关函数即可将彩色图片变为灰度图片,代码如下:
from PIL import Image
...
image = Image.open("./traindataset/" + f)
image = image.convert('L') # 灰度处理
...
二值化:将灰度图片的每个像素点设置为0(黑)或者255(白)。此步骤主要是消除噪点,由上图的灰度图可以看到数字与字母部分颜色较深,其像素值更接近与0,而噪点的像素值与255更接近,因此存在一个阈值,用以划分该像素是噪点还是数字与字母部分。经过反复的测试,尽可能使得噪点变少,得到阈值为50。即将像素值大于50的直接设置为255(白),而小于等于50的直接设置为0(黑色),此所谓二值化(二值:0/255)。代码如下:
...
image = image.point(lambda x: 255 if x > 50 else 0) # 二值化
...
裁剪:即进行分割,将每个数字/字符分割开来以便于特征提取。通过比较不同的验证码,最终确定提取的大小为12*22。代码如下:
...
crop_range = [(4, 0, 16, 22), (16, 0, 28, 22), (28, 0, 40, 22), (42, 0, 54, 22)] # 分割范围
for i in range(4):
image_t = image.crop(crop_range[i]) # 裁剪
...
2.机器学习训练验证码
该步骤最重要的就是特征提取
特征提取就是将图片的特征提取出来,而不是将整个图片都作为数组放入训练。如果将整个图片作为数组进行训练,则feature包括12*22=264,特征数过多,不利于机器学习的训练,因此采用特征提取的办法来降低feature。而常用的算法是提取每一行、每一列的黑色,也就是像素值为0的个数,然后作为feature,则需要的特征数为12+22=34,特征数大大降低。具体代码如下:
def extract_characters(image):
img = np.asarray(image)
characters = []
for i in range(image.height):
total = 0
for j in range(image.width):
if img[i][j] == 0:
total += 1
characters.append(total)
for i in range(image.width):
total = 0
for j in range(image.height):
if img[j][i] == 0:
total += 1
characters.append(total)
return characters # 返回特征向量
然后用机器学习的方法训练训练集,这里采用的是随机森林的方法,代码如下:
def train_captcha():
list1 = list(range(48, 57))
list1 = list1 + list(range(97, 122))
list1.remove(ord('o')) # 'o'没有出现
train_x = []
train_y = []
for i in range(len(list1)):
work_dir = "./train_classify/" + chr(list1[i]) + "/"
for f in os.listdir(work_dir):
filepath = work_dir + f
train_x.append(extract_characters(Image.open(filepath)))
train_y.append(list1[i])
train_x = np.array(train_x)
train_y = np.array(train_y)
rf = RandomForestClassifier(n_estimators=45, max_features='sqrt', oob_score=True)
rf.fit(train_x, train_y)
joblib.dump(rf, './randomforest.m')
3.测试结果
对测试集200个验证码进行测试,得到的正确率如下:
Total: 200 correct 194 Accuracy: 0.97
项目地址
https://github.com/bladchan/captcha_identity