Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
 |
|
Распознавание каптчи (PHP + GD) |

27.01.2010, 12:18
|
|
Познавший АНТИЧАТ
Регистрация: 24.06.2008
Сообщений: 1,996
Провел на форуме: 6075534
Репутация:
2731
|
|
Распознавание каптчи (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(7, 10);
Теперь надо скопировать туда символ каптчи. Воспользуемся функцией 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, $captcha, 0, 0, 9 * $i, 13, 7, 10);
Это значит, что мы часть изображения $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($im, 0, $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
(
1 => array
(
0 => 0,
1 => 0,
2 => 0,
3 => 0,
5 => 0
),
2 => array
(
0 => 0,
2 => 1,
9 => 1
),
3 => array
(
1 => 1,
8 => 1
),
4 => array
(
4 => 0,
5 => 1,
6 => 1),
5 => array
(
0 => 1,
1 => 1,
5 => 0
),
6 => array
(
0 => 0,
1 => 0,
4 => 1,
7 => 1
),
7 => array
(
0 => 1,
9 => 1
),
8 => array
(
0 => 0,
1 => 0,
2 => 1,
4 => 0,
6 => 1
),
9 => array
(
0 => 0,
1 => 0,
3 => 1,
5 => 0
),
0 => array
(
0 => 0,
2 => 0,
3 => 1,
4 => 1,
5 => 1,
7 => 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 код:
<?php
error_reporting(E_ALL ^ E_NOTICE);
$captcha = imagecreatefrompng("php_captcha.png");
$numbers = array(1 => array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 5 => 0), 2 => array(0 => 0, 2 =>
1, 9 => 1), 3 => array(1 => 1, 8 => 1), 4 => array(4 => 0, 5 => 1, 6 => 1), 5 => array(0 =>
1, 1 => 1, 5 => 0), 6 => array(0 => 0, 1 => 0, 4 => 1, 7 => 1), 7 => array(0 => 1, 9 => 1),
8 => array(0 => 0, 1 => 0, 2 => 1, 4 => 0, 6 => 1), 9 => array(0 => 0, 1 => 0, 3 => 1, 5 =>
0), 0 => array(0 => 0, 2 => 0, 3 => 1, 4 => 1, 5 => 1, 7 => 0));
for ($i = 0; $i <= 4; $i++)
{
$im = imagecreatetruecolor(7, 10);
imagecopy($im, $captcha, 0, 0, 9 * $i, 13, 7, 10);
for ($j = 0; $j <= 9; $j++)
{
if (imagecolorat($im, 0, $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..
|
|
|

27.01.2010, 17:44
|
|
Постоянный
Регистрация: 11.10.2007
Сообщений: 406
Провел на форуме: 7215020
Репутация:
1423
|
|
С тех пор, как появились “сервисы” anti-captcha.com и ей подобные я думал, что все забросят это дело и начнут повсеместно использовать быдлотруд ишачащих там школьников ( что в принципе и случилось ). Не может не радовать тот факт, что есть люди, которые продолжают работать в направлении автоматического распознавания капчи. mailbrush, большой плюс.
Сообщение от mailbrush
Долго я искал статьи, подобные этой, но не нашёл. И мне в голову пришла идея, которую мне получилось успешно реализовать. Именно ею я и хочу поделиться с вами!
Их на античате было как минимум 3 (если не поудаляли). И все посвящены распознаванию элементарных капчей. Кроме того кое-какие материалы по этой теме можно найти на хабре.
То, что нашел сходу
http://forum.antichat.net/showthread.php?p=1131976
Так же рекомендую ознакомиться с этим
https://docs.google.com/fileview?id=0B-xpafMYi--7M2U4OGY3MWEtYzNjYi00OTkyLTg0ZDYtZjQzZTVkMmJhYWEz& hl=ru
Эх было б здорово чтобы какой-нибудь кодер реализовал приведенные там методы и алгоритмы =)
|
|
|

27.01.2010, 20:05
|
|
Познавший АНТИЧАТ
Регистрация: 24.06.2008
Сообщений: 1,996
Провел на форуме: 6075534
Репутация:
2731
|
|
Сообщение от ElteRUS
Их на античате было как минимум 3 (если не поудаляли). И все посвящены распознаванию элементарных капчей. Кроме того кое-какие материалы по этой теме можно найти на хабре.
То, что нашел сходу
http://forum.antichat.net/showthread.php?p=1131976
Возможно, были готовые скрипты, пускай даже с комментами, просто у меня руки кривые, и не нашёл
Сообщение от ElteRUS
Так же рекомендую ознакомиться с этим
https://docs.google.com/fileview?id=0B-xpafMYi--7M2U4OGY3MWEtYzNjYi00OTkyLTg0ZDYtZjQzZTVkMmJhYWEz& hl=ru
Эх было б здорово чтобы какой-нибудь кодер реализовал приведенные там методы и алгоритмы =)
Хех, завтра почитаю, а то текста много 
Последний раз редактировалось mailbrush; 27.01.2010 в 20:33..
|
|
|

27.01.2010, 20:44
|
|
Динозавр
Регистрация: 10.01.2008
Сообщений: 2,841
Провел на форуме: 9220514
Репутация:
3338
|
|
Очень даже прикольно, зачетная статья, риспект. Осталось добавить только немного AI для распознавания чуть других капч, не таких именно. Но все равно классно
|
|
|

27.01.2010, 20:57
|
|
Познающий
Регистрация: 08.06.2009
Сообщений: 89
Провел на форуме: 469214
Репутация:
26
|
|
https://forum.antichat.ru/threadnav62896-1-10.html
ыот тоже про капчи. имхо беспонтовая статья. именно из за простоты. надоели однообразные. в тысячу раз интереснее почитать как на php распознать капчу e-gold'a или еще какие сложные..а тут ниче интересного
|
|
|

28.01.2010, 01:52
|
|
Он хакер.
Регистрация: 01.11.2008
Сообщений: 1,756
Провел на форуме: 6462214
Репутация:
3171
|
|
Что бы распознать сложную каптчу,даже без мусора,просто с помехами, нужно очень много ресурсов и времени.
Пока что я смог собрать небольшую базу символов,только в 18к символов,то есть - обучил своего дешифровщика распознавать 18к сиволов в такой каптче.Пока что результат неплохой,в среднем 3 варианта на 1 каптчу,где1 в всегда верный.Но мучений конечно слишком много,непонятно как делить на символы,приходиться тпо руками обучать 
Простой перевод картинки в байтовое представление.
Вот тута
Пока что на основе этого,могу распознать каптчу от дле как я говорил,с 33% удачи.Давно этим не занимался =)
То есть, я смог полностью очистить каптчу от ненужных мне вещей,и оставить только буквы.Можно обучить построчно искать буквы,можно по рядам.
Последний раз редактировалось m0Hze; 28.01.2010 в 01:55..
|
|
|

28.01.2010, 17:09
|
|
Он хакер.
Регистрация: 01.11.2008
Сообщений: 1,756
Провел на форуме: 6462214
Репутация:
3171
|
|
Сообщение от m0Hze
Что бы распознать сложную каптчу,даже без мусора,просто с помехами, нужно очень много ресурсов и времени.
Пока что я смог собрать небольшую базу символов,только в 18к символов,то есть - обучил своего дешифровщика распознавать 18к сиволов в такой каптче.Пока что результат неплохой,в среднем 3 варианта на 1 каптчу,где1 в всегда верный.Но мучений конечно слишком много,непонятно как делить на символы,приходиться тпо руками обучать 
Простой перевод картинки в байтовое представление.
Вот тута
Пока что на основе этого,могу распознать каптчу от дле как я говорил,с 33% удачи.Давно этим не занимался =)
То есть, я смог полностью очистить каптчу от ненужных мне вещей,и оставить только буквы.Можно обучить построчно искать буквы,можно по рядам.
Стоит сказать,что проще всего распознать такие символы как 5,0\о,l,1.так как они ну хоть как,но всегда идут по одному алгоритму,например петелька + палочка,просто "побайтово" считываем изображение,и например регулярками построчно проходим по единицам.Ну а далее сравниваем с уже обученым ботом,на наличие сходства +\-10 "байтов" в стороны, на счет искожения.
|
|
|

28.01.2010, 17:16
|
|
Он хакер.
Регистрация: 01.11.2008
Сообщений: 1,756
Провел на форуме: 6462214
Репутация:
3171
|
|
+еще 5 копеек от себя,так как, какое то время пытался распознать искаженные каптчи(только в одну сторону).
Есть алгоритм,в приведенной выше ссылки на пдф он есть,так вот он работат по методу слоев.В докладе выше есть подробное описание.Слой сниметься за слоем.Так вот, php предоставляет простое средство для такое реализации.это фильтры,достаточно перевести изображение в черно-белый режим,далее применить фильтр "яркость",и далее эксперементировать с четкостью.Я подобрал оптимальный параметр для своей каптчи -150.В таком режиме,буквы максимально тонкие,если гнуть и дальше,можно добиться тонкости букв в 1px, что очень существенно упрощает декрипт "байтов" => symbols => Каптча.
После того как мы получили максимально тонкие буквы с помощью фильтров,было бы хорошо заюзать алгоритм "углы",я хз как его назвать.В докладе выше он тоже есть.По принципу "углов" убираеться что,что не соответствует приведенным там шаблонам,читайте там,тут описывать долго.В идеале,если буквы искажены не очень сильно - получаем почти чистые быквы.конечно у них не будет хватать некоторых углов,искаженны,их отрежет фильт,но то только упрощает задачу.Далее,все отрезанные углы(они запоминаються в виде 2-х мерных матриц),заполняються линиями,прямыми,от X-px до Y-px, после этого у нас готовые буквы,прямые и ровные,но всегда разного размера.
|
|
|

28.01.2010, 17:38
|
|
Он хакер.
Регистрация: 01.11.2008
Сообщений: 1,756
Провел на форуме: 6462214
Репутация:
3171
|
|

Вот такая не очень сложная в плане помех каптча.Что бы получить максимаьно тонкие символы, в 0-1 представлении,как у mailbrush, можно использовать такой скрипт.Эффекты подбирались руками,и последний эффект(колоризация),нужна для того,что бы плохо прорисованные пиксели темного цвета,после "черно-белого" фильтра,стали другого цвета,таким образом мы еще утоньшаем наши буквы.А вот и скрипт "за 5 минут на каленке", поставил на хост его,заменив старый,тут буквы чотче
PHP код:
<?php
/**
* @author m0hze
* @copyright 2010
*/
$img = imagecreatefromstring(file_get_contents('http://www.captcha.ru/captcha/'));
imagefilter($img, IMG_FILTER_GRAYSCALE);
imagefilter($img, IMG_FILTER_CONTRAST, -500);
imagefilter($img,IMG_FILTER_COLORIZE,54,4,5);
$image_p = ImageCreate(120, 50);
imagecopyresampled($image_p, $img, 0, 0, 0, 0, 120, 50, 120, 50);
imagedestroy($img);
$im = imagecreatetruecolor(120, 50);
imagecopy($im, $image_p, 0, 0, 0, 0, 120, 50);
imagedestroy($image_p);
for ($i = 0; $i <= 50; $i++) {
for ($j = 0; $j <= 120; $j++) {
if(imagecolorat($im, $j, $i) != 16777215){
$return .= '1';
}else{
$return .= '0';
}
}
$return .= '<br>';
}
echo $return;
imagedestroy($im);
?>
|
|
|

15.02.2010, 23:49
|
|
Новичок
Регистрация: 14.05.2009
Сообщений: 12
Провел на форуме: 64945
Репутация:
0
|
|
1 => array
(
0 => 0,
1 => 0,
2 => 0,
3 => 0,
5 => 0
),
Вот так мы определяем координаты по Y значению, то есть по цифрам справо, а как сделать что бы можно было и по x значению определить?
|
|
|
|
 |
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|