Binarização Automática para Reconhecimento de CAPTCHA

Método Iterativo

Este algoritmo calcula o limiar ideal ietrativamente:

  1. Encontrar os valores mínimo (Gmin) e máximo (Gmax) de intensidade na imagem, e definir o limiar inicial T0 = (Gmin + Gmax) / 2.
  2. Dividir os pixels com base no limiar atual: pixels com intensidade ≥ T0 são considerados primeiro plano (C1), e os demais como fundo (C2).
  3. Calcular as médias de intensidade m1 (para C1) e m2 (para C2), onde a média é a soma das intensidades dividida pelo número de pixels em cada grupo.
  4. Definir um novo limiar T1 = (m1 + m2) / 2. Se T0 ≠ T1, atribuir T1 a T0 e repetir a partir do passo 2; caso contrário, o limiar é encontrado.

Implementação em Python:

import numpy as np
from PIL import Image

def calcular_limiar_iterativo(caminho_imagem):
    imagem = Image.open(caminho_imagem).convert('L')
    pixels = np.array(imagem).flatten()
    intensidade_min = pixels.min()
    intensidade_max = pixels.max()
    limiar_corrente = (intensidade_min + intensidade_max) // 2
    limiar_anterior = -1
    while limiar_corrente != limiar_anterior:
        grupo_fg = pixels[pixels >= limiar_corrente]
        grupo_bg = pixels[pixels < limiar_corrente]
        media_fg = grupo_fg.mean() if len(grupo_fg) else 0
        media_bg = grupo_bg.mean() if len(grupo_bg) else 0
        limiar_anterior = limiar_corrente
        limiar_corrente = int((media_fg + media_bg) / 2)
    return limiar_corrente

Método Máxima Variância Entre Classes (OTSU)

Este algoritmo encontra o limiar que maximiza a variância entre as classes de pixels (primeiro plano e fundo). Para um limiar T, define-se:

  • Probabilidades: p1 (pixels com intensidade ≥ T) e p2 (pixels com intensidade < T).
  • Médias: m1 (intensidade média do primeiro plano) e m2 (intensidade média do fundo).
  • A variância antre classes é dada por: p1 * p2 * (m1 - m2)2.

O limiar ótimo T é aquele que maximiza essa variância. Implementação em Python:

import numpy as np
from PIL import Image

def calcular_limiar_otsu(caminho_imagem):
    imagem = Image.open(caminho_imagem).convert('L')
    pixels = np.array(imagem).flatten()
    variancias = []
    for t in range(256):
        fg_pixels = pixels[pixels >= t]
        bg_pixels = pixels[pixels < t]
        if len(fg_pixels) == 0 or len(bg_pixels) == 0:
            variancias.append(0)
            continue
        media_fg = fg_pixels.mean()
        media_bg = bg_pixels.mean()
        prob_fg = len(fg_pixels) / len(pixels)
        prob_bg = len(bg_pixels) / len(pixels)
        var_entre_classes = prob_fg * prob_bg * (media_fg - media_bg) ** 2
        variancias.append(var_entre_classes)
    return variancias.index(max(variancias))

Ambos os métodos fornecem limiares similares para bianrização, melhorando a eficiência no reconhecimento de CAPTCHA. Os limiares calculados podem ser usados para converter a imagem em tons de cinza em uma imagem binária, por exemplo, com imagem_binaria = (pixels > limiar) * 255.

Tags: CAPTCHA binarizacao Python NumPy otsu

Publicado em 7-4 18:37