• 基于SVM的python简单实现验证码识别


    验证码识别是一个适合入门机器学习的项目,之前用knn 做过一个很简单的,这次用svm来实现。svm直接用了开源的库libsvm。验证码选的比较简单,代码也写得略乱,大家看看就好。

    1. 爬取验证码图片

     1 import urllib
     2 from urllib import request
     3 
     4 
     5 def download_pics(pic_name):
     6     url = 'http://smart.gzeis.edu.cn:8081/Content/AuthCode.aspx'
     7     res = request.urlopen(url)
     8     get_img = res.read()
     9 
    10     with open( 'D:python验证码\%s.jpg'%(pic_name),'wb') as f:
    11         f.write(get_img)
    12 
    13 if __name__ == '__main__':
    14     for i in range(100):
    15         pic_name = i
    16         download_pics(pic_name)

     

    2. 二值化

     接下来要做的工作就是二值化验证码,所谓二值化,就是将每一个像素点用0或1来表示,图像的每个像素点都有rgb三个值,我们首先转化成灰度图,这样每个像素点就只有一个灰度值了。接下来根据自己设定的阈值来确定每个像素点是该为0还是为1。

    我的思路是首先将图像转化为array处理,当然完全可以直接图像处理。

     1 def binarization(im):  #二值化
     2     imgry = im.convert('L')
     3     imgry = np.array(imgry)  #将图像转化为数组
     4     height, width = imgry.shape
     5     #f = open('s.txt','w')
     6     for i in range(height):
     7         for j in range(width):
     8             gray = imgry[i,j]
     9             if gray <= 220:  #阈值设为220
    10                 imgry[i, j] = 0
    11             else:
    12                 imgry[i, j] = 1
    13             #f.write(str(imgry[i,j]))  #输出到txt查看
    14         #f.write('
    ')
    15     '''
    16     plt.figure('')
    17     plt.imshow(imgry, cmap='gray')
    18     plt.axis('off')
    19     plt.show()
    20     '''
    21     return imgry

    在二值化处理之后,处理结果如下所示:

                       

    在txt的结果如下所示,可以很明显的看到0413:

    3. 去除噪点

    在二值化之后,还存在一个问题就是图像之中还有许多黑点,这成为噪点,是干扰项,去除噪点有很多不同的方法,由于我只是一个小菜鸟,所以我就用了最简单的8-邻域去除噪点法。依次检查每个像素点周围8个点的情况,如果黑点少于阈值时,那么就可以认为该点是噪点。其实这样的处理效果是比较差的,只是适用于去除小点,但是对于干扰线条这种可能就没什么作用了。

     1 def noiseReduction(imgry):  #去除噪点
     2     global dx, dy
     3     height, width = imgry.shape
     4     for i in range(height):
     5         for j in range(width):
     6             cnt = 0
     7             if imgry[i, j] == 1:  #白点不用管
     8                 continue
     9             else:
    10                 for k in range(8):
    11                     x = dx[k] + i
    12                     y = dy[k] + j
    13                     if x < 0 or x >= height or y < 0 or y >= 
    14                         continue
    15                     if imgry[x, y] == 0:
    16                         cnt += 1
    17             if cnt < 4:  #周围少于4点就算噪点
    18                 imgry[i, j] = 1
    19     return imgry

    处理之后可以明显的看到黑点基本上都被处理掉了。

    4. 图片分割

     接下来要做的就是将这四个数字分割开来形成训练集,这个操作并不难。因为这些验证码的位置都是差不多的,如果验证码字符位置比较乱的话就会比较麻烦。。

     1 def cutImg(img):  #图像切割
     2     s = 12
     3     w = 40
     4     h = 81
     5     t = 0
     6     cut_img = []
     7     for i in range(4):
     8         pic = img.crop((s + w * i, t, s + w * (i + 1), h))
     9         cut_img.append(pic)
    10     return cut_img

    5. 图片分类

    这个步骤的目的就是人为的给训练集打上标签。 将相同的数字放在同一个文件夹下面。

                 

    6.  训练模型

     训练模型很简单,因为直接就是使用libsvm库,我们只需要按照数据格式生成一些特征值即可。在切割完图片并保存之后,我发现我图片的像素值有略微的改变,可能是重新保存了的原因,所有我这里又进行了一次二值化。。。

    这里说明依稀libsvm数据格式的要求:

    [label]   [index:value]   [index:value]   [index:value].....

    每一个数据都是这样的格式,label是标签,[index:value]是数据的特征值,index就是从0开始的编号,value是特征值。

    在这里对于每一张图片,我就把特征值设为每行每列的黑点个数了。如第一个特征值就是第一行黑点个数。。。

     1 import os
     2 from PIL import *
     3 from PIL import Image
     4 import numpy as np
     5 from libsvm.python.svmutil import *
     6 from libsvm.python.svm import *
     7 
     8 
     9 address = 'D:python验证码-sort\'
    10 f = open('train.txt', 'w')
    11 
    12 def get_feature(dir, file):
    13     f.write(dir)
    14     im = Image.open(address + dir +'\' + file)
    15     imarr = np.array(im)
    16     height, width = imarr.shape
    17     for i in range(height):
    18         for j in range(width):
    19             gray = imarr[i,j]
    20             if gray <= 150:
    21                 imarr[i, j] = 0
    22             else:
    23                 imarr[i, j] = 255
    24     im = Image.fromarray(imarr)
    25     count = 0
    26     width, height = im.size
    27     for i in range(height):
    28         c = 0
    29         for j in range(width):
    30             if im.getpixel((j, i)) == 0: c += 1
    31         f.write(' %d:%d'%(count, c))
    32         count += 1
    33     for i in range(width):
    34         c = 0
    35         for j in range(height):
    36             if im.getpixel((i, j)) == 0: c += 1
    37         f.write(' %d:%d'%(count, c))
    38         count += 1
    39     f.write('
    ')
    40 
    41 def train_svm_model():
    42     y, x = svm_read_problem('train.txt')
    43     model = svm_train(y, x)
    44     svm_save_model('model_file', model)
    45 
    46 if __name__ == '__main__':
    47     dirs = os.listdir(address)
    48     for dir in dirs:
    49         files = os.listdir(address + dir)
    50         for file in files:
    51             get_feature(dir, file)
    52     train_svm_model()

    7.  测试模型

     用测试数据对模型进行测试。

    1 from libsvm.python.svmutil import *
    2 from libsvm.python.svm import *
    3 import image_slove
    4 
    5 if __name__ == '__main__':
    6     model = svm_load_model('model_file')
    7     yt, xt = svm_read_problem('test.txt')
    8     p_label, p_acc, p_val = svm_predict(yt, xt, model)

    还是不错的,毕竟验证码很简单。。。

    8.  预测验证码

    终于走到最后一步了,得到一张验证码后先按照之前的操作根据该图片生成特征值,这里标签还是需要的,可以随便填一个,反正这个不重要。或许有别的方法,反正我暂时还不知道。

     1 from libsvm.python.svmutil import *
     2 from libsvm.python.svm import *
     3 from PIL import Image
     4 import image_slove
     5 
     6 if __name__ == '__main__':
     7     '''
     8       在这里处理图片生成特征值
     9     '''
    10     model = svm_load_model('model_file')
    11     yt, xt = svm_read_problem('predict.txt')
    12     p_label, p_acc, p_val = svm_predict(yt, xt, model)
    13     print('该验证码为:', end='')
    14     for label in p_label:
    15         print(int(label), end='')

    最后成功的验证出来了。

    9.  总结

    通过这个实验对于验证码识别流程有了一定的了解,这次也是直接使用了支持向量机,后续需要稍微学习一下。

  • 相关阅读:
    [python第七课]字符串和常用数据结构
    深浅拷贝与循环引用问题
    CSS居中总结
    CSS布局总结
    跨域
    函数节流与防抖
    浏览器渲染原理及渲染阻塞
    进程与线程
    前端之网络攻击
    前端之缓存
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/8724621.html
Copyright © 2020-2023  润新知