Para desenvolver um sistema de captcha visual em Python, a biblioteca Pillow é a ferramenta ideal. O primeiro passo é instalar o pacote através do gerenciador de pacotes:
pip install Pillow
Fundamentos de Manipulação de Imagens
A criação de uma imagem base é feita utilizando a classe Image. Abaixo, demonstramos como inicializar uma tela em branco e salvar o resultado em disco.
from PIL import Image
# Inicializa uma tela de 500x500 pixels com fundo branco
canvas = Image.new(mode="RGB", size=(500, 500), color=(255, 255, 255))
# Persiste a imagem no sistema de arquivos
canvas.save("tela_base.png", format="PNG")
Para desenhar formas e textos, utilizamos o objeto ImageDraw, que atua como um pincel sobre a imagem.
from PIL import ImageDraw
# Cria o objeto de desenho vinculado ao canvas
pincel = ImageDraw.Draw(canvas, mode="RGB")
# Desenha pontos em coordenadas específicas
pincel.point((150, 150), fill="red")
pincel.point((200, 200), fill=(0, 0, 0))
# Traça linhas retas
pincel.line((100, 50, 100, 250), fill="blue", width=2)
pincel.line((50, 100, 250, 100), fill="green", width=2)
# Desenha arcos e circunferências
pincel.arc((100, 300, 300, 500), start=0, end=360, fill="purple")
pincel.arc((200, 200, 400, 400), start=45, end=135, fill="orange")
Adicionando Tipografia Personalizada
A renderização de texto simples pode ser feita diretamente, mas para captchas, é comum utilizar fontes personalizadas para dificultar a leitura por bots.
from PIL import ImageFont
# Carrega uma fonte TrueType com tamanho específico
fonte_custom = ImageFont.truetype("arial.ttf", 32)
# Renderiza texto padrão
pincel.text((10, 10), "Texto Simples", fill="black")
# Renderiza texto com a fonte customizada
pincel.text((10, 50), "Texto Customizado", fill="darkblue", font=fonte_custom)
Implementação do Gerader de Captcha
Combinando os conceitos acima, podemos estruturar um gerador de captcha que produz uma imagem com caracteres aleatórios, cores variadas e um fundo dinâmico.
import random
from PIL import Image, ImageDraw, ImageFont
def gerar_captcha_visual(largura=160, altura=60, qtd_caracteres=4):
# Gera um fundo com cor aleatória suave
cor_fundo = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255))
imagem = Image.new("RGB", (largura, altura), cor_fundo)
desenho = ImageDraw.Draw(imagem)
# Tenta carregar uma fonte, fallback para a padrão se falhar
try:
tipo_fonte = ImageFont.truetype("arial.ttf", 40)
except IOError:
tipo_fonte = ImageFont.load_default()
codigo = ""
for indice in range(qtd_caracteres):
# Sorteia entre letras maiúsculas e números
caractere = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
codigo += caractere
# Cor aleatória e contrastante para o caractere
cor_texto = (random.randint(0, 150), random.randint(0, 150), random.randint(0, 150))
# Calcula a posição X para distribuir os caracteres uniformemente
pos_x = (largura // (qtd_caracteres + 1)) * (indice + 1) - 10
pos_y = random.randint(0, altura - 40)
desenho.text((pos_x, pos_y), caractere, font=tipo_fonte, fill=cor_texto)
# Adiciona linhas de ruído para dificultar o OCR
for _ in range(5):
x1, y1 = random.randint(0, largura), random.randint(0, altura)
x2, y2 = random.randint(0, largura), random.randint(0, altura)
cor_linha = (random.randint(0, 200), random.randint(0, 200), random.randint(0, 200))
desenho.line((x1, y1, x2, y2), fill=cor_linha, width=2)
imagem.save("captcha_gerado.png", "PNG")
return codigo
# Executa a funcao e imprime o codigo gerado para validacao
texto_captcha = gerar_captcha_visual()
print(f"Captcha gerado com sucesso: {texto_captcha}")