数据挖掘(八)
从图像中抽取信息很难,图像包罗大量原始数据,图像的尺度编码单元像素提供的信息量很少。图像特别是照片可能存在一系列标题,比如含糊不清、离目标太近、光线太亮或太暗、比例失真、残缺、扭曲等,这会增加计算机体系抽取有用信息的难度。本文先容如何用神经网络辨认图像中的字母,从而主动辨认验证码CAPTCHA。
人工神经网络
- 神经网络由一些列相互毗连的神经元构成,每个神经元都是一个简单的函数,接收一定输入,给出相应输出。神经元可以利用任何尺度函数来处理数据比如线性函数,这些函数统称为激活函数。一样平常来说,神经网络学习算法要能正常工作,激活函数应当是可导和光滑的。常用的激活函数由逻辑斯蒂函数,x为神经元的输入,k、L通常为1,这时函数达到最大值。每个神经元接收几个输入,计算输出,如许的一个个神经元毗连起来构成了神经网络。
f ( x ) = L 1 + e − k ( x − x 0 ) f(x) = \frac{L}{1 + e^-k(x-x0)} f(x)=1+e−k(x−x0)L
- 用于数据挖掘应用的神经网络,神经元按照层级进行排列。第一层是输入层,接收来子数据集的输入。第一层中的每个神经元对输入进行计算,把得到的结果通报给第二层的神经元,这种叫做前向神经网络。在神经网络中,上一层的输出作为下一层的输入,直到到达最后一层。输出结果表示的是神经网络分类器给出的分类结果。输入层和输出层之间的全部层称为隐含层。
- 我们优先考虑利用全毗连层,也就是上一层中每个神经元的输出都输入到下一层的全部神经元。现实构建神经网络时,练习过程中,很多权重都会被设置为0,有用地淘汰边的数量。神经元激活函数通常利用逻辑斯蒂函数,每层神经元之间为全毗连,创建和练习神经网络还需要用到其他几个参数。创建过程指定神经网络的规模需要用到两个参数,神经网络共有多少层和隐含层每层有多少个神经元。练习过程中还会用到神经元之间边的权重参数。一个神经元毗连到另一个神经元,两者之间的边具有一定的权重,在计算输出时,用边的权重乘以信号的巨细。如果边的权重为0.8,神经元激活后,输出值为1,那么下一个神经元从前面这个神经元得到的输入就是0.8。如果第一个神经元没有激活,值为0,那么输出到第二个神经元的值就是0。
- 神经网络巨细合适而且权重经过充分练习,它的分类效果才气精确。通常开始时利用随机选取的权重,练习过程中再渐渐更新。设置好网络巨细后,再从练习集中练习得到边的权重参数后,就能构造分类器。然后我们可以利用分类器分类。
创建数据集
我们以破解网站4个字母的英文单词的验证码为例,编写步伐还原图像中的单词。步骤是把大图像分成只包罗一个字母的4张小图像,为每个字母分类,把字母重新组合为单词,用词典修正单词辨认错误。假设验证码中的单词是一个完备的有用的英文单词,长度为4个字母,现实上我们利用同一个词典生成和破解验证码;单词全部字母均为大写情势,不实用符号、数字或空格。为了增加难度,再生成图像时对单词利用差异的错切变化效果。
绘制验证码
- 我们编写创建验证码的函数,绘制一张含有单词的图像,对单词利用错切变化效果。绘制图像利用PIL库,错切变化需要利用scikit-image库。
- import numpy as np
- from PIL import Image, ImageDraw, ImageFont
- from skimage import transform as tf
- from matplotlib import pyplot as plt
- # 生成验证码的基础函数,接收一个单词和错切值(通常在0到0.5之间),还可以指定图像大小
- def create_captcha(text, shear=0, size=(100, 24)):
- # 使用字母L生成一张黑白图像,为ImageDraw类初始化一个实例
- im = Image.new('L', size, 'black')
- draw = ImageDraw.Draw(im)
- # 指定验证码文字所使用的字体
- font = ImageFont.truetype(r'C:\Windows\Fonts\Gabriola.ttf', 22)
- draw.text((2, 2), text, fill=1, font=font)
- # 把PIL图像转换为numpy数组
- image = np.array(im)
- # 应用错切变化效果,返回图像
- affine_tf = tf.AffineTransform(shear=shear)
- # 根据给定的坐标变换图像
- image = tf.warp(image, affine_tf)
- # 对图像特征进行归一化处理,确保特征值落在0~1之间
- return image/image.max()
- image = create_captcha('JOHN', shear=0.5)
- plt.imshow(image, cmap='gray')
- plt.show()
复制代码
- 固然验证码是单词,但是我们可以把大标题转换为辨认字母的小的标题,验证码辨认算法的下一步是分割单词,找出其中的字母。创建函数探求图像中连续的黑色像素,抽取他们作为新的小图像,这些小图像就是我们要找的字母。
- from skimage.measure import label, regionprops
- # 图像分割函数接收图像,返回小图像列表,每张小图像为单词的一个字母
- def segment_iamge(image):
- # 检测每个字母的位置,使用label函数能找出图像中像素值相同且由连接在一起的像素块
- # label函数参数是图像数组,返回跟输入同型的数组,在返回的数组中图像连接在一起的区域用不同的值表示,在这些区域以外的像素用0表示
- labeled_image = label(image > 0)
- subimages = []
- # regionprops函数可以抽取连续区域,遍历这些区域分别处理,通过region对象获取到当前区域的相关信息
- for region in regionprops(labeled_image):
- # 用当前区域的起始位置坐标作为索引就能抽取到小图像
- start_x, start_y, end_x, end_y = region.bbox
- subimages.append(image[start_x:end_x, start_y:end_y])
- # 没有找到小图像就把原图像作为子图返回
- if len(subimages) == 0:
- return [image,
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |