python之pillow模块学习--验证码的生成和破解
一、基础学习
在Python中,有一个优秀的图像处理框架,就是PIL库,pip install pillow
示例1
from PIL import Image # 读取当前图片 im = Image.open('test.png') # 用系统自带的图片查看器查看该图片 im.show() # 将图片进行逆时针旋转 im.rotate(90).show() # 将图片进行顺时针旋转 im.rotate(-90).show() # 保存图像为gif格式 im.save("save.gif", "GIF") # resize成128*128像素大小 out = im.resize((128, 128)) out.save("test2.png", "png") # 拷贝黏贴:设置要拷贝的地区的大小,里面含有四个元素,为左上右下 box = (100, 100, 200, 200) region = im.crop(box) # 按照box的大小拷贝到region里面 region.save("corp.png", "png") # 获取图片基本信息 # format: 图片格式;size:图片大小(长*宽); mode: 色彩模式 print(im.format, im.size, im.mode) # 等比例缩放 size = (128, 128) im.thumbnail(size, Image.ANTIALIAS) im.save("new.png", "png") # 通道分离,将图片封装成三个或四个通道,分别为三个或四个图像对象 print(im.mode) # 查看图片是什么色彩模式 r, g, b, a = im.split() # 我这里是RBGA模式 # r, g, b = im.split() # 如果是RGB模式 # 能分离就能合并,将b,r两个通道进行翻转。 im = Image.merge("RGBA", (b, g, r, a)) # Image.merge("RGB", (b, g, r)) # 图像左右转换 im.transpose(Image.FLIP_LEFT_RIGHT).show() # 图像上下转换 im.transpose(Image.FLIP_TOP_BOTTOM).show() # 图像类型转换 im = im.convert("RGB") im.show() im = im.convert("L") # 灰度图 im.show()
二、生成验证码
生成图片验证码
import random from PIL import Image, ImageDraw, ImageFont, ImageFilter """图片模糊化处理 im = Image.open('test.png') # BLUR:模糊 还有:CONTOUR DETAIL等等 im2 = im.filter(ImageFilter.BLUR) im2.show() """ # 返回随机的RGB数字 def random_color(): return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) def get_code(): with open('1.png', 'wb') as f: # 第一步:生成一张图片(画布) # 创建一个随机颜色的图片对象 # 参数:颜色模式,图片大小,图片颜色 img_obj = Image.new('RGB', (250, 35), random_color()) # 第二步:在该图片对象上生成一个画笔对象 draw_obj = ImageDraw.Draw(img_obj) # 使用什么字体,字体大小,kumo.ttf是我本地下载好的字体文件(sc.chinaz.com)可下载 font_obj = ImageFont.truetype('static/font/kumo.ttf', 28) # 生成验证码 code = '' for i in range(6): num = str(random.randint(0, 9)) # 数字 lower = chr(random.randint(97, 122)) # 小写字母 upper = chr(random.randint(65, 90)) # 大写字母 c = random.choice([num, lower, upper]) # 随机选取一个 code += str(c) # 用画笔把验证码画到图片上 # 参数:xy:坐标,画在哪个位置;text:画的内容;fill:画什么颜色;font:字体格式 draw_obj.text((35 + i * 30, 0), c, fill=random_color(), font=font_obj) # 保存图片并模糊化 image = img_obj.filter(ImageFilter.BLUR) image.save(f) get_code()
加干扰线和干扰点
画完验证码后,可以添加一些干扰 就是在 draw_obj.text((35 + i*30, 0), c, fill=random_color(), font=font_obj)之后加 1. 加干扰线 width = 250 # 图片宽度(防止越界) height = 35 for i in range(5): x1 = random.randint(0, width) x2 = random.randint(0, width) y1 = random.randint(0, height) y2 = random.randint(0, height) draw_obj.line((x1, y1, x2, y2), fill=random_color()) 2. 加干扰点 for i in range(40): draw_obj.point([random.randint(0, width), random.randint(0, height)], fill=random_color()) x = random.randint(0, width) y = random.randint(0, height) draw_obj.arc((x, y, x+4, y+4), 0, 90, fill=random_color())
三、验证码破解
1、预备知识
二值化
from PIL import Image """ 灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度, 范围一般从0到255,白色为255,黑色为0。所谓灰度值是指色彩的浓淡程度, 灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰度值的象素数。 """ # 方法一:使用load函数获取到图片像素,直接对像素进行修改 def convert_img(img, threshold): # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度 img = img.convert("L") # img.convert("1")也是可以直接二值化,但是阈值是固定的127 # 图片的像素二维数组,例如:pixels[0,0] 第一行第一个的像素值 pixels = img.load() # 二值化:自定义灰度界限,大于这个值为白色,小于这个值为黑色 for x in range(img.width): for y in range(img.height): if pixels[x, y] > threshold: pixels[x, y] = 255 else: pixels[x, y] = 0 return img # 方法二:使用point函数 from PIL import Image img = Image.open("captcha.png") # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。 Img = img.convert('L') # 自定义灰度界限,大于这个值为白色,小于这个值为黑色 threshold = 140 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) # 图片二值化 photo = Img.point(table, '1') photo.save("test2.jpg")
获取每个像素点的RGB(RGBA)值
我的理解是:像素值是由这个点的RGB(A)值结合得到的,因此注意了,上面的像素值,我们这里是RGB值
# 获取每个像素点的RGB(RGBA)值 from PIL import Image im = Image.open("captcha.png") # getdata()函数的返回值是一个sequence对象, # sequence对象的每一个值就是这个像素点对应的R、G、B(A)值 data = im.getdata() data = list(data) print(data) # [(135, 142, 169, 255), (104, 111, 139, 255), ....]
2、利用Tesseract识别图片验证码
Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本,目前已支持60多种语言(包括中文)。 Tesseract最初由HP公司开发,后来由Google维护。
因此,我们需要在自己的环境安装Tesseract,至于怎么安装,百度下吧。。。
然后再下载 python对应的Tesseract模块
pip install pytesseract
from PIL import Image import pytesseract """ 灰度图像上每个像素的颜色值又称为灰度,指黑白图像中点的颜色深度, 范围一般从0到255,白色为255,黑色为0。所谓灰度值是指色彩的浓淡程度, 灰度直方图是指一幅数字图像中,对应每一个灰度值统计出具有该灰度值的象素数。 """ def convert_img(img, threshold): """图片二值化""" # 模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度 img = img.convert("L") # img.convert("1")也是可以直接二值化,但是阈值是固定的127 # 图片的像素二维数组,例如:pixels[0,0] 第一行第一个的像素值 pixels = img.load() # 二值化:自定义灰度界限,大于这个值为白色,小于这个值为黑色 for x in range(img.width): for y in range(img.height): if pixels[x, y] > threshold: pixels[x, y] = 255 else: pixels[x, y] = 0 return img def denoise(img): """图片降噪""" data = img.getdata() w, h = img.size count = 0 for x in range(1, h - 1): for y in range(1, h - 1): # 找出各个像素方向 mid_pixel = data[w * y + x] if mid_pixel == 0: top_pixel = data[w * (y - 1) + x] left_pixel = data[w * y + (x - 1)] down_pixel = data[w * (y + 1) + x] right_pixel = data[w * y + (x + 1)] if top_pixel == 0: count += 1 if left_pixel == 0: count += 1 if down_pixel == 0: count += 1 if right_pixel == 0: count += 1 if count > 4: img.putpixel((x, y), 0) return img if __name__ == '__main__': captcha = Image.open("captcha.png") res = convert_img(captcha, 140) ret = denoise(res) ret.show() result = pytesseract.image_to_string(ret) print(result)
3、Tesseract-OCR样本训练
待我研究研究。。。