机器学习实例——简单验证码识别

简单验证码识别项目
基于逻辑回归和图像处理的项目
输入:一个验证码图像
输出:这个验证码图像中的数字(字母)

我们的需求是需要将一张彩色,由四个数字且有噪点所构成的提交给计算机,让计算机对该图片进行识别。从上述条件分析可知,我们需要以下步骤:

  1. 首先对图像进行处理,分为以下三小步:
    (1)二值化:首先把图像从RGB3通道转化成Gray1通道,然后把灰度图(0~255)转化成二值图(0,1),简单来说就是将彩色的图片转为黑白的,只有两个颜色时,黑和白两个颜色就可以通过1,0两个数字进行表示。
    (2)降噪:通过处理孤立点,对二值化的图进行降噪,由于图片都是由一个个小的像素点合成的,所以当一个像素点周围空白点大于四个,咱们就认为他是一个孤立点。
    (3)图片切割:根据像素格,把图片中的所有(4个)数字,分别保存到对应的0~9文件夹下,供机器进行识别。

至此:数据处理就完成了,我们来看看上述部分的代码:

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


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


def getRandonColor():
    c1 = random.randint(0, 255)
    c2 = random.randint(0, 255)
    c3 = random.randint(0, 255)
    if c1 == 255:
        c1 = 0
    if c2 == 255:
        c2 = 0
    if c3 == 255:
        c3 = 0
    return c1, c2, c3


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, getRandonColor(), 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=getRandonColor())
            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_new/', label, '.png']), 'wb'), 'png')


def binarization(path):
    img = Image.open(path)
    img_gray = img.convert("L")
    img_gray = np.array(img_gray)
    print(img_gray)
    w, h = img_gray.shape
    for x in range(w):
        for y in range(h):
            gray = img_gray[x, y]
            if gray <= 220:
                img_gray[x, y] = 0
            else:
                img_gray[x, y] = 1
    plt.figure('')
    plt.imshow(img_gray, cmap='gray')
    plt.axis('off')
    # plt.show()
    return img_gray


def nosieReduction(img_gray, label):
    height, width = img_gray.shape
    for x in range(height):
        for y in range(width):
            cnt = 0
            if img_gray[x, y] == 1:
                continue
            else:
                try:
                    if img_gray[x - 1, y - 1] == 0:
                        cnt += 1
                except:
                    pass

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

                if cnt < 4:
                    img_gray[x, y] = 1
    plt.figure('')
    plt.imshow(img_gray, cmap='gray')
    plt.axis('off')
    # plt.show()
    plt.savefig(''.join(['CLEAN_captcha_img/',label,'.png']))

def img_2_clean():
    captchas = os.listdir(''.join(['captcha_images/']))
    for captcha in captchas:
        print(captcha)
        label = captcha.split('.')[0]
        img_path = ''.join(['captcha_images/', captcha])
        im = binarization(img_path)
        nosieReduction(im, label)


def cutImg(label):
    labels = list(label)
    img = Image.open(''.join(['CLEAN_captcha_img/', label, '.png']))
    for i in range(5):
        pic = img.crop((100 * (1 + i), 170, 100 * (1 + i) + 100, 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


def create_dir():
    for i in range(10):
        os.mkdir(''.join(['cut_number/', str(i)]))

def clean_to_cut():
    captchas = os.listdir(''.join(['CLEAN_captcha_img/']))
    for captcha in captchas:
        label = captcha.split('.')[0]
        cutImg(label)

if __name__ == '__main__':
    for i in range(1):
        generate_captcha()
    # img_2_clean()
    # create_dir()
    # clean_to_cut()

    # path = 'captcha_images/'
    # binarization()

以上还有生成的验证码的代码,生成结果为:
在这里插入图片描述

至此:数据处理就完成了接下来需要:
2. 把数据带入逻辑回归进行建模
(1)把切割好的数据,按照X(二位数组),Y(一维数组)的方式传入logisticRegression.fit()函数进行拟合
我们可以通过网格搜索(GridSearch)来进行调参
(2)通过joblib包,把模型保存到本地
我们需要对得出的数据进行逻辑回归:

import os
from PIL import Image
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.externals import joblib

from check_code import *


def load_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 <= 240:
                        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))
    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_cif = LogisticRegression(multi_class='ovr', solver='sag', max_iter=10000)
    log_cif.fit(X_train, Y_train)
    joblib.dump(log_cif, 'captcha_model/captcha_model.model')


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


def captcha_predict():
    path = 'captcha_new/unkonwn.png'
    pre_img_gray = binarization(path)
    nosieReduction(pre_img_gray, 'unknown')
    labels = ['0', '1', '2', '3', '4']
    img = Image.open(''.join(['CLEAN_captcha_img/unknown.png']))
    for i in range(5):
        pic = img.crop((100 * (i + 1), 170, 100 * (1 + i) + 100, 280))
        plt.imshow(pic)
        pic.save(''.join(['captcha_new/', labels[i], '.png']))
    result = ''
    model = get_model()
    for i in range(5):
        path = ''.join(['captcha_new/', 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 <= 220:
                    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_data()
    generate_model(X,Y)

当模型生成好了之后就可以对给入的数据进行对比了:
调用此函数:

	if __name__ == '__main__':
    result = captcha_predict()
    print(result)

结果如下:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值