[На русском] Decoder Captcha

Тема в разделе "Материалы по SEO", создана пользователем Schtirliz, 1 мар 2008.

Статус темы:
Закрыта.
  1. Schtirliz

    Schtirliz Постоялец

    Регистр.:
    6 апр 2006
    Сообщения:
    77
    Симпатии:
    168
    Decoder Captcha

    [​IMG]

    Рыскав по инету я заменил, что опять какой то барыга продаёт кучу софта и в ней был хрумер 4. Я почитал описалово, прифигел и опять задумался над тем как же декодят эти капчи. Как то раз я уже пытался задекодить самую простую но ничего не вышло и я забил на это дело. В этот раз я наконец то написал скрипт который декодит одну из самых простейцих капч чему очень рад(ура я не такой тупой =)). В капче присутствует эффект шума и ничего более.

    Вот пример капчи:

    [​IMG]

    Алгоритм очень простой:
    -Переводим капчу в монохромное(чёрно-белое) изображение.
    -Ищем первый чёрный пиксел и после нахождения ставим флаг что это начало первый цифры
    -Сверяем каждую колонку пикселов идя вправо и суммируя чёрные до тех пор пока не дойдём до колонки где наша сумма не станет равной нулю.
    -Если стала равна нулю то значит один символ мы идентифицировали.
    -Обнуляем флаги.
    -Сравниваем сомвол с шаблонами.
    -Записываем в переменную для вывода задекоденной капчи.

    Итак обо всём попорядку.

    Переводим капчу в монохромное(чёрно-белое) изображение.

    Унас есть капча(пример выше). В чём её слабость. Ну первое что бросается в глаза это то, что все символы написаны белым. Так за это и нужно зацепиться. Алгоритм перевода в монохромное изображение будет таков, что все пикселы кроме белого мы переводим в белый, а белые пикселы в чёрный.

    Код:
    /Цикл перевода капчи в монохромное изображение
    for($i=0;$i<$width;$i++)
    {
    for($j=0;$j<$height;$j++)
    {
    // Получаем RGB пикселя по координате
    $color=imageColorAt($im,$i,$j);
    // Разбиваем RGB на Red,Green,Blue и записываем каждую составляющую в свою переменную
    list($r,$g,$b)=array_values(imageColorsForIndex($im,$color));
    //Сравнение белого ли цвета пиксель
    if($r==255 && $g=255 && $b==255)
    {
    imagesetpixel($im,$i,$j,$black); // Установка пикселя в чёрный
    } else {
    imagesetpixel($im,$i,$j,$white); // Установка пикселя в белый
    }
    }
    }
    После этого капча станет такого вида.

    [​IMG]

    Далее нам нужно отсекать по каждому символу в капче. Разберём код

    Код:
    for($i=0;$i<$width;$i++)
    {
    for($j=0;$j<$height;$j++)
    {
    // Получаем RGB пикселя по координате
    $color=imageColorAt($im,$i,$j);
    // Разбиваем RGB на Red,Green,Blue и записываем каждую составляющую в свою переменную
    list($r,$g,$b)=array_values(imageColorsForIndex($im,$color));
    // Сравнение на чёрный пиксел
    if($r==0 && $g==0 && $b==0 && $left==0)
    {
    $left=1;
    $black_pix++;
    }
    // Сравнение на чёрный пиксел и левую границу символа
    else if($r==0 && $g==0 && $b==0 && $left==1)
    {
    $black_pix++;
    }
    // То же самое только ещё добавлна проверка на кол-во чёрных пикселов
    else if($r==0 && $g==0 && $b==0 && $left==1 && $black_pix==0)
    {
    $left=0;
    $black_pix=0;
    }
    }
    Уже в монохромной капче мы ищем первый чёрный пиксел. Если это первый чёрный пиксе и флаг левой границы не установлен, то мы утсанавливаем этот флаг и увеличиваем переменную $black_pix которая отвечает за кол-во символов в данном столбце пикселов. Далее если флаг границы установлен, то мы просто увеличиваем переменную $black_pix, а вот если флаг границы утсановлен и переменная $black_pix равна нулю то значит мы достигли гонца первого символа и можем начать сравнеие по шаблонам предварительно обнулив переменную $black_pix и флаг $left.Каждый раз после подсчёта чёрных пикселов мы добавляли в переменную $char значение переменной $black_pix. Как это сделано можно посмотреть в коде декодера, здесь я этот момент затрагивать не стану.

    Идём дальше по коду.

    Сравниваем сомвол с шаблонами.

    Перед тем как делать сравнение я подготовил шаблоны для всех цифр которы есть в капче.

    Код:
    //Цикл сравнения цифры из капчи с каждой цифрой по шаблонам
    for($x=0;$x {
    for($y=0;$y {
    //Если равно кол-во чёрных пикселов то увеличиваем переменную OK
    if($char[$y]==$templates[$x][$y])
    {
    //Увеличили совпадения
    $ok++;
    //Если кол-во совпадений больше либо равно 8 то нашли цифру
    if($ok>=8)
    {
    $out .= $x;
    break;
    }
    }
    }
    //Обнуляем переменную совпадений
    $ok=0;
    }
    //Обнуляем переменную символа
    $char=”;
    }
    содержится количество символов в каждом стобце пикселов для данной отсечённой цифоы из капчи. Там будет чтото вроде 23433343. Это значит, что в ширина символа всего 8 пикселов и в первом столбце чёрных пиксела 2, во втором 3 ну итд.
    Исключение составляет только цифра 4, ширина то у неё тоже 8 пикселов, но кол-во чёрных пикселов в некоторых столбцах равно 10, а вот сравнение идёт побайтово и шаблон для цифры 4 был сделано из 10 символов. Ну и теперь можно сравнивать побайтово переменную $char с каждым шаблоном и если например первое байт из шаблона совпадает с первым байтом из переменной $char, то мы увеличиваем переменную $ok, ну а если кол-во совпадений становится 8 и больше то мы просто прерывааем цикли так как нашли цифру. В переменную $out записываем переменную $x так как символы расположены по порядку в массиве $templates то $x будет соответствовать искомой цифре.Капчи были взяты с сайта Перейти по ссылке, но там нет готового решения, я решил написать и от что получилось

    Архив с капчами

    Link: Перейти по ссылке

    Код:
    $image = “01.png”; // Сама капча
    
    $black_pix=0; // Кол-во чёрных пикселей по высоте
    $left=0; // Левая граница каждой цифры
    $ok=0; // Кол-во совпадений
    
    //Шаблоны цифр
    $zero = array(4,6,4,4,4,4,6,4);
    $one = array(2,3,1,0,1,0,1,1);
    $two = array(2,4,5,4,4,5,5,3);
    $three = array(2,4,2,3,3,7,7,3);
    $four = array(2,3,3,3,3,1,0,1,0,1);
    $five = array(6,7,4,3,3,5,6,3);
    $six = array(6,8,5,3,3,6,6,2);
    $seven = array(3,4,3,3,3,3,4,3);
    $eigth = array(3,7,7,3,3,7,7,3);
    $nine = array(2,6,6,3,3,5,8,6);
    
    //Большой массив который содержит все шаблоны
    $templates = array($zero,$one,$two,$three,$four,$five,$six,$seven,$eigth,$nine);
    
    //Ширина и высота капчи
    list($width,$height) = getimagesize($image);
    
    //Получаем хендл капчи
    $im = imagecreatefrompng($image);
    
    //определяем чёрный и белые цвета
    $white = imagecolorallocate($im,255,255,255);
    $black = imagecolorallocate($im, 0, 0, 0);
    
    //Цикл перевода капчи в монохромное изображение
    for($i=0;$i<$width;$i++)
    {
    for($j=0;$j<$height;$j++)
    {
    // Получаем RGB пикселя по координате
    $color=imageColorAt($im,$i,$j);
    // Разбиваем RGB на Red,Green,Blue и записываем каждую составляющую в свою переменную
    list($r,$g,$b)=array_values(imageColorsForIndex($im,$color));
    //Сравнение белого ли цвета пиксель
    if($r==255 && $g=255 && $b==255)
    {
    imagesetpixel($im,$i,$j,$black); // Установка пикселя в чёрный
    } else {
    imagesetpixel($im,$i,$j,$white); // Установка пикселя в белый
    }
    }
    }
    
    ($i=”0;$i<$width;$i++)<BR”> {
    for($j=0;$j<$height;$j++)
    {
    // Получаем RGB пикселя по координате
    $color=imageColorAt($im,$i,$j);
    // Разбиваем RGB на Red,Green,Blue и записываем каждую составляющую в свою переменную
    list($r,$g,$b)=array_values(imageColorsForIndex($im,$color));
    // Сравнение на чёрный пиксел
    if($r==0 && $g==0 && $b==0 && $left==0)
    {
    $left=1;
    $black_pix++;
    }
    // Сравнение на чёрный пиксел и левую границу символа
    else if($r==0 && $g==0 && $b==0 && $left==1)
    {
    $black_pix++;
    }
    // То же самое только ещё добавлна проверка на кол-во чёрных пикселов
    else if($r==0 && $g==0 && $b==0 && $left==1 && $black_pix==0)
    {
    $left=0;
    $black_pix=0;
    }
    }
    //Проверка равено ли кол-во чёрных пикселов в столбце 0
    if($black_pix!=0)
    {
    $char .= $black_pix;
    } else {
    //Цикл сравнения цифры с каждой цифрой по шаблонам
    for($x=0;$x {
    for($y=0;$y {
    //Если равно кол-во чёрных пикселов то увеличиваем переменную OK
    if($char[$y]==$templates[$x][$y])
    {
    //Увеличили совпадения
    $ok++;
    //Если кол-во совпадений больше либо равно 8 то нашли цифру
    if($ok>=8)
    {
    $out .= $x;
    break;
    }
    }
    }
    //Обнуляем переменную совпадений
    $ok=0;
    }
    //Обнуляем переменную символа
    $char=”;
    }
    //Обнуляем переменную кол-ва чёрных пикселов
    $black_pix=0;
    }//Вывод капчи и прочей информации
    print(”————————–
    “);
    print(”Sample captcha decode:
    “);
    print(”————————–
    “);
    print(” <—> “.$out.”“);
    print(”Полный кодЕсли чтото для вас стало сложно или непонятно, если есть какие то предложение или замечания, пишите в ПМ, пишите здесь, пишите в асю или жабер(если знаете конечно).
    Вот и всё…
    Author: perdimonokl aka 4nob1oz just 4 fun

    Перейти по ссылке
     
  2. Lonely Wolf

    Lonely Wolf Прохожие

    Привет бро, респект за статейку, только надо продолжить про помехи в виде линей и разворотов цифр и букв ;-)
     
Статус темы:
Закрыта.