Siguiendo el hilo del post creado por nuestro colega tuxotron, vamos a ver cómo funciona un programa en JavaScript para pasar el test de un Captcha, en concreto para Megaupload.
Nuestro interés está por encima de pasar o no el test del Megaupload, radica en la compleja estructura del programa y el objetivo final del mismo, que no es otro que emular al ser humano a la hora de analizar una imágen.
Shaun Friedle es el creador de este código. Utiliza el HTML 5 Canvas getImageData API para obtener los pixeles de la imágen. El script también incluye la implementación de una red neuronal escrita en JavaScript puro. Los datos extraidos de la imágen se envían a la red neuronal para adivinar exactamente qué caracteres se han usado, usando técnicas de OCR.
El código fuente completo puedes encontrarlo aquí:
http://userscripts.org/scripts/review/38736
Analizándolo un poco:
1. El Captcha es copiado al Canvas y convertido en escala de grises:
function convert_grey(image_data){
for (var x = 0; x < image_data.width; x++){
for (var y = 0; y < image_data.height; y++){
var i = x*4+y*4*image_data.width;
var luma = Math.floor(image_data.data[i] * 299/1000 +
image_data.data[i+1] * 587/1000 +
image_data.data[i+2] * 114/1000);
image_data.data[i] = luma;
image_data.data[i+1] = luma;
image_data.data[i+2] = luma;
image_data.data[i+3] = 255;
}
}
}
2. Luego se separa en tres matrices de pixeles diferentes por cada caracter:
filter(image_data[0], 105);
filter(image_data[1], 120);
filter(image_data[2], 135);
function filter(image_data, colour){
for (var x = 0; x < image_data.width; x++){
for (var y = 0; y < image_data.height; y++){
var i = x*4+y*4*image_data.width;
// Turn all the pixels of the certain colour to white
if (image_data.data[i] == colour) {
image_data.data[i] = 255;
image_data.data[i+1] = 255;
image_data.data[i+2] = 255;
// Everything else to black
} else {
image_data.data[i] = 0;
image_data.data[i+1] = 0;
image_data.data[i+2] = 0;
}
}
}
}
3. Luego se eliminan todos los pixeles que no podemos analizar (posiblemente sean basura), esto se consigue buscando pixeles blancos que están rodeados por otros pixeles negros:
var i = x*4+y*4*image_data.width;
var above = x*4+(y-1)*4*image_data.width;
var below = x*4+(y+1)*4*image_data.width;
if (image_data.data[i] == 255 &&
image_data.data[above] == 0 &&
image_data.data[below] == 0) {
image_data.data[i] = 0;
image_data.data[i+1] = 0;
image_data.data[i+2] = 0;
}