You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PIL图像中单独旋转每个验证码字符?

实现PIL验证码单个字符单独旋转的方法

核心思路是为每个字符创建独立的透明临时图像,绘制字符后进行旋转,再将旋转后的图像粘贴到主验证码画布上,解决直接绘制无法旋转字符的问题。以下是修改后的完整代码:

import random
from PIL import Image, ImageDraw, ImageFont

def generate_random_string(length):
    random_string = ""
    for i in range(length):
        random_string += random.choice('1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    return random_string

def draw_random_ellipse(draw):
    # 补充原代码缺失的随机椭圆绘制函数
    x1 = random.randint(0, 400)
    y1 = random.randint(0, 200)
    x2 = x1 + random.randint(10, 50)
    y2 = y1 + random.randint(10, 50)
    draw.ellipse([x1, y1, x2, y2], fill=(random.randint(150,255), random.randint(150,255), random.randint(150,255), 128))

def generate_captcha():
    fonts = ["Aaargh.ttf", "SerpentineBoldItalic.ttf", "FUTURAM.ttf"]
    character_count = random.randrange(6, 10)
    captcha_string = generate_random_string(character_count)
    
    # 定义背景色(替换原代码未定义的default_color变量)
    bg_color = (255, 255, 255)
    captcha_image = Image.new("RGBA", (400, 200), bg_color)
    draw = ImageDraw.Draw(captcha_image, "RGBA")
    
    # 绘制干扰椭圆
    for i in range(20):
        draw_random_ellipse(draw)
    
    # 初始位置
    x = 10 + random.randrange(0, 50)
    y = 100 + random.randrange(-20, 20)
    
    for letter in captcha_string:
        selected_font = random.choice(fonts)
        font_style = ImageFont.truetype(selected_font, 50)
        
        # 1. 创建透明临时图像,尺寸足够容纳旋转后的字符
        temp_img = Image.new("RGBA", (80, 80), (255, 255, 255, 0))
        temp_draw = ImageDraw.Draw(temp_img)
        
        # 2. 在临时图像居中位置绘制字符,避免旋转裁剪
        text_bbox = temp_draw.textbbox((0,0), letter, font=font_style)
        text_width = text_bbox[2] - text_bbox[0]
        text_height = text_bbox[3] - text_bbox[1]
        temp_x = (80 - text_width) // 2
        temp_y = (80 - text_height) // 2
        temp_draw.text((temp_x, temp_y), letter, (0, 0, 0), font=font_style)
        
        # 3. 随机生成旋转角度(-30到30度区间)
        rotate_angle = random.randint(-30, 30)
        rotated_img = temp_img.rotate(rotate_angle, expand=True)
        
        # 4. 计算粘贴位置,让字符垂直居中于基准线
        rotated_height = rotated_img.height
        paste_y = y - rotated_height // 2
        
        # 5. 粘贴旋转后的字符,用alpha通道做掩码保证透明效果
        captcha_image.paste(rotated_img, (x, paste_y), rotated_img)
        
        # 6. 更新x坐标,根据旋转后的宽度调整间距避免重叠
        x += rotated_img.width + random.randint(5, 15)
    
    return (captcha_image, captcha_string)

关键细节说明

  • 透明临时图像:采用RGBA模式并设置全透明背景,确保旋转后的字符边缘不会覆盖主图的背景或干扰元素。
  • 居中绘制字符:通过textbbox获取字符的精确尺寸,在临时图像中居中绘制,避免旋转时字符被裁剪。
  • 旋转参数:rotate方法的expand=True参数会自动扩展图像尺寸,完整容纳旋转后的字符内容。
  • 掩码粘贴:paste方法传入旋转后的图像作为第三个参数,利用其alpha通道作为掩码,仅粘贴字符的非透明区域。

内容的提问来源于stack exchange,提问作者mattdub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 14:44:55