8

tengo una imagen de código de imagen que se ve así:Extracción del ruido de fondo de una imagen de código de imagen de replicando el filtro de picar de TesserCap

Usando una utilidad llamada TesserCap de McAfee, pude aplicar un " cortando "filtro a la imagen. (Antes de ejecutarlo, me aseguré de que solo hubiera dos colores en la imagen, blanco y negro.) Me impresionaron mucho los resultados de usar ese filtro con un valor de 2 en el cuadro de texto. Se retira con precisión la mayor parte del ruido, pero mantuvo el texto principal, lo que resulta en esto:

quería implementar algo como esto en uno de mis propios guiones, así que traté de averiguar qué biblioteca de procesamiento de imágenes TesserCap usado. No pude encontrar nada; resulta que usa su propio código para procesar la imagen. Luego leo this whitepaper que explica exactamente cómo funciona el programa. Me dio la siguiente descripción de lo que hace este filtro de picar:

Si el número contiguo de píxeles para valores de escala de grises dados son menos que el número proporcionado en el cuadro numérico, el filtro de cortar sustituye a estas secuencias con 0 (negro) o 255 (blanco) según la elección del usuario. El CAPTCHA se analiza en direcciones horizontales y verticales y se realizan los cambios correspondientes.

No estoy seguro de entender lo que está haciendo. Mi secuencia de comandos está en Python, así que traté de usar PIL para manipular los píxeles, como esa frase descrita. Suena un poco simple, pero falló, probablemente porque yo no sabía muy bien qué es exactamente el filtro estaba haciendo:

(Esto se hace de un código de imagen ligeramente diferente que utiliza un patrón circular.)

También intenté ver si se podía hacer fácilmente con ImageMagick's convert.exe. Su opción -chop es algo completamente diferente. Usar -median junto con algunos comandos de morfología ayudó a reducir parte del ruido, pero aparecieron puntos desagradables y las letras se volvieron muy distorsionadas. No era tan simple como hacer el filtro de corte con TesserCap.

Entonces, mi pregunta es la siguiente: ¿cómo implemento el filtro de corte de TesserCap en Python, ya sea usando PIL o ImageMagick? Ese filtro de corte funciona mucho mejor que cualquiera de las alternativas que he probado, pero parece que no puedo replicarlo. He estado trabajando en esto durante horas y todavía no he averiguado nada.

+0

http://dsp.stackexchange.com/ – scord

+0

como nota al margen, se puede tratar de usar las estadísticas. Outliers (2 sd) o extremos atípicos (3.5 sd) me permitieron quitar captcha images (para propósitos legales) sin perder calidad de imagen –

Respuesta

10

El algoritmo comprueba esencialmente si hay múltiples píxeles de destino (en este caso, píxeles no blancos) en una fila, y los cambia si el número de píxeles es menor o igual que el factor de corte.

Por ejemplo, en una fila de la muestra de píxeles, donde # es negro y - es blanco, la aplicación de un factor de chuleta de 2 transformaría --#--###-##---#####---#-# en ------###-------#####-------. Esto se debe a que hay secuencias de píxeles negros que son menores o iguales a 2 píxeles, y estas secuencias se reemplazan por blancas. Las secuencias continuas de más de 2 píxeles permanecen.

Este es el resultado del algoritmo de chuleta como se aplica en mi código Python (abajo) en la imagen original en su mensaje:

'Chopped' image

Con el fin de aplicar esto a toda la imagen, simplemente realizar este algoritmo en cada fila y en cada columna. Aquí está el código Python que logra que:

import PIL.Image 
import sys 

# python chop.py [chop-factor] [in-file] [out-file] 

chop = int(sys.argv[1]) 
image = PIL.Image.open(sys.argv[2]).convert('1') 
width, height = image.size 
data = image.load() 

# Iterate through the rows. 
for y in range(height): 
    for x in range(width): 

     # Make sure we're on a dark pixel. 
     if data[x, y] > 128: 
      continue 

     # Keep a total of non-white contiguous pixels. 
     total = 0 

     # Check a sequence ranging from x to image.width. 
     for c in range(x, width): 

      # If the pixel is dark, add it to the total. 
      if data[c, y] < 128: 
       total += 1 

      # If the pixel is light, stop the sequence. 
      else: 
       break 

     # If the total is less than the chop, replace everything with white. 
     if total <= chop: 
      for c in range(total): 
       data[x + c, y] = 255 

     # Skip this sequence we just altered. 
     x += total 


# Iterate through the columns. 
for x in range(width): 
    for y in range(height): 

     # Make sure we're on a dark pixel. 
     if data[x, y] > 128: 
      continue 

     # Keep a total of non-white contiguous pixels. 
     total = 0 

     # Check a sequence ranging from y to image.height. 
     for c in range(y, height): 

      # If the pixel is dark, add it to the total. 
      if data[x, c] < 128: 
       total += 1 

      # If the pixel is light, stop the sequence. 
      else: 
       break 

     # If the total is less than the chop, replace everything with white. 
     if total <= chop: 
      for c in range(total): 
       data[x, y + c] = 255 

     # Skip this sequence we just altered. 
     y += total 

image.save(sys.argv[3]) 
+0

¡Gracias por esto! El otro problema al que me enfrenté es que cada personaje tiene un ángulo diferente, ¿hay alguna solución para ello? – Kostanos

+1

@kbhomes hay un pequeño error. ¿Puedes ver que las letras se vuelven más delgadas? Esto se debe a que "x + = total" no funciona en el ciclo for, necesita convertirlo en un ciclo while. –

+0

@AndreMiras ¿cómo puedo hacer que 'x + = total' funcione en un ciclo while? –

3

intentar algo como esto (pseudocódigo):

for each row of pixels: 
    if there is a group of about 3 or more pixels in a row, leave them 
    else remove the pixels 

Después, simplemente repetir lo mismo para las columnas. Parece que podría funcionar al menos un poco. Ir horizontal y verticalmente de esta manera también eliminará las líneas horizontales/verticales.