Клуб сео

Черным по белому

Эй! Спасибо, что решили посмотреть на тему! Осмотритесь вокруг
и подпишитесь на RSS, чтобы узнавать обо всех обновлениях. До встречи!

Ломаем (распознаем) каптчу sape.ru


Извините за некрасивое размещение кода пхп. В редакторе он красивый, но после копипаста табы ломаются.

Недавно я подсчитал свои затраты за осень\зиму\весну на распознавание каптчи (у негров антикаптча), и немного прибалдел. В общем, я начал работать в направлении ocr, и в качестве тренировки выбрал sape.ru

Вот такие каптчи (4 шт):

Первое, что нужно сделать – очистить от синего шума (делается это так просто, что саповцы просто решили выпендрится, поместив его на цифры). Красим в белый цвет все пиксели, цвет которых не равняется черному:

$y = 0;
for ($x = 0;$x<70;$x++)
{
$col = imagecolorat($image, $x, $y);
if ($col != 0)
{
imagesetpixel($image,$x,$y,$red);
}
if ($x == 69)
{
$y++;
$x = 0;
}
if ($y == 30)
{
break;
}

}

Вот результат обработки:

Теперь нужно разрезать на 4 цифры, но так, как их границы могут быть не всегда на одном и том же месте, нужно подсчитать во всех столбцах пиксели по вертикали, и в которых наибольшее количество белых пикселей – значит там нету цифры, и можно считать, что это граница. Вот пример кода, для определения одной из границ:

//Считаем количество белого цвета в каждом столбце

$count = ”;
$x = 0;
for ($y=0;$y<30;$y++)
{
$col = imagecolorat($image, $x, $y);
if ($col != 0)
{
$count++;
}
if ($y == 29)
{
$count_stolb[] = $count;
$count = ”;
$y = 0;
$x++;
}
if ($x == 70)
{
break;
}
}
//——————————-

//Определяем границу каждого символа

for ($i=0;$i<count($count_stolb);$i++)
{

if ($count_stolb[$i]>26)
{

$x_start1 = $i;
echo ‘<br>x_start1: ‘.$x_start1.’<br>’;
break;
}

}

for ($i=16;$i<count($count_stolb);$i++)
{

if ($count_stolb[$i]>26)
{

$x_start2 = $i;
echo ‘<br>x_start2: ‘.$x_start2.’<br>’;
break;
}

}

for ($i=25;$i<count($count_stolb);$i++)
{

if ($count_stolb[$i]>26)
{

$x_start3 = $i;
echo ‘<br>x_start3: ‘.$x_start3.’<br>’;
break;
}

}

for ($i=35;$i<count($count_stolb);$i++)
{

if ($count_stolb[$i]>26)
{

$x_start4 = $i;
echo ‘<br>x_start4: ‘.$x_start4.’<br>’;
break;
}

}

//———————————-

Следующий шаг – нарезать 4 картинки, это просто, т.к. у нас есть 4 переменных – начальная позиция Х символов на картинке.

//Нарезаем на цифры

$destImage = imagecreate( 16, 30);
ImageCopyResized( $destImage, $image, 0, 0, $x_start1, 0, 16,30, 15,30 );
ImagePng($destImage,”p01.png”);
$destImage = imagecreate( 16, 30);
ImageCopyResized( $destImage, $image, 0, 0, $x_start2, 0, 16,30, 15,30 );
ImagePng($destImage,”p02.png”);
$destImage = imagecreate( 16, 30);
ImageCopyResized( $destImage, $image, 0, 0, $x_start3, 0, 16,30, 15,30 );
ImagePng($destImage,”p03.png”);
$destImage = imagecreate( 16, 30);
ImageCopyResized( $destImage, $image, 0, 0, $x_start4, 0, 16,30, 15,30 );
ImagePng($destImage,”p04.png”);
//——————-

Вот что у нас выходит:



В этом примере я отказался от использования нейронной сети,  т.к. каптча легкая – решил обойтись простым сравнением каптчи с эталоном. Я подготовил 10 папок от ноля до девяти, в которых лежат по 300 эталонных цыфр каждой папки (300 шт нолей, 300 шт единиц и тд). Далее накладываю распознаваемую картинку на предполагаемый эталон, и считаю количество черных пикселей, которые пересекаются на двух картинках. Итого, на 1 распознаваемую цифру мы проводим 3 тыс. сравнений. На выходе у нас массив: количество совпадений на каждую предполагаемую цифру, какой масив наибольший – такой и результат распознавания.

for ($os=1;$os<5;$os++)
{

$file_captcha = ‘p0′.$os.’.png’;

for ($i=0;$i<10;$i++)
{

$fscan = scandir(‘ocr/’.$i);
//print_r($fscan);
//exit();

foreach ($fscan as $file_etalon)
{
if ($file_etalon == ‘.’)
{
continue;
}if ($file_etalon == ‘..’)
{
continue;
}

$file_etalon = ‘ocr/’.$i.’/’.$file_etalon;

$image_etalon = ImageCreateFromPNG($file_etalon);
$image_captcha = ImageCreateFromPNG($file_captcha);

$count[$i] = 1;
$y = 0;
for ($x=0;$x<16;$x++)
{
$col_captcha = imagecolorat($image_captcha, $x, $y);
$col_etalon = imagecolorat($image_etalon, $x, $y);

if ($col_captcha == 0)
{
if ($col_captcha == $col_etalon)
{
$count[$i]++;
}
}

if ($x == 15)
{
if ($y==29)
{
if ($x == 15)
{
break;
}
}
$y++; $x = 1;
}
}

ImageDestroy($image_etalon);
ImageDestroy($image_captcha);
}
}

$max_c = max($count);
for ($u=0;$u<10;$u++)
{

if ($count[$u] == $max_c)
{
$cifra = $u; break;
}
// print_r($count);
}

//print_r($count);
echo $cifra;

3 тыс сравнений х 4 цифры = 12 тыс сравнений. Время распознавания картинки – 30-40 секунд. Процент распознавания – по 300 образцов\каждый символ = 80%. Легко можно довести до 100%, но для этого надо потратить около 5 баксов – озадачить негров с антикаптчи, пусть они помогут обучить систему. Я же обучил только на пару баксов :)

P.S. Сейчас пытаюсь повторить тоже самое на Visual Basic 2010, только уже с другим ресурсом

UPD: Пример папки с эталонными нолями

Постовой: Вас привлекает туризм, путешествия, отдых? Все турфирмы Владивостока тут

 

Вы можете оставить комментарий, или трекбэк с Вашего сайта.

Комментарии: 1 к “Ломаем (распознаем) каптчу sape.ru”

  1. AWM пишет:

    В сети стало появляться столько статей по распознаванию капч что скоро все под свои нужды будут писать свои распознавалки, я уже с пару месяцев назад написал себе одну. А китайцам слать особо сложные капчи.
    А так статейка очень позновательная. Взял данный принцип на вооружение.

Оставить отзыв

Вы должны войти, чтобы оставить комментарий.