之前写过一篇验证码的破解,地址在这,其实效果不好,有很多朋友来问,其实我已经说了只是个demo;既然如此,就写下文本验证码的破解;本次的主题是定长的,就是验证码的长度是个定值,也是大家在上网过程中遇到的最多的验证码。
其实挺简单的,网上也有很多的总结性的文章,基本验证码破解就两个思路(deep learning):
- 定长类:卷积 多个Softmax
- 不定长类: LSTM CTC
这次的方法就是卷积 多个softmax
与传统的方法的区别
传统的方法是:
- 判定长度
- 分割单个字符
- 单个字符分类
现在我们的方法是:
构建一个网络让其一次性输出所有的字符(定长)
好处是显而易见的,简单啊!!!!同时借助大量的数据可以获得相当高的成功率
破解过程
数据的获取
由于需要大量的数据,所以无法通过网络down下来手写答案,所以只好代码生成;有一个python库可以帮我们搞定这个事情,地址戳这 贴下官方生成验证码的示例:
代码语言:javascript复制from captcha.audio import AudioCaptcha
from captcha.image import ImageCaptcha
audio = AudioCaptcha(voicedir='/path/to/voices')
image = ImageCaptcha(fonts=['/path/A.ttf', '/path/B.ttf'])
data = audio.generate('1234')
audio.write('1234', 'out.wav')
data = image.generate('1234')
image.write('1234', 'out.png')
非常简单,同时还可以生成语音验证码
构建网络
大家看下生成的验证码图片就知道了其实很简单,所以网络不需要构建很复杂就可以很有效的搞定这件事,假设字符的固定长度是4,参考代码如下(keras):
代码语言:javascript复制for i in range(4):
x = Convolution2D(32*2**i, 3, 3, activation='relu')(x)
x = Convolution2D(32*2**i, 3, 3, activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Flatten()(x)
x = Dropout(0.25)(x)
x = [Dense(n_class, activation='softmax', name='c%d'%(i 1))(x) for i in range(4)]
model = Model(input=input_tensor, output=x)
很简单对吧,其实这个网络就可以工作的很好
训练
代码语言:javascript复制model.fit_generator(gen(), samples_per_epoch=51200, nb_epoch=5, nb_worker=2, pickle_safe=True, validation_data=gen(), nb_val_samples=1280)
gen是个生成器,生成训练数据
测试
代码语言:javascript复制x, y = next(gen(1))
y_pred = model.predict(X)
plt.title('real: %snpred:%s'%(decode(y), decode(y_pred)))
plt.imshow(X[0], cmap='gray')
结果
训练了5个epoch,每个epoch大概5W张,acc可以到0.99
代码我是跑了别人使用Keras写的,准备使用Tensorflow复现下,写好后一并拿出来吧,暂时没有!
参考博客:
端到端的OCR