验证码识别最主要难点在于图像的处理,模型的训练网上有太多例子,所以只要能将图片处理成可训练的数据集,便没什么难度了。
图片处理 (生成data.dat 训练数据)
验证码获取: http://222.24.62.120/CheckCode.aspx
训练图片生成器
from PIL import Image
def denoise_img(img):
'''图片降噪处理'''
img2 = Image.new("L", img.size, 255)
for x in range(img.size[1]):
for y in range(img.size[0]):
pix = img.getpixel((y, x))
if pix == 17:
img2.putpixel((y, x), 0)
return img2
img1 = Image.open("CheckCode.gif")
# 将图片转化为 灰度图
img2 = img1.convert("L")
img3 = denoise_img(img2)
图片切分与转化成训练数据: 0代表存在像素点,1则表示没有像素点
数据张量:
- 输入: 336 = 16*21
- 输出: 36
def photo_to_text(img):
x_size, y_size = img.size
y_size -= 5
piece = (x_size - 22) // 8
centers = [4 + piece * (2 * i + 1) for i in range(4)]
photo_data = []
data_str = ''
for i, center in enumerate(centers):
single_img = img.crop((center - (piece + 2), 1, center + (piece + 2), y_size))
# single_img.save("%s.png" % i)
width, height = single_img.size
photo_data_x = []
for h_index in range(0, height):
for w_index in range(0, width):
pixel = single_img.getpixel((w_index, h_index))
data_str += '1 ' if pixel == 255 else '0 '
data_str += '\n\n'
return data_str
分割图片
将图片转成可训练集 (336 = 16*21)
将图片转化01字符串,存储到训练数据data.dat
完整的图片处理代码
模型训练 (生成theta.dat特征文本)
import numpy as np
from scipy.optimize import fmin_bfgs
def sigmoid(z):
g = 1.0/(1.0+np.exp(-z))
return g
def lrGD(theta, *args):
theta = np.matrix(theta).transpose()
X, y, the_lambda = args
m = y.shape[0]
grad = np.zeros(theta.shape)
htheta = sigmoid(X * theta)
grad[0] = 1.0/m * np.sum(np.array((htheta-y))*np.array(X[:, 0:1]))
for i in range(1, theta.shape[0]):
grad[i] = 1.0/m * np.sum(np.array((htheta-y)) *
np.array(X[:, i:i+1])) + the_lambda/m*theta[i]
return grad.flatten()
def lrCostFunction(theta, *args):
theta = np.matrix(theta).transpose()
X, y, the_lambda = args
m = y.shape[0]
htheta = sigmoid(X*theta)
J = -np.sum(np.array(y)*np.array(np.log(htheta)) + np.array((1-y))
* np.array(np.log(1-htheta)))/m + the_lambda*np.sum(
np.array(theta[1:]) * np.array(theta[1:]))/(2*m)
return J
def oneVsAll(X, y, num_labels, the_lambda):
m, n = np.shape(X)
all_theta = np.matrix(np.zeros((num_labels, n+1)))
X = np.hstack((np.ones((m, 1)), X))
initial_theta = np.zeros((n+1, 1))
for c in range(num_labels):
print ('Training for %d/%d' % (c+1, num_labels))
args = (X, (y == c), the_lambda)
theta = fmin_bfgs(lrCostFunction, initial_theta,
fprime=lrGD, args=args, maxiter=50)
all_theta[c, :] = theta.transpose()
return all_theta
def train():
'''开始训练'''
num_labels = 36 # 输出量
num_y = 336 # 输入量 16*21
the_lambda = 0.1
data = np.matrix(np.loadtxt('data.dat')) # 载入训练数据
y = data[:, num_y]
X = data[:, :num_y]
all_theta = oneVsAll(X, y, num_labels, the_lambda)
''' 生成训练后的特征文本 '''
np.savetxt('theta.dat', all_theta)
if __name__ == '__main__':
train()
使用模型识别
精简版教程查看
github:https://github.com/dairoot/zfxfzb-code