一张验证码图片需要
- 正确的答案字符绘制到图片中,随机生成
- 增加难度
- 绘制干扰线
- 颜色随机
- 绘制噪点
- 模糊
- 代码如下
import random
import string
import os
from PIL import Image, ImageFont, ImageDraw, ImageFilter # 图像库
class ImageVerify:
"""图像验证码类"""
def __init__(self, length=4, width=140, height=40, size=30):
"""
初始化图片
:param length: 字符个数
:param width: 字符宽度
:param height: 字符高度
:param size: 字符大小
"""
self.length = length
self.width = width
self.height = height
self.size = size
def random_str(self):
"""
随机字符串
26个大小写字母+10个数字作为数据源(将池)
:return:
"""
#
source = string.ascii_letters + ''.join([str(i) for i in range(0, 10)])
return ''.join(random.sample(source, self.length))
def random_color(self, start=0, end=255):
"""随机RGB颜色"""
res = (random.randint(start, end) for i in range(3)) # 产生的是一个生成器
return tuple(res)
def random_lines(self, draw):
"""
绘制干扰线
:param draw: 画笔
:return:
"""
for i in range(self.length):
lines = [(random.randint(0, self.width), random.randint(0, self.height)) for i in range(2)] # 循环两次得到两个点
draw.line(list(lines), fill=self.random_color(50, 200), width=3) # 线的两个点,线条颜色 ,线条宽度
def random_points(self, draw, rate):
"""
绘制噪点
:param draw: 画笔
:param rate: 频率
:return:
"""
for x in range(self.width):
for y in range(self.height):
if random.randint(1, 100) <= rate:
draw.point((x, y), fill=self.random_color(0, 200)) # 点色坐标,颜色
def verify_code(self):
"""
生成验证码图片
:return:
"""
# 创建画布.Image图像 底图
image = Image.new('RGB', (self.width, self.height), (255, 255, 255)) # (颜色通道,(宽,高),(R,G,B))
# 创建Font对象
# os.path.abspath(__file__)返回文件绝对路径
# os.path.dirname() 返回文件上一级路径
file_path = os.path.dirname(os.path.abspath(__file__))
font = ImageFont.truetype(f'{file_path}/HYYakuHei-85W.ttf', self.size)
# 创建画笔对象
draw = ImageDraw.Draw(image) # 告诉这个笔我们在那个画布画画
self.random_lines(draw) # 自定义的随机线条
self.random_points(draw, 10) # 自定义的噪点
# 验证码
code = self.random_str()
# 将验证码绘制到图片中
for i in range(self.length):
draw.text((random.randint(30, 35) * i, random.randint(0, 5)), code[i],
font=font, fill=self.random_color(0, 120))
# 模糊滤镜
image = image.filter(ImageFilter.BLUR) # 模糊
return image, code
if __name__ == '__main__':
imageVerify = ImageVerify()
image, code = imageVerify.verify_code()
with open('test.png', 'wb') as fp:
image.save(fp) # 传入要保存的对象
print(code)