├── README.md ├── ocr4qqcaptcha.py └── qqcaptcha-with-xception.py /README.md: -------------------------------------------------------------------------------- 1 | # n2n-ocr-for-qqcaptcha 2 | an n2n ocr for qq captcha, 端到端的腾讯验证码识别 3 | 4 | http://kexue.fm/archives/4138/ 5 | 6 | 最新结果参考 7 | 8 | http://kexue.fm/archives/4503/ 9 | -------------------------------------------------------------------------------- /ocr4qqcaptcha.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import numpy as np 3 | from scipy import misc 4 | from keras.layers import Input, Convolution2D, MaxPooling2D, Flatten, Activation, Dense 5 | from keras.models import Model 6 | from keras.utils.np_utils import to_categorical 7 | 8 | 9 | imgs = glob.glob('sample/*.jpg') 10 | img_size = misc.imread(imgs[0]).shape #这里是(53, 129, 3) 11 | data = np.array([misc.imresize(misc.imread(i), img_size).T for i in imgs]) 12 | data = 1 - data.astype(float)/255.0 13 | target = np.array([[ord(i)-ord('a') for i in j[7:11]] for j in imgs]) 14 | target = [to_categorical(target[:,i], 26) for i in range(4)] 15 | img_size = img_size[::-1] 16 | 17 | input = Input(img_size) 18 | cnn = Convolution2D(32, 3, 3)(input) 19 | cnn = MaxPooling2D((2, 2))(cnn) 20 | cnn = Convolution2D(32, 3, 3)(cnn) 21 | cnn = MaxPooling2D((2, 2))(cnn) 22 | cnn = Activation('relu')(cnn) 23 | cnn = Convolution2D(32, 3, 3)(cnn) 24 | cnn = MaxPooling2D((2, 2))(cnn) 25 | cnn = Activation('relu')(cnn) 26 | cnn = Convolution2D(32, 3, 3)(cnn) 27 | cnn = MaxPooling2D((2, 2))(cnn) 28 | cnn = Flatten()(cnn) 29 | cnn = Activation('relu')(cnn) 30 | 31 | model = Model(input=input, output=[Dense(26, activation='softmax')(cnn) for i in range(4)]) 32 | model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 33 | model.summary() 34 | 35 | batch_size = 256 36 | nb_epoch = 30 37 | model.fit(data, target, batch_size=batch_size, nb_epoch=nb_epoch) 38 | model.save_weights('yanzheng_cnn_2d.model') 39 | rr = [''.join(chr(i.argmax()+ord('a')) for i in model.predict(data[[k]])) for k in tqdm(range(len(data)))] 40 | s = [imgs[i][7:11]==rr[i] for i in range(len(imgs))] 41 | print 1.0*sum(s)/len(s) 42 | 43 | def ocr(filename): 44 | img = misc.imresize(misc.imread(filename), img_size[::-1]).T 45 | img = np.array([1 - img.astype(float)/255]) 46 | return ''.join(chr(i.argmax()+ord('a')) for i in model.predict(img)) 47 | -------------------------------------------------------------------------------- /qqcaptcha-with-xception.py: -------------------------------------------------------------------------------- 1 | import glob 2 | samples = glob.glob('sample/*.jpg') 3 | 4 | import numpy as np 5 | np.random.shuffle(samples) #打乱训练样本 6 | 7 | nb_train = 90000 #共有10万样本,9万用于训练,1万用于测试 8 | train_samples = samples[:nb_train] 9 | test_samples = samples[nb_train:] 10 | 11 | from keras.applications.xception import Xception,preprocess_input 12 | from keras.layers import Input,Dense,Dropout 13 | from keras.models import Model 14 | 15 | img_size = (50, 120) #全体图片都resize成这个尺寸 16 | input_image = Input(shape=(img_size[0],img_size[1],3)) 17 | base_model = Xception(input_tensor=input_image, weights='imagenet', include_top=False, pooling='avg') 18 | predicts = [Dense(26, activation='softmax')(Dropout(0.5)(base_model.output)) for i in range(4)] 19 | 20 | model = Model(inputs=input_image, outputs=predicts) 21 | model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) 22 | model.summary() 23 | 24 | from scipy import misc 25 | def data_generator(data, batch_size): #样本生成器,节省内存 26 | while True: 27 | batch = np.random.choice(data, batch_size) 28 | x,y = [],[] 29 | for img in batch: 30 | x.append(misc.imresize(misc.imread(img), img_size)) 31 | y.append([ord(i)-ord('a') for i in img[-8:-4]]) 32 | x = preprocess_input(np.array(x).astype(float)) 33 | y = np.array(y) 34 | yield x,[y[:,i] for i in range(4)] 35 | 36 | #训练过程终会显示逐标签的准确率 37 | model.fit_generator(data_generator(train_samples, 100), steps_per_epoch=1000, epochs=10, validation_data=data_generator(test_samples, 100), validation_steps=100) 38 | 39 | #评价模型的全对率 40 | from tqdm import tqdm 41 | total = 0. 42 | right = 0. 43 | step = 0 44 | for x,y in tqdm(data_generator(test_samples, 100)): 45 | _ = model.predict(x) 46 | _ = np.array([i.argmax(axis=1) for i in _]).T 47 | y = np.array(y).T 48 | total += len(x) 49 | right += ((_ == y).sum(axis=1) == 4).sum() 50 | if step < 100: 51 | step += 1 52 | else: 53 | break 54 | 55 | print u'模型全对率:%s'%(right/total) 56 | --------------------------------------------------------------------------------