方式一:
# -*- coding: utf-8 -*-
import random,os
import string
# pip install Pillow
# Image:是一个画板(context),ImageDraw:是一个画笔, ImageFont:画笔的字体
from PIL import Image,ImageDraw,ImageFont
from common_utils.lqredis import SiteRedis
# Captcha验证码
class Captcha(object):
# 把一些常量抽取成类属性
#字体的位置
font_path = os.path.dirname(os.path.realpath(__file__)) + '/verdana.ttf'
#生成几位数的验证码
number = 4
#生成验证码图片的宽度和高度
size = (100,30)
#背景颜色,默认为白色 RGB(Re,Green,Blue)
bgcolor = (255,255,255)
#随机字体颜色
fontcolor = (random.randint(0,100),random.randint(0,100),random.randint(0,100))
# 验证码字体大小
fontsize = 25
#随机干扰线颜色。
linecolor = (random.randint(0,220),random.randint(0,255),random.randint(0,100))
# 是否要加入干扰线
draw_line = True
# 是否绘制干扰点
draw_point = True
# 加入干扰线的条数
line_number = 3
SOURCE = list(string.letters)
for index in range(0, 10):
SOURCE.append(str(index))
#用来随机生成一个字符串(包括英文和数字)
# 定义成类方法,然后是私有的,对象在外面不能直接调用
@classmethod
def gene_text(cls):
# return ''.join(random.sample(cls.SOURCE,cls.number))#number是生成验证码的位数
return ''.join(random.sample('01234567898',4))
#用来绘制干扰线
@classmethod
def __gene_line(cls,draw,width,height):
begin = (random.randint(0, width), random.randint(0, height))
end = (random.randint(0, width), random.randint(0, height))
draw.line([begin, end], fill = cls.linecolor)
# 用来绘制干扰点
@classmethod
def __gene_points(cls,draw,point_chance,width,height):
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]
for w in xrange(width):
for h in xrange(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))
#生成验证码
@classmethod
def gene_code(cls):
width,height = cls.size #宽和高
image = Image.new('RGBA',(width,height),cls.bgcolor) #创建图片
font = ImageFont.truetype(cls.font_path,cls.fontsize) #验证码的字体
draw = ImageDraw.Draw(image) #创建画笔
text = cls.gene_text() #生成字符串
font_width, font_height = font.getsize(text)
draw.text(((width - font_width) / 2, (height - font_height) / 2),text,font= font,fill=cls.fontcolor) #填充字符串
# 如果需要绘制干扰线
if cls.draw_line:
# 遍历line_number次,就是画line_number根线条
for x in xrange(0,cls.line_number):
cls.__gene_line(draw,width,height)
# 如果需要绘制噪点
if cls.draw_point:
cls.__gene_points(draw,10,width,height)
return (text,image)
#用来验证验证的函数
@classmethod
def check_captcha(cls,captcha):
captcha_lower = captcha.lower()
if SiteRedis.get_keys(captcha_lower):
SiteRedis.dele(captcha_lower)
return True
else:
return False
#图形验证码
def graph_captcha():
# 获得文体和图片
text, image = Captcha.gene_code()
# StringIO 相当于是一个管道
out = StringIO()
# 把StringIO 塞进这个管道中,并指定图片的格式
image.save(out, 'png')
# 将StringIO的指针指向开始的位置
out.seek(0)
# 生成一个响应对象,out,read是把图片流读出来
response = make_response(out.read())
# 指定响应的类型n
response.content_type = 'image/pag'
SiteRedis.set(text.lower(), text.lower(), expire='60')
return response
方式二:
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
import cv2,sys
import numpy as np
import matplotlib.pyplot as plt
path = sys.path[0] + '/verdana.ttf' # 选择字体
# random chr
def rndChar():
return chr(random.randint(65, 90)) # 随机字母
def rndInt():
return str(random.randint(0, 9)) # 随机数字
def rndColor():
return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) # 随机颜色
def rndColor2():
return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) # 随机颜色
def gaussian_noise(): # 高斯噪声
mu = 125
sigma = 20
return tuple((np.random.normal(mu, sigma, 3).astype(int)))
def rotate(x, angle): # 旋转
M_rotate = cv2.getRotationMatrix2D((x.shape[0] / 2, x.shape[1] / 2), angle, 1)
x = cv2.warpAffine(x, M_rotate, (x.shape[0], x.shape[1]))
return x
width = 180 * 4
height = 180
def gen_image(num):
for l in range(num):
image = Image.new('RGB', (width, height), (255, 255, 255)) # 先生成一张大图
font = ImageFont.truetype(path, 36)
draw = ImageDraw.Draw(image) # 新的画板
for x in range(0, width):
for y in range(0, height):
draw.point((x, y), fill=rndColor())
label = []
for t in range(4): # 每一张验证码4个数字
numb = rndInt()
draw.text((180 * t + 60 + 10, 60 + 10), numb, font=font, fill=rndColor2())
label.append(numb)
with open(sys.path[0] + "/label.txt", "a") as f:
for s in label:
f.write(s + ' ')
f.writelines("\n") # 写入label
img = image.filter(ImageFilter.GaussianBlur(radius=0.5))
img = np.array(img)
img1 = np.array([])
for i in range(0, 4):
img0 = img[:, 180 * i: 180 * i + 180] # 提取含有验证码的小图
angle = random.randint(-45, 45)
img0 = rotate(img0, angle) # 对小图随机旋转
if img1.any():
img1 = np.concatenate((img1, img0[60:120, 60:120, :]), axis=1)
else:
img1 = img0[60:120, 60:120, :]
plt.imsave(sys.path[0] + '/' + str(l) + '.jpg', img1) # 保存结果
if __name__ == '__main__':
gen_image(5)
方式三:
from captcha.image import ImageCaptcha
# 验证码的包
from PIL import Image
import random
import time
# 系统模块
import os
def random_captcha():
captcha_text = []
for i in range(4):
c = random.choice(['0', '1', '2', '3', '4'])
captcha_text.append(c)
return ' '.join(captcha_text) # 字符串中间没有空格
# 生成验证码方法
def gen_capthca():
image = ImageCaptcha()
captcha_text = random_captcha()
captcha_image = Image.open(image.generate(captcha_text))
return captcha_text, captcha_image
# 定义图片个数
count = 5
# 定义图片文件夹
path = './captcha_image'
if not os.path.exists(path):
os.makedirs(path)
# 循环创建图片
for i in range(count):
# 定义创建时间
now = str(int(time.time()))
# 接收字符串和图片
text, image = gen_capthca()
# 定义图片名称
filename = text + '_' + now + '.png'
# 存储图片
image.save(path + os.path.sep + filename)
print('saved %s' % filename)