什么是验证码

验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computersand Humans Apart”

(全自动区分计算机和人类的图灵测试)的缩写,

是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,

有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。

这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,

所以回答出问题的用户就可以被认为是人类。

图像验证码

对图像验证码来讲,这类验证码大多是数字、字母的组合,国内也有使用汉字的。

在这个基础上增加噪点、干扰线、变形、重叠、不同字体颜色等方法来增加识别难度。

相应的这种验证码的识别大概分为以下几个步骤:

1.灰度处理

2.二值化

3.降噪

4.识别

PIL介绍

PIL (Python Image Library) 是 Python 平台处理图片的事实标准,兼具强大的功能和简洁的 API。

另外虽然介绍的是 PIL,但实际上安装的却是 Pillow。PIL 的更新速度很慢,而且存在一些难以配置的问题,不推荐使用;

而 Pillow 库则是 PIL 的一个分支,维护和开发活跃,Pillow 兼容 PIL 的绝大多数语法,推荐使用。

安装:

sudo pip install pillow

安装好之后,打开 Python 解释器,输入 from PIL import Image 来测试是否安装成功

PIL基本概念

PIL中所涉及的基本概念有如下几个:通道(bands)、尺寸(size)、坐标系统(coordinate system)。

通道

每张图片都是由一个或者多个数据通道构成。PIL允许在单张图片中合成相同维数和深度的多个通道。

以RGB图像为例,每张图片都是由三个数据通道构成,分别为R、G和B通道。而对于灰度图像,则只有一个通道。

对于一张图片的通道数量和名称,可以通过方法getbands()来获取。方法getbands()是Image模块的方法,它会返回一个字符串元组(tuple)。该元组将包括每一个通道的名称。

from PIL import Image

im = Image.open("code.jpg")

print(im.getbands())

# 输出:

# ('R', 'G', 'B')

尺寸

通过size属性可以获取图片的尺寸。这是一个二元组,包含水平

和垂直方向上的像素的个数。

属性size的使用如下:

from PIL import Image

im = Image.open("code.jpg")

print(im.size)

# 输出:
#
# (240, 60)

PIL操作图像 

PIL 的主要功能定义在 Image 类当中,而 Image 类定义在同名的 Image 模块当中。使用 PIL 的功能,一般都是从新建一个Image 类的实例开始。新建 Image 类的实例有多种方法。

你可以用 Image 模块的 open()函数打开已有的图片档案,也可以处理其它的实例,或者从零开始构建一个实例。

# 生成图片 Image.new(mode, size, color) ⇒ image
# 其中mode表示模式,size表示大小,color表示颜色 from PIL import Image
im= Image.new("RGB", (128, 128), "#FF0000")
im.save('red.jpg') im = Image.open('red.jpg')
im.show()
im_l = im.convert('L') # R=G=B
im_l.show()

Image 类的实例有 4 个常用属性,分别是:

format: 以 string 返回图片档案的格式(JPG, PNG, BMP, None, etc),如果不是从打开文件得到的实例,则返回 None。

mode: 以 string 返回图片的模式(RGB, CMYK, etc)

size: 以二元 tuple 返回图片档案的尺寸 (width, height)

info: 以字典形式返回示例的信息

# Image实例方法:
# convert 将当前图像转换为其他模式,并且返回新的图像。
from PIL import Image
im = Image.open('code.jpg')
print(im.mode)
im1 = im.convert('L')
print(im1.mode)
print(im1.getpixel((1,1)))
print(im1.getpixel((20,6)))
#
# # getpixel((x,y)) 返回给定位置的像素值。如果图像为多通道,则返回一个元组。
from PIL import Image
im1 = Image.open("code.jpg")
print(im1.getpixel((1,1)))
print(im1.getpixel((6,6)))
# (220, 220, 210)
# (204, 214, 205) # crop()图像中剪切出某个矩形大小的图像。它接收一个四元素的元组作为参数,各元素为(left, upper, right, lower),坐标系统的原点(0, 0)是左上角。
from PIL import Image
im1 = Image.open("code.jpg")
im = im1.crop((0, 0, 100, 50)) # 需要四个坐标x1,y1,x2,y2
im.show()

使用滤镜

from PIL import Image,ImageFilter

