ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

Распознавание каптчи (PHP + GD)
  #1  
Старый 27.01.2010, 12:18
Аватар для mailbrush
mailbrush
Познавший АНТИЧАТ
Регистрация: 24.06.2008
Сообщений: 1,996
Провел на форуме:
6075534

Репутация: 2731


Отправить сообщение для mailbrush с помощью ICQ
По умолчанию Распознавание каптчи (PHP + GD)

INTRO

Здравствуйте! Здесь я постараюсь рассказать о том, как с помощью PHP и GD распознавать обычные каптчи на примере 000webhost.com (http://www.000webhost.com/includes/php_captcha.php). Сразу хочу сказать, что на основе этого способа можно распознавать только простые каптчи.


Долго я искал статьи, подобные этой, но не нашёл. И мне в голову пришла идея, которую мне получилось успешно реализовать. Именно ею я и хочу поделиться с вами!

Термины

Итак, для начала хочу объяснить некоторые термины (© WikiPedia):
  • PHP - скриптовый язык программирования.
  • GD - библиотека для динамической работы с изображениями.
  • CAPTCHA — полностью автоматизированный публичный тест Тьюринга для различия компьютеров и людей, используемый для того, чтобы определить, кем является пользователь системы: человеком или компьютером. В Рунете часто транскрибируется как капча. Применяется CAPTCHA для того, чтобы предотвратить множественные автоматические регистрации и отправления сообщений программами-роботами. Т. е. задача CAPTCHA — защита от спама, флуда, и захвата аккаунтов.

Распознавание

Для начала надо создать изображение. Для этого воспользуемся функцией imagecreatefrompng, которая создает изображение из указанного файла.
Синтаксис:
PHP код:
#resource imagecreatefrompng (string filename) 
Использование:
PHP код:
$captcha imagecreatefrompng("php_captcha.png"); 
Теперь каптчу нужно разделить на пять ровных частей - для каждой цифры свое изображение. Конечно, вручную делать мы этого не будем, эту работу мы предоставим интерпретатору, тобишь PHP. Создадим цикл, который будет повторяться пять раз, каждый раз обрабатывая новое изображение.
Далее создадим новое изображение с шириной 7px, высотой 10px. Каждый символ каптчи имеет именно такие размеры.
PHP код:
    $im imagecreatetruecolor(710); 
Теперь надо скопировать туда символ каптчи. Воспользуемся функцией imagecopy:
PHP код:
#int imagecopy (resource dst_im, resource src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h) 
Она копирует часть изображения src_im в dst_im, начиная с x,y-координат src_x, src_y, с шириной src_w и высотой src_h.Определённая часть будет скопирована в x,y-координаты dst_x и dst_y. Объясню:
  • src_im - ресурс исходного изображения.
  • dst_im - ресурс нового изображения, в которое и будет записан наш символ.
  • src_x, src_y - начальные X и Y координаты нашего символа.
  • src_w, src_h - длина и высота символа.
Использовать будем так:
PHP код:
imagecopy($im$captcha00$i13710); 
Это значит, что мы часть изображения $captcha, начиная с координат
X: 9 * $i
Y: 13
с шириной 7 и высотой 10. Эта часть и будет скопирована в $im. Наверное непонятно, почему X = 9 * $i, Y - 13. $i - переменная, которая при каждом выполнении цикла увеличивается на единицу. Возьмем первое повторение, когда $i - равно нулю. Таким образом X = 0, Y = 13. Если открыть изображение любым из редакторов, то можно увидеть, что именно эти координаты и будут началом первого символа. При втором выполнении, в $im скопируется второй символ, т.к. X = 9, Y = 13, и т.д... Это изображение - $im выглядит так:
Теперь создаем еще один цикл, в теле которого по очереди будет перебирать каждый пиксель первого столбца, и засовывать в массив 1 или 0, в зависимости от того, закрашен этот пиксель, или нет... Воспользуемся функцией imagecolorat, которая возвращает индекс цвета пикселя.
PHP код:
#int imagecolorat (resource image, int x, int y) 
Этой функции надо передать три значение - ресурс изображения, X и Y координаты.
PHP код:
    for ($j 0$j <= 9$j++)
    {

        if (
imagecolorat($im0$j) != 16777215)
            
$gd[$j] = 1;
        else
            
$gd[$j] = 0;

    } 
Если индекс цвета не равен 16777215, тоесть не белый, записываем в массив $gd единицу, в противном случае - нолик. Итак, у нас образовался массив $gd. Если воспользоваться функцией print_r, которая выводит все ключи и элементы массива, то можно увидеть следующее:
Код:
Array
(
    [0] => 1
    [1] => 1
    [2] => 1
    [3] => 1
    [4] => 1
    [5] => 0
    [6] => 0
    [7] => 1
    [8] => 0
    [9] => 0
)
Нет, это не бинарные числа Это первый столбец по матрице числа 5. А вот и вся она:
Код:
1111111
1100000
1100000
1101110
1110011
0000001
0000001
1100001
0110011
0011110
А теперь выделим единички красным цветом:
Код:
1111111
1100000
1100000
1101110
1110011
0000001
0000001
1100001
0110011
0011110
Так вот, в массиве выше у нас первый столбец этой матрицы, по которому и будем распознавать число. Сразу нарождается вопрос - как именно? Я постараюсь ответить на этот вопрос. Дело в том, что каждый символ имеет пиксели, индекс цвета которых уникален только для него, поэтому его можно легко распознать. Например в тройки закрашен первый и восьмой пиксель, если считать с нуля:

Код:
0 0111110
1 1100011
2 0000001
3 0000011
4 0001110
5 0000011
6 0000001
7 0000001
8 1100011
9 0111110
А в цифры 4 - закрашен пятый и шестой, но не закрашен четвертый.

Код:
0 0000011
1 0000111
2 0001111
3 0011011
4 0110011
5 1100011
6 1111111
7 0000011
8 0000011
9 0000011
Немножко посидев и посмотрев на эти числа в фотошопе, я вывел таблицу в виде массива уникальных индексов цвета и их закраски в цифрах 0-9.
PHP код:
$numbers = array
(
=> array
    (
    
=> 0
    
=> 0
    
=> 0
    
=> 0
    
=> 0
    
), 
=> array
    (
    
=> 0
    
=> 1
    
=> 1
    
), 
=> array
    (
    
=> 1
    
=> 1
    
), 
=> array
    (
    
=> 0
    
=> 1
    
=> 1), 
=> array
    (
    
=> 1
    
=> 1
    
=> 0
    
), 
=> array
    (
    
=> 0
    
=> 0
    
=> 1
    
=> 1
    
), 
=> array
    (
    
=> 1
    
=> 1
    
), 
=> array
    (
    
=> 0
    
=> 0
    
=> 1
    
=> 0
    
=> 1
    
), 
=> array
    (
    
=> 0
    
=> 0
    
=> 1
    
=> 0
    
),
=> array
    (
    
=> 0
    
=> 0
    
=> 1
    
=> 1
    
=> 1
    
=> 0)
); 
Итак, половина работы проделана, остается каждое из этих чисел проверить по первому столбцу изображения, и если все индексы и их закраска в массиве равны индексам в первом ряде символа, то вывести это число.

PHP код:
    foreach ($numbers as $k_num => $number)
    {
        foreach (
$number as $key => $value)
        {
            if (
$gd[$key] == $value)
                
$k++;
        }
        if (
$k == count($number))
        {
            
$cp .= $k_num;
        }
        
$k 0;
    } 
foreach - цикл предназначен специально для перебора массивов. Здесь команды циклически выполняются для каждого элемента массива, при этом очередная пара ключ=>значение оказывается в переменных $ключ и $значение.

В первом цикле перебираются все массивы номеров. Дальше в цикле идет цикл, в котором - если массив $gd с индексом $key равно $value, то переменная $k увеличивается на еденицу. Тобишь если все пары индекс => цвет верны, то $k будет равно текущему числу а если это так, то оно дописывается в переменную $cp.

После всего этого остается вывести переменную с каптчей:
PHP код:
echo $cp
А вот и весь наш код:

PHP код:
<?php

error_reporting
(E_ALL E_NOTICE);

$captcha imagecreatefrompng("php_captcha.png");

$numbers = array(=> array(=> 0=> 0=> 0=> 0=> 0), => array(=> 0=>
    
1=> 1), => array(=> 1=> 1), => array(=> 0=> 1=> 1), => array(=>
    
1=> 1=> 0), => array(=> 0=> 0=> 1=> 1), => array(=> 1=> 1),
    
=> array(=> 0=> 0=> 1=> 0=> 1), => array(=> 0=> 0=> 1=>
    
0), => array(=> 0=> 0=> 1=> 1=> 1=> 0));

for (
$i 0$i <= 4$i++)
{
    
$im imagecreatetruecolor(710);
    
imagecopy($im$captcha00$i13710);

    for (
$j 0$j <= 9$j++)
    {

        if (
imagecolorat($im0$j) != 16777215)
            
$gd[$j] = 1;
        else
            
$gd[$j] = 0;

    }

    foreach (
$numbers as $k_num => $number)
    {
        foreach (
$number as $key => $value)
        {
            if (
$gd[$key] == $value)
                
$k++;
        }
        if (
$k == count($number))
        {
            
$cp .= $k_num;
        }
        
$k 0;
    }
}
echo 
$cp;
?>
Постскриптум

Это моя первая статья по PHP, так что прошу не судить строго Оценивайте, отписывайтесь, критикуйте, спрашивайте Копипаст разрешен только с согласия автора, тоесть меня! Стучите в асю 674542 с просьбой об копировании на свой форум.

Последний раз редактировалось mailbrush; 27.01.2010 в 12:28..
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Books PHP FRAGNATIC PHP, PERL, MySQL, JavaScript 186 21.02.2010 02:41
На PHP, как на "Новые ворота"... Mertvii-Listopad Чужие Статьи 7 18.09.2006 12:42
Безопасность в Php, Часть Iii k00p3r Чужие Статьи 0 11.07.2005 19:02
Защищаем Php. Шаг за шагом. k00p3r Чужие Статьи 0 13.06.2005 11:31



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