PHP

Распознавание капчи php

Здравствуйте, уважаемые читатели, в данном посте я хочу показать как может выглядеть скрипт Pраспознавание капчи php.

Все мы привыкли ежедневно видеть, на самых разнообразных ресурсах интернета, картинки, надписи на которых нас просят вписать в специальное поле формы, перед каким либо действием, к примеру, перед скачиванием файлов или отправкой сообщений. Такие картинки называются капчами, подробнее о происхождении этого термина можно прочесть в моей статье "Капча на PHP".

И ведь действительно без капчи теперь не обходится ни один из более-менее полезных сайтов. Связано это с тем, что с ростом технологического процесса и развитием ресурсов, становится все больше роботов гуляющих по интернету и вредящих безбрежному благополучию ресурсов, не имеющих защиты от ботов.
Капча как раз таки является одним из средств защиты от роботов, а как следствие и от спама. Все дело в том, что для человека распознать капчу является не трудоемким процессом, а для спам бота оно может стать невыполнимым.

Но нет таких способов защиты, на которые нельзя найти способы взлома, вопрос лишь во времени и средствах. Другими словами, выяснить, что же написано на картинке – можно программно, и я хочу показать, как может происходить распознавание капчи php скриптом.

Как действовать при распознавании капчи

На сегодняшний день существует множество сложных способов распознавания капчи на php и на любых других языках, но чтобы их понять стоит начать с малого, а именно с написания скрипта распознающего примитивную капчу.

Под примитивной капчей понимается картинка с монотонным фоном, на которой изображено трехзначное число. Число всегда выводится в одном шрифте и не имеет коэффициента искажения.

Пример примитивной капчи:



Перед тем как приступить к обдумыванию алгоритмов, и начинать изучать природу нейронных сетей, проанализируем имеющуюся примитивную капчу.

Как видите можно выделить ряд условий формирования этой картинки:

Шрифт всегда одинаковый.
Высота цифр одинаковая.
Между цифрами существует пустота минимум в 2 px.
Алгоритм распознавания такой капчи не требует знаний о нейронных сетях и может выглядеть так:

Разбить все цифры меду собой.
Составить ассоциативный массив с количеством пикселей для каждой цифры.
Посчитать для каждой цифры из капчи, из какого количества пикселей она состоит а именно сколько содержит пикселей отличных от цвета фона.
Получить цифру из массива соответствий.
Распознавание цифр с картинки по шагам.

Переводим картинку в бинарную матрицу (1 шаг)



Вычисляем интервалы содержащие цифры (2 шаг )
Складываем построчно все столбцы, получаем строку:

Вычисление интервалов

По полученной строке можно вычислить интервалы, задающие положение цифр.



Теперь мы знаем, что столбцы матрицы с индексами в интервалах [1,15], [18,32], [35,49] содержат цифры.

Вычисляем количество пикселей для каждой цифры (шаг 3)

Складываем все единицы в найденных интервалах, получаем:

[1,15] = 215 единиц;
[18,32] = 213 единиц;
[35,49] = 184 единиц.

Подсчет количества пикселей для всех возможных цифр (шаг 4)

Скачиваем несколько вариаций капчи, которые содержат все цифры от 0 до 9.

Затем необходимо вычислить количество пикселей для каждой из цифр [1234567890].

Например, подсчитав пиксели в цифре восемь – получим 215 шт.



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



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



В результате у меня получился скрипт который с 100% вероятностью распознает числа на картинках данной капчи:



Набор картинок и сам код скрипта для распознавания капчи php лежит в архиве который можно скачать по следующей ссылке.

<?php
  
// пробуем распознать картинку 1.png
$encrypt = new crackCapcha('1.png'); 
echo "<br><span style='font-size: 25px;'>Resolve: ".$encrypt->resolve."</span><br><br>";

class crackCapcha {

  public $im;
  public $binaryMartix;
  public $assocNumber = array(
    '200' => 0,
    '86' => 1,
    '156' => 2,
    '180' => 3,
    '147' => 4,
    '184' => 5,
    '213' => 6,
    '118' => 7,
    '215' => 8,
    '209' => 9,
  );
  public $resolve;


  function __construct($path) {
    $this->im = @imagecreatefrompng($path);

    if (!$this->im){ 
      return false;
    }
    
    $this->binaryMartix =  $this->imageToMatrix($this->im, true);   
    $explode =  $this->explodeMatrix($this->binaryMartix);
    $this->resolve = '';
    foreach ($explode as $number) {
       $this->resolve .= $this->assocNumber[$number];
    } 
  }


  function explodeMatrix($binaryMartix) {
    $temp = array();

    // сложение столбцов для выявления интервалов
    for ($i = 0; $i < count($binaryMartix); $i++) {
      $sum = 0;
      for ($j = 0; $j < count($binaryMartix[0]); $j++) {
        $sum += $binaryMartix[$i][$j];
      }
      $temp[] = $sum ? 1 : 0;
    }

    // вычисление интервалов по полученной строке
    $start = false;
    $countPart = 0;
    $arrayInterval = array();
    foreach ($temp as $k => $v) {

      if ($v == 1 && !$start) {
        $arrayInterval[$countPart]['start'] = $k;
        $start = true;
      }

      if ($v == 0 && $start) {
        $arrayInterval[$countPart]['end'] = $k - 1;
        $start = false;
        $countPart++;
      }
    }

    // сложение всех единиц в полученных интервалах столбцов
    foreach ($arrayInterval as $interval) {
      $sum = 0;
      for ($i = 0; $i < count($binaryMartix); $i++) {
        for ($j = 0; $j < count($binaryMartix[0]); $j++) {
          if ($i >= $interval['start'] && $i <= $interval['end']) {
            $sum += $binaryMartix[$i][$j];
          }
        }
      }
      $result[] = $sum;
    }

    return $result;
  }

  /**
   * Конвертация рисунка в бинарную матрицу
   * Все пиксели отличные от фона получают значение 1
   * @param imagecreatefrompng $im - картинка в формате PNG
   * @param bool $rotate - горизонтальная или вертикальная матрица 
   */
  function imageToMatrix($im, $rotate = false) {
    $height = imagesy($im);
    $width = imagesx($im);

    if ($rotate) {
      $height = imagesx($im);
      $width = imagesy($im);
    }

    $background = 0;
    for ($i = 0; $i < $height; $i++)
      for ($j = 0; $j < $width; $j++) {

        if ($rotate) {
          $rgb = imagecolorat($im, $i, $j);
        } else {
          $rgb = imagecolorat($im, $j, $i);
        }

        //получаем индексы цвета RGB 
        list($r, $g, $b) = array_values(imageColorsForIndex($im, $rgb));

        //вычисляем индекс красного, для фона изображения
        if ($i == 0 && $j == 0) {
          $background = $r;
        }

        // если цвет пикселя не равен фоновому заполняем матрицу единицей
        $binary[$i][$j] = ($r == $background) ? 0 : 1;
      }
    return $binary;
  }

  /**
   * Выводит матрицу на экран
   * @param type $binaryMartix
   */
  function printMatrix($binaryMartix) {
    for ($i = 0; $i < count($binaryMartix); $i++) {
      echo "<br/>";
      for ($j = 0; $j < count($binaryMartix[0]); $j++) {
        echo $binaryMartix[$i][$j]." ";
      }
    }
  }

}

Теги:
Распознавание, капча
Добавлено: 25 Сентября 2013 09:19:05 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...