# 打开一个jpg图像文件,注意是当前路径:
im = Image.open('code.jpg')
# 获得图像尺寸:
w, h = im.size
print('Original image size: %sx%s' % (w, h))
# 缩放到50%:
im.thumbnail((w//2, h//2))
print('Resize image to: %sx%s' % (w//2, h//2))
# 把缩放后的图像用jpeg格式保存:
im.save('thumbnail.jpg', 'jpeg') # 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg') # 高斯模糊
im2.filter(ImageFilter.GaussianBlur).save('GaussianBlur.jpg')
# 普通模糊
im2.filter(ImageFilter.BLUR).save('BLUR.jpg')
# 边缘增强
im2.filter(ImageFilter.EDGE_ENHANCE).save('EDGE_ENHANCE.jpg')
# 找到边缘
im2.filter(ImageFilter.FIND_EDGES).save('FIND_EDGES.jpg')
# 浮雕
im2.filter(ImageFilter.EMBOSS).save('EMBOSS.jpg')
# 轮廓
im2.filter(ImageFilter.CONTOUR).save('CONTOUR.jpg')
# 锐化
im2.filter(ImageFilter.SHARPEN).save('SHARPEN.jpg')
# 平滑
im2.filter(ImageFilter.SMOOTH).save('SMOOTH.jpg')
# 细节
im2.filter(ImageFilter.DETAIL).save('DETAIL.jpg')

生成字母+数字验证码

PIL的ImageDraw提供了一系列绘图方法,让我们可以直接绘图。比如要生成字母验证码图片

画验证码需要的一些基础

from PIL import Image, ImageFilter, ImageDraw, ImageFont

# 创建画笔,用于在图片上画任意内容
img = Image.new(mode='RGB', size=(120,50), color=(0, 0, 0)) # 黑色
draw = ImageDraw.Draw(img, mode='RGB')
img.show() # 画点
img = Image.new(mode='RGB', size=(120, 60), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
# 第一个参数:表示坐标
# 第二个参数:表示颜色
draw.point([100, 100], fill="red")
draw.point([105, 100], fill="red")
draw.point([110, 100], fill="red")
draw.point([300, 300], fill=(0, 255, 255))
# img.show() # 画线
img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
# 第一个参数:表示起始坐标和结束坐标
# 第二个参数:表示颜色
draw.line((100,100,100,300), fill='red')
draw.line((100,100,300,100), fill=(255, 255, 255)) # 写文本
img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
# 第一个参数:表示起始坐标
# 第二个参数:表示写入内容
# 第三个参数:表示颜色
draw.text([0,0],'python',"red")
img.show() # 特殊字体文字
img = Image.new(mode='RGB', size=(180, 60), color=(255, 255, 255))
draw = ImageDraw.Draw(img, mode='RGB')
# 第一个参数:表示字体文件路径
# 第二个参数:表示字体大小
font = ImageFont.truetype('arial.ttf',36)
# 第一个参数:表示起始坐标
# 第二个参数:表示写入内容
# 第三个参数:表示颜色
# 第四个参数:表示颜色
draw.text([0, 0], 'python', "red", font=font)
img.show()

生成字母+数字图形验证码

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import string def rndChar():
"""
生成随机字母+数字
:return:
"""
return random.choice(string.ascii_lowercase + string.digits) def rndColor():
"""
生成随机颜色
:return:
"""
return (random.randint(0, 130), random.randint(0, 130), random.randint(0, 130)) def check_code(width=180, height=60, char_length=5, font_file='micross.ttf', font_size=30):
code = []
img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype(font_file, font_size)
# 创建Draw对象:
draw = ImageDraw.Draw(img, mode='RGB')
# # 填充每个像素:
# for x in range(width):
# for y in range(height):
# draw.point((x, y), fill=rndColor()) # 写文字
font = ImageFont.truetype(font_file, font_size)
for i in range(char_length):
char = rndChar()
code.append(char)
h = random.randint(10, 20)
draw.text([i * 25+6, h], char, font=font, fill=rndColor()) # 写干扰点
for i in range(50):
draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) # 画干扰线
for i in range(3):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=rndColor()) # img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
return img, ''.join(code) if __name__ == '__main__':
# 1. 直接打开
img,code = check_code()
img.show() # 2. 写入文件
# img, code = check_code()
# print(code)
# with open('code3.png','wb') as f:
# img.save(f, format='png') # 3. 写入内存(Python3)
# from io import BytesIO
# stream = BytesIO()
# img.save(stream, 'png')
# stream.getvalue()
# print(stream.getvalue())

简单验证码识别

知识点一: 灰度处理

灰度化处理的基本原理

灰度图像是R、G、B三个分量相同的一种特殊的彩色图像。

简单来讲就是

R=G=B

from PIL import Image

image =Image.open('code.jpg')

im =image.convert('L')

知识点二: 二值化

图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。

def binarizing(img,threshold=127):

   """传入image对象进行灰度、二值处理"""

​    img = img.convert("L") # 转灰度

​    pixdata = img.load()

​    w, h = img.size

​    # 遍历所有像素,大于阈值的为黑色

​    for y in range(h):

​        for x in range(w):

​            if pixdata[x, y] < threshold:

​                pixdata[x, y] = 0

​            else:

​                pixdata[x, y] = 255

​    return img

知识点三: 降噪

根据一个点A的RGB值,与周围的8个点的RBG值比较,设定一个值N(0<N <8),当A的RGB值与周围8个点的RGB相等或者小于N时,此点为噪点

 def depoint(img):

   """传入二值化后的图片进行降噪"""

​    pixdata = img.load()

​    w,h = img.size

​    for y in range(1,h-1):

​        for x in range(1,w-1):

​            count = 0

​            if pixdata[x,y-1] > 245:#上

​                count = count + 1

​            if pixdata[x,y+1] > 245:#下

​                count = count + 1

​            if pixdata[x-1,y] > 245:#左

​                count = count + 1

​            if pixdata[x+1,y] > 245:#右

​                count = count + 1

​            if count > 4:

​                pixdata[x,y] = 255

​    return img

pytesser3识别

安装

pip Install pytesser3 

下载Tesseract 文件

pytesser是谷歌OCR开源项目的一个模块,在python中导入这个模块即可将图片中的文字转换成文本。

链接:https://code.google.com/p/pytesser/

或者使用 http://yun.baidu.com/s/1jHJvNiI

安装路径

 

设置路径

 验证码

实现代码

def depoint(image):# 像素 判断一个点周围情况 4,8邻域
"""
降噪
:param image:
:return:
"""
pixdata = image.load()
print(pixdata)
w, h = image.size
for y in range(1,h-1):
for x in range(1,w-1):
count = 0
if pixdata[x,y-1] > 245:
count +=1
if pixdata[x,y+1] > 245:
count += 1
if pixdata[x-1,y] > 245:
count += 1
if pixdata[x+1,y] > 245:
count += 1
if count > 3:
pixdata[x,y] = 255
return image def binaring(image,threshold = 160):
"""
对传入的图像进行灰度,二值化处理
:param image:
:param threshold:
:return:
"""
image = image.convert('L')
image.show()
pixdata = image.load()
# print(pixdata)
w, h = image.size
for y in range(h):
for x in range(w):
# print(pixdata[x,y])
pix_l.append(pixdata[x,y])
if pixdata[x, y] < threshold:
pixdata[x, y] = 0
else:
pixdata[x, y] = 255
return image from pytesser3 import image_to_string
# from pytesser3 import image_file_to_string
from PIL import Image
image = Image.open('code3.png')
pix_l =[]
# image.show()
# pix_l_set = sorted(list(set(pix_l)))
# print(pix_l_set[:len(pix_l_set)//2]) # 求平均数的值
image2 = binaring(image) # 二值化
image3 = depoint(image2) # 降噪
image3.show()
# 识别文字
print('code: ',image_to_string(image3))

二值化

降噪

Python——pytessercat识别简单的验证码的更多相关文章

  1. java识别简单的验证码

    1.老规矩,先上图 要破解类似这样的验证码: 拆分后结果: 然后去匹配,得到结果. 2.拆分图片 拿到图片后,首先把图片中我们需要的部分截取出来. 具体的做法是,创建一个的和图片像素相同的一个代表权重 ...

  2. 基于Python使用SVM识别简单的字符验证码的完整代码开源分享

    关键字:Python,SVM,字符验证码,机器学习,验证码识别 1   概述 基于Python使用SVM识别简单的验证字符串的完整代码开源分享. 因为目前有了更厉害的新技术来解决这类问题了,但是本文作 ...

  3. python 简单图像识别--验证码

    python  简单图像识别--验证码 记录下,准备工作安装过程很是麻烦. 首先库:pytesseract,image,tesseract,PIL windows安装PIL,直接exe进行安装更方便( ...

  4. 【转】Python OCR识别图片验证码

    转载自:博客 对于某些网站登录的时候,往往需要输入验证码才能实现登录.如果要爬虫这类网站,往往总会比这个验证码导致无法爬取数据.以下介绍一种比较折中的方法,也是比较可行的方法: 实现思想: 1.通过截 ...

  5. 使用TensorFlow 来实现一个简单的验证码识别过程

    本文我们来用 TensorFlow 来实现一个深度学习模型,用来实现验证码识别的过程,这里识别的验证码是图形验证码,首先我们会用标注好的数据来训练一个模型,然后再用模型来实现这个验证码的识别. 1.验 ...

  6. Flask学习之旅--用 Python + Flask 制作一个简单的验证码系统

    一.写在前面 现在无论大大小小的网站,基本上都会使用验证码,登录的时候要验证,下载的时候要验证,而使用的验证码也从那些简简单单的字符图形验证码“进化”成了需要进行图文识别的验证码.需要拖动滑块的滑动验 ...

  7. knn识别简单验证码

    参考 https://www.biaodianfu.com/knn-captcha-recognition.html 内容大致一样,只是根据自己的想法加入了一些改动 KNN(k近邻算法) 算法原理请看 ...

  8. python简单处理验证码,三分钟,不能再多了

    序言 大家好鸭, 又是我小熊猫啦 我们在做采集数据的时候,过快或者访问频繁,或者一访问就给弹出验证码,然后就蚌珠了~今天就给大家来一个简单处理验证码的方法 环境模块 Python和pycharm如果还 ...

  9. python利用selenium库识别点触验证码

    利用selenium库和超级鹰识别点触验证码(学习于静谧大大的书,想自己整理一下思路) 一.超级鹰注册:超级鹰入口 1.首先注册一个超级鹰账号,然后在超级鹰免费测试地方可以关注公众号,领取1000积分 ...

随机推荐

  1. cdnbest区域里快速配置全部节点的缓存

    1.在cdn后台区域中自定义区域配置中添加下面代码,具体参数也可自行调整,代码解释在文档最下面有 <!--#start --> <config> <lang>zh_ ...

  2. oracle用户间表数据复制迁移

    如system用户要将scott中的emp表倒入其中,按如下方法: 1.登录scott用户 2.给system用户赋予查询emp标的权限: grant select on emp to system; ...

  3. 深入理解Jvm 虚拟机

    参考: 内存模型:https://blog.csdn.net/qq_34280276/article/details/52783096 类加载原理:https://nomico271.github.i ...

  4. JAVA中float与double的区别

    float是单精度类型,精度是8位有效数字,取值范围是10的-38次方到10的38次方,float占用4个字节的存储空间 double是双精度类型,精度是17位有效数字,取值范围是10的-308次方到 ...

  5. 微信小程序记账本进度二

    二.1,下载微信web开发者工具 2,使用新注册的账号登录,并创建工程

  6. [leetcode]51. N-QueensN皇后

    The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens ...

  7. iview表格高度自适应只需要三步即可

    1. 需要增加到table表格里的 highlight-row :height="tableHeight" ref="table" 2.在return 定义一个 ...

  8. 校验金额、大小写字母、大写字母、合法uri、email

    /* 合法uri*/ export function validURL(url) { const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0- ...

  9. 20172325 2018-2019-2 《Java程序设计》第九周学习总结

    20172325 2018-2019-2 <Java程序设计>第九周学习总结 教材学习内容总结 图的定义 图是由顶点集(VertexSet)和边集(EdgeSet)组成,针对图G,顶点集和 ...

  10. 创建 sp

    创建 sharepoint solutions---Empty project--module(跟环境中的网站页面一样) element.xml增加pages url=“site pages” 将ws ...