captcha模块ImageCaptcha之create_captcha_image

使用captcha模块即可直接生成验证码

码云链接

语言:python
python版本:Python 3.8.3
编译器:vscode
需要的模块:captcha,PIL
  • 安装capthca模块pip install -i https://pypi.douban.com/simple captcha
  • 查看更多验证码的文章请点击[传送门]
  1. create_captcha_image源码
def create_captcha_image(self, chars, color, background):
        """Create the CAPTCHA image itself.

        :param chars: text to be generated.
        :param color: color of the text.
        :param background: color of the background.

        The color should be a tuple of 3 numbers, such as (0, 255, 255).
        """
        image = Image.new('RGB', (self._width, self._height), background)
        draw = Draw(image)

        def _draw_character(c):
            font = random.choice(self.truefonts)
            w, h = draw.textsize(c, font=font)

            dx = random.randint(0, 4)
            dy = random.randint(0, 6)
            im = Image.new('RGBA', (w + dx, h + dy))
            Draw(im).text((dx, dy), c, font=font, fill=color)

            # rotate
            im = im.crop(im.getbbox())
            im = im.rotate(random.uniform(-30, 30), Image.BILINEAR, expand=1)

            # warp
            dx = w * random.uniform(0.1, 0.3)
            dy = h * random.uniform(0.2, 0.3)
            x1 = int(random.uniform(-dx, dx))
            y1 = int(random.uniform(-dy, dy))
            x2 = int(random.uniform(-dx, dx))
            y2 = int(random.uniform(-dy, dy))
            w2 = w + abs(x1) + abs(x2)
            h2 = h + abs(y1) + abs(y2)
            data = (
                x1,
                y1,
                -x1,
                h2 - y2,
                w2 + x2,
                h2 + y2,
                w2 - x2,
                -y1,
            )
            im = im.resize((w2, h2))
            im = im.transform((w, h), Image.QUAD, data)
            return im

        images = []
        for c in chars:
            if random.random() > 0.5:
                images.append(_draw_character(" "))
            images.append(_draw_character(c))

        text_width = sum([im.size[0] for im in images])

        width = max(text_width, self._width)
        image = image.resize((width, self._height))

        average = int(text_width / len(chars))
        rand = int(0.25 * average)
        offset = int(average * 0.1)

        for im in images:
            w, h = im.size
            mask = im.convert('L').point(table)
            image.paste(im, (offset, int((self._height - h) / 2)), mask)
            offset = offset + w + random.randint(-rand, 0)

        if width > self._width:
            image = image.resize((self._width, self._height))

        return image
  • 接受的参数
    在这里插入图片描述
    1. chars图片上面的字,只要字体支持,那就可以是任意字符
    2. color是字的颜色,可以是英文单词里面的颜色,也可以指定rgb(0,0,0)这样的格式
    3. background图片的背景颜色,同上
  • 紧接着是下面的两行代码
image = Image.new('RGB', (self._width, self._height), background)
draw = Draw(image)
  • Image是从PIL导入的模块
from PIL import Image
  • Image.new()方法源码
    在这里插入图片描述
  • 查看Pillow的文档得到第一个参数接受的模型(谷歌自带的翻译…)
    在这里插入图片描述
  • 所以下面的代码传入的是RGB模型,就是真彩色,第二个就是图片的大小了,然后就是背景颜色
    image = Image.new('RGB', (self._width, self._height), background)
  • 剩下的代码看一下就好,最后返回的是PIL.Image.Image类型
  • 然后就是遍历传进来的chars,使其调用_draw_charecter方法,并将单个字符传给这个函数
    在这里插入图片描述
  • 其中random.random()>0.5那个是控制相邻的字符之间的距离,所有有的时候相邻字符离的远,有的离的近,就是因为这个
  • 重要的是这个_draw_character()函数
def _draw_character(c):
	font = random.choice(self.truefonts)
	w, h = draw.textsize(c, font=font)
	
	dx = random.randint(0, 4)
	dy = random.randint(0, 6)
	im = Image.new('RGBA', (w + dx, h + dy))
	Draw(im).text((dx, dy), c, font=font, fill=color)
	
	# rotate
	im = im.crop(im.getbbox())
	im = im.rotate(random.uniform(-30, 30), Image.BILINEAR, expand=1)
	
	# warp
	dx = w * random.uniform(0.1, 0.3)
	dy = h * random.uniform(0.2, 0.3)
	x1 = int(random.uniform(-dx, dx))
	y1 = int(random.uniform(-dy, dy))
	x2 = int(random.uniform(-dx, dx))
	y2 = int(random.uniform(-dy, dy))
	w2 = w + abs(x1) + abs(x2)
	h2 = h + abs(y1) + abs(y2)
	data = (
	    x1,
	    y1,
	    -x1,
	    h2 - y2,
	    w2 + x2,
	    h2 + y2,
	    w2 - x2,
	    -y1,
	)
	im = im.resize((w2, h2))
	im = im.transform((w, h), Image.QUAD, data)
	return im
  • w, h = draw.textsize(c, font=font)这个方法就是获取字体的大小而已
    在这里插入图片描述
  • 咱们来看看这个getsize的返回值是咋样的
# 在ipython下运行
from captcha.image import ImageCaptcha
import string

fonts = [r'C:\Windows\Fonts\simfang.ttf']
img = ImageCaptcha(fonts=fonts, font_sizes=[20])
# truefonts是返回字体和大小的,大家别忘了类源码查看那里提到过
temp = img.truefonts[0]
letters = string.ascii_letters
for letter in letters:
	print(temp.getsize(letter), letter)

在这里插入图片描述

  • 算了不写了,写不下去了…
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值