方式一:
# -*- 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)