使用机器学习识别简单的验证码(一)

113次阅读
没有评论

共计 4692 个字符,预计需要花费 12 分钟才能阅读完成。

识别验证码

在我们的生活中,验证码是经常使用到的一个东西,那么有没有一种程序可以自动识别验证码呢?

准备步骤:生成验证码

首先我们生成一部分的验证码用以识别。

import random
from PIL import Image, ImageDraw, ImageFont


def getRandomStr():
    random_num = str(random.randint(0, 9))
    return random_num


def getRandomColor():
    R = random.randint(0, 255)
    G = random.randint(0, 255)
    B = random.randint(0, 255)

    if R == 255 and G == 255 and B == 255:
        R = G = B = 0

    return (R, G, B)


def generate_captcha():
    image = Image.new('RGB', (150, 50), (255, 255, 255))
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype('LiberationSans-Bold.ttf', size=32)
    label = ''

    for i in range(5):
        random_char = getRandomStr()
        label += random_char
        draw.text((10 + i * 30, 0), random_char, getRandomColor(), font=font)

    width = 150
    height = 30

    for i in range(3):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=(0, 0, 0))

    for i in range(5):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=getRandomColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x + 4, y + 4), 0, 90, fill=(0, 0, 0))
    image.save(open(''.join(['captcha_predict/',  'unknown.png']), 'wb'), 'png')


if __name__ == '__main__':
    generate_captcha()


生成验证码的效果如下图:

使用机器学习识别简单的验证码(一)

进行识别:首先对验证码进行降噪

降噪:顾名思义,降低噪音,也就是将验证码中那些无用的东西去除掉,比如一些点、线之类的

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import os


def binarization(path):
    img = Image.open(path)
    img_gray = img.convert('L')
    img_gray = np.array(img_gray)

    w, h = img_gray.shape
    for x in range(w):
        for y in range(h):
            gray = img_gray[x, y]
            if gray <= 250:
                img_gray[x, y] = 0
            else:
                img_gray[x, y] = 1

    return img_gray


def noiseReduction(img_gray, label):
    width, height = img_gray.shape
    for x in range(width):
        for y in range(height):
            count = 0
            if img_gray[x, y] == 1:
                continue

            try:
                if img_gray[x - 1, y - 1] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x - 1, y] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x - 1, y + 1] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x, y + 1] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x + 1, y + 1] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x + 1, y] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x + 1, y - 1] == 0:
                    count += 1
            except:
                pass

            try:
                if img_gray[x, y - 1] == 0:
                    count += 1
            except:
                pass

            if count < 4:
                img_gray[x, y] = 1
    plt.figure('')
    plt.imshow(img_gray, cmap='gray')
    plt.axis('off')
    plt.savefig(''.join(['降噪image/', label, '.png']))


def cutImg(label):
    labels = list(label)
    img = Image.open(''.join(['降噪image/', label, '.png']))
    for i in range(5):
        pic = img.crop((100 * (1 + i), 170, 100 * (2 + i), 280))
        plt.imshow(pic)
        seq = get_save_seq(label[i])
        pic.save(''.join(['cut_number/', str(label[i]), '/', str(seq), '.png']))


def get_save_seq(num):
    numlist = os.listdir(''.join(['cut_number/', num, '/']))
    if len(numlist) == 0 or numlist is None:
        return 0
    else:
        max_file = 0
        for file in numlist:
            if int(file.split('.')[0]) > max_file:
                max_file = int(file.split('.')[0])
        return int(max_file + 1)


if __name__ == '__main__':
    img_list = os.listdir('captcha_images/')
    label_list = []
    for img in img_list:
        img = str(img).replace('.png', '')
        label_list.append(img)

    for label in label_list:
        img = 'captcha_images/' + label + '.png'
        img_gray = binarization(img)
        noiseReduction(img_gray, label)
        cutImg(label)

降噪后的效果如下:

使用机器学习识别简单的验证码(一)

进行识别:切片建模

from sklearn.externals import joblib
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from 机器学习.降噪 import *


def load_train_data():
    X = []
    Y = []
    cut_list = os.listdir('cut_number')
    for numC in cut_list:
        num_list_dir = ''.join(['cut_number/', str(numC), '/'])
        nums_dir = os.listdir((num_list_dir))
        for num_file in nums_dir:
            img = Image.open(''.join((['cut_number/', str(numC), '/', num_file])))
            img_gray = img.convert('L')
            img_array = np.array(img_gray)
            w, h = img_array.shape
            for x in range(w):
                for y in range(h):
                    gray = img_array[x, y]
                    if gray <= 250:
                        img_array[x, y] = 0
                    else:
                        img_array[x, y] = 1
            img_re = img_array.reshape(1, -1)
            X.append(img_re[0])
            Y.append(int(numC))
    # print(np.array(X), np.array(Y))
    return np.array(X), np.array(Y)


def generate_model(X, Y):
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3)
    log_clf = LogisticRegression(multi_class='ovr', solver='sag', max_iter=10000)

    log_clf.fit(X_train, Y_train)
    joblib.dump(log_clf, 'captcha_model/captcha_model.model')


def get_model():
    model = joblib.load('captcha_model/captcha_model.model')
    return model


def captcha_predict():
    path = 'captcha_predict/unknown.png'
    pre_img_gray = binarization(path)
    noiseReduction(pre_img_gray,'unknown')
    labels = ['0','1','2','3','4']
    img = Image.open(''.join(['降噪image/unknown.png']))
    for i in range(5):
        pic = img.crop((100 * (1 + i), 170, 100 * (2 + i), 280))
        plt.imshow(pic)
        pic.save(''.join(['captcha_predict/',labels[i],'.png']))

    result = ''
    model = get_model()
    for i in range(5):
        path = ''.join(['captcha_predict/',labels[i],'.png'])
        img = Image.open(path)
        img_gray = img.convert('L')
        img_array = np.array(img_gray)
        w, h = img_array.shape
        for x in range(w):
            for y in range(h):
                gray = img_array[x, y]
                if gray <= 250:
                    img_array[x, y] = 0
                else:
                    img_array[x, y] = 1
        img_re = img_array.reshape(1.-1)
        X = img_re[0]
        Y_pre = model.predict([X])
        result = ''.join([result,str(Y_pre[0])])
    return result

if __name__ == '__main__':
    X,Y=load_train_data()
    generate_model(X,Y)
    # print(captcha_predict())

切片效果如下

使用机器学习识别简单的验证码(一)

 

正文完
 
admin
版权声明:本站原创文章,由 admin 2019-11-26发表,共计4692字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码