29 июня 2008 в 22:11

Каптча 3d

PHP*
Прочитав топик «RapidShare — новые каптчи», я вспомнил как слушал доклад создателя каптчи на UaВебе.



Зайдя на сайт, желая посмотреть код, я увидел:
Q: Is it opensource?
A: No, sorry. Maybe later.

Я удивился! Мне казалось что любой маломальски образованный хороший программист сделает такую каптчу.
Погуглив и нашел пару интересных линков: 1, 2 и не получил кода, решил написать сам.

:00 С чего начать? Вспоминая времена университета, линейный анализ (ее у меня вел класный препод) и подумав что както нежно сделать с 3D -> 2D, а это как я помню называется «проекция», я набрал это слово в строку поиска
:03 Пройдя по цепочке ссылок в Википедии и прочитав подходящую статью я решил что мне подойдет изометрическая проекция
:05 Ну вот главная формула есть
изометрическая проекция
:15 пару строк кода и вот первая 3D картинка
Piccy.info - Free Image Hosting
:16 два цикла и
Piccy.info - Free Image Hosting
:20 выведу текст и используя его как патерн для z оси получаем
Piccy.info - Free Image Hosting
:30 добавим шума и синусоид получим
Piccy.info - Free Image Hosting

Скорость частота отрисовки 31.42 [#/sec] на Intel Core 2 Duo 2.2 GGz php 5.2.6 Apache 2.2.4 on Win Vista Sp1

/**
*
* @author Andrii Kasian <to.kandy@gmail.com>
*/

<?php 


$capthca 
= new Capthca3d();

$capthca->render();



class 
Capthca3d{


    const 
CHARS 'WEafRTYIPAGHJKXBNM3479j';

    
protected $hypot 8;

    
protected $image null;

    

    
protected $text '';


    

    
public function __construct()

    {

        
$this->time microtime(true);

        
$this->generateCode();


    

    }

    
protected function generateCode()

    {

        
$chars self::CHARS;

        for(
$i =0$i<3$i++){


            
$this->text .= $charsmt_rand(0,22)};

        }

    }

    

    
public function getText()


    {

        return 
$this->text;

    }

    
protected function getProection($x1,$y1,$z1)


    {

        
$x $x1 $this->hypot

        
$y $z1 $this->hypot;


        
$z = -$y1 $this->hypot;

        

        
$xx 0.707106781187

        
$xy 0;


        
$xz = -0.707106781187

        

        
$yx 0.408248290464

        
$yy 0.816496580928


        
$yz 0.408248290464;

        

        
$cx $xx*$x $xy*$y $xz*$z;


        
$cy $yx*$x $yy*$y $yz*$z20 $this->hypot;


        return array(

            
'x' => $cx,

            
'y' => $cy

            
); 

    }

    

    function 
zFunction($x,$y){


        
$z imagecolorat($this->image,$y/2,$x/2)>0?2.6:0;


        if( 
$z != ){

            
$z += mt_rand(0,60)/100;

        }

        
$z += 1.4 sin(($x+$this->startX)*3.141592654/15)*sin(($y+$this->startY)*3.141592654/15);


        return 
$z;

    }

    
public function render()    

    {

        
$xx =30;

         
$yy =60;


        

         
$this->image imageCreateTrueColor($yy $this->hypot  $xx $this->hypot);


        

        
$whiteColor imageColorAllocate($this->image,255,255,255);

        
imageFilledRectangle($this->image,0,0,$yy $this->hypot  $xx $this->hypot,$whiteColor);


        

        
$textColor imageColorAllocate($this->image,0,0,0);

        
imageString($this->image530$this->text$textColor);


        

        

         
$this->startX mt_rand(0,$xx);    

         
$this->startY mt_rand(0,$yy);


        

         
$coordinates = array();

         

        for(
$x 0$x $xx 1$x++){


            for(
$y 0$y $yy 1$y++){

                
$coordinates[$x][$y] = $this->getProection($x,$y,$this->zFunction($x,$y));


             }

         }

         

        for(
$x 0$x $xx$x++){

            for(
$y 0$y $yy$y++){


                 
$coord = array();

                 
$coord[] = $coordinates[$x][$y]['x'];

                 
$coord[] = $coordinates[$x][$y]['y'];


                 

                 
$coord[] = $coordinates[$x+1][$y]['x'];

                 
$coord[] = $coordinates[$x+1][$y]['y'];


                 

                 
$coord[] = $coordinates[$x+1][$y+1]['x'];

                 
$coord[] = $coordinates[$x+1][$y+1]['y'];


                 

                 
$coord[] = $coordinates[$x][$y+1]['x'];

                 
$coord[] = $coordinates[$x][$y+1]['y'];


                

                
$c = (int) ($this->zFunction($x,$y)*32);

                
$linesColor imageColorAllocate($this->image$c$c$c);


                
imageFilledPolygon($this->image$coord4$whiteColor);

                
imagePolygon($this->image$coord4$linesColor);


             }

         }

        

        
$textColor imageColorAllocate($this->image,0,0,0);


        
imageString($this->image530$this->text$whiteColor);


        
imageString($this->image130, (microtime(true)-$this->time), $textColor);


        
header('Content-Type: image/png');

        

        
imagepng($this->image);

        
imagedestroy($this->image);


    }

}





П.С.: GPL
KAndy @KAndy
карма
150,2
рейтинг 0,0
Самое читаемое Разработка

Комментарии (102)

  • НЛО прилетело и опубликовало эту надпись здесь
    • +2
      Шантаж - именно это слово сразу пришло и мне в голову.
    • +7
      > П.С.: желающие получить код могут написать его сами (это очень просто) или добавить мне кармы (что намного сложнее, ее нужно иметь) , при 20+ я его выложу
      >Кармашантаж? Это что-то новенькое.

      отдаю код за +15 кармы ))))
      • 0
        кстати это все на правах рекламы (c)

        ps очень надеюсь тут люди с юмором
      • 0
        А что же делать бедным несчастным людям с кармой < 5 не понимающим смысл этой формулы?
        • 0
          Идти учиться в универ. Это на первом курсе проходят.
          • 0
            Я в данный момент абитуриент =)
            • 0
              обычная матричная алгебра
    • 0
      Вам выбор дали. Пишите сами раз не нравятся условия.
    • +3
      «Шантаж» звучит как-то вульгарно, мне больше нравится «вымогательство» ©
      • +2
        Скорее, кармабазар. Или, "Программирую за карму"
        • 0
          Это цитата, из "Футурамы" :)
  • +14
    Хорошая статья, понравилось. Пожалуй, попробую такую штуковину реализовать на досуге.

    P.S. Пожалуй, без карматоргов Вы бы и так заработали свою двадцатку, а так — сомневаюсь.
  • НЛО прилетело и опубликовало эту надпись здесь
  • НЛО прилетело и опубликовало эту надпись здесь
    • НЛО прилетело и опубликовало эту надпись здесь
      • +3
        Автор написал: "31 штука в секунду".
        • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Автор, будьте добры, поделитесь кодом и будет вам счастье! ;)
  • +5
    Да ладно вам.. что вам кармы жалко для человека?
    Он же не за хухры-мыхру просит.. такая работа достойна поощрения.

    Хотя вымогать действительно некрасиво) - выкладывай давай)
  • –3
    Бессмысленный пост, но автор молодец. Здорово. Жалко, что у меня карма ниже плинтуса, и нечего ставить :)
  • +24
    я бы вам поставил плюс и за топик и в карму(никогда не жалел и с удовольствием поощеряю все новое), вы бы получили свое если бы не вот это:
    код могут написать его сами (это очень просто) или добавить мне кармы (что намного сложнее, ее нужно иметь) , при 20+ я его выложу
    вы получаете здесь информацию безвоздмездно, так почему же ваш пост на других условиях?
    Исходя из этого топику поставил плюс, а вам минус, и даже извиняться не буду — по моему мнению "заслужили".

    PS: http://code.google.com/p/3dcaptcha/downl…

    • –1
      Что плохого в "кармашантаже"?
      Мне видится это зарождением новой тенденции скорее.
      Хотите чтоб за вас реализовали описанное в коде? - Заплатите за это кармой. Все честно.

      ...like in real life.
      • 0
        >>...like in real life.
        если для вас это нормально, то оставайтесь людьми хотя бы тут
        • 0
          парень — умный. и даже если он ошибся (а он поймет, в чем ошибка), то это не дает Вам права его оскорблять.
        • 0
          И всеже считаю это весьма оригинальным вымогательством и потому не понимаю почему попросить кармы за готовое решение не есть хорошо. Странно что вы восприняли чужое мнение как абсолютно неприелимое.
          Прямой "шатнаж" и впрямь выглядит грубо, но суть...
          • 0
            все-все, очень жаль что столь очевидные вещи сказываются на моей карме, поэтому ребятки я в сторону, а мои строчки перечитайте(я никого не оскорблял и не собирался, а лишь говорил о человечности, как автора так и mrtim).
            • 0
              Just4justice: карму вам не снижал.
              "Нет ничего более очевидного чем субъективная реальность" (с) MrTiM;)
    • +1
      К тому же описание же дано бесплатно
  • 0
    хм. ну вот, пару запросов чтото _подобное_ по теме.
    пример
    http://dmtsoft.ru/captcha/dmtCaptcha_v1.2/form.php

    качать с http://dmtsoft.ru/bn/428/as/oneaticleshablon/ "DMT Hard Captcha v1.0"
  • 0
  • НЛО прилетело и опубликовало эту надпись здесь
    • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      накрутите на тор набор и 8-10 символов, обозначив первый например размером, остальные будут читаться по ХЧС, получится неплохая капча
      • +1
        о, а я два года назад рисовал ленту мёбиуса, можно на ней капчу нарисовать ^_^
        openGL к php прикручивается? :)
        • +2
          я не знаю, я ваще дизайнер, мимо проходил просто)
          • НЛО прилетело и опубликовало эту надпись здесь
            • НЛО прилетело и опубликовало эту надпись здесь
              • –1
                кстати я и не говорил, что надо будет вручную рисовать, все легко считается (логику придумать легко, остальное за прогерами)
            • 0
              у вас неправильное представление о дизайнерах)
              • +1
                А у кого оно правильное?
              • НЛО прилетело и опубликовало эту надпись здесь
                • 0
                  всегда думал, что дизайнер - это тот кто делает удобно и эффективно. я ошибался?
    • +1
      Тор, который можно вертеть, поставлялся еще в составе комплекта программ-примеров для Quick Basic четвертой версии ;-)
  • 0
    Еще год назад научились на bigmir.net распознавать такую картинку.
    Так что использовать не советую.
  • 0
    Apatch поправте
  • 0
    Заюзаем:)
  • –6
    автор - убейся
  • 0
    30 запросов формы в секунду и сервер ляжет на отрисовке капчи? Круто.
    • 0
      их можно кэшировать :D, вариации из трех букв быстро закончатся
      • 0
        Неа, не прокатит =) Он добавляет "шума и синусоид".
    • 0
      Ну я как понимаю можно неплохо ускорить скорость отрисовки, например отказавшись от зашумлений по оси z а также предварительно можно нагенерировать сколько угодно капчей
      • 0
        upd: ну и в крайнем случае можно по частям заставить генерировать капчи самих поьзователей ...
      • 0
        зачем отказываться, если можно предрасчитать матрицу шумов эдак на мегапиксель и ее по случайному смещению накладывать.
        • 0
          Но тут же вроде красиво и правильно, и как вижу еще с отсечением заднего плана :)
          В рапиде например смещение по оси z поменьше, и зашумления только сдвигом в 2d
          • +1
            отсечение заднего плана, видимо, делается отрисовкой залитых полигонов на переднем.
      • 0
        Просто необходимо оптимизировать процесс. Имхо, я могу написать капчу, которая с помощью pure-PHP (используя только заполнение точками) будет генерить тоже самое и возможно быстрее, чем у автора :)

        p.s. Оптимизировал когда-то Воксельный ландшафт, который на P-200 шел со скорость 30 fps с разрешением 640x480 ;). Так что, упрощая формулы расчёта и используя средства GD можно добиться очень высокой работоспособности. Тем более средств для этого (в том числе, как вы предлагали, кеширования скринов) существует масса.
        Например, генерить для пользователей капчу раз в 2-3 секунды, либо за каждый написанный пост.
    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Новый веб-сервер под названием "Apatch 2.2.4" улыбнул :)
    • 0
      да-да=)
  • 0
    Хоть и сам могу это написать, но плюсанул,
    в детстве еще за Z80 писал программку для интерактивного вращения шарика самым интересным был вывод всех формул на уровне знанаий 7-го - 8-го класса.
    Ну и также ограничения по памяти и скорости , кажется дошел при вменяемом быстродействии только до сотни.

    ЗЫ:Хотелось бы побольше таких статей на хабре.
    • –2
      ЗЫ: хотелось бы, но без прозьб про карму!
      • +5
        Да ну что вы как дети малые, человек бы и сам получил за эту статью более чем 20 пунктов, а из за одного слова его готовы чуть ли не на костре сжечь, он дал ведь все выкладки теоретические, пусть кто нибуть впихнет код в комментариях если так уж тяжело человеку помочь. Почему перед фактом человек может попросить кармы (темы о кармакредитах етц ...) а постфактум и с плюсовой кармой нет ?
    • +1
      вращать шар — чертовски сложная задача :))
      • 0
        Канечно, когда синусов и косинусов еще не знаеш...
      • 0
        Щас то конечно с улыбкой смотрю на себя тогда, а на тот момент это было типа открытие...
    • 0
      тяжелое детство было +)
  • +1
    Самое сложное в капчах - это подбор параметров, при которых и человеку будет просто распознать, и машине затруднительно. Иногда на это уходит несколько дней, а то и недель
  • +1
    Тянет на приз зрительских симпатий (:
    ЗЫ: Карму плюсанул, но не для выкладывания, а просто из уважения.
  • +1
    Плюс поставил, но демиург уже давно предложил решение без всяких формул для простых умов.
  • +3
    Карму дали, гони капчу пацан.
    >_<
  • +1
    Навеяно комментарием bask'а.

    Мне кажется распознать эту каптчу не очень сложно:
    1) Сетка уже наложена, картинку переносим в 3D.
    2) Символы уже порядочно возвышаются, их можно выделить из основного зашумленного фона
    3) Дальше уравниваем поверхность и избавляемся от глубины (оси Z)
    4) На этом этапе у нас банальная плоская картинка с символами, которые не составит труда распознать =)
    p.s. Не претендую на самый оптимальный алгоритм, просто этот мне кажется наиболее интересным =)


    А можно и вовсе с помощью поворота и растягивания каптчи получить что то подобное:
    http://img204.imageshack.us/img204/989/capkh4.jpg
    Здесь видно что поверхность букв более темная чем фон, фильтруем, и снова получаем плоскую картинку с символами.
    • 0
      а давай ка на вот этом ?)
      http://i.piccy.kiev.ua/i2/55/b1/5f5bbef6…
      • 0
        Чесно говоря, тут всё точно также :)
        • 0
          результат в студию :)
          • 0
            Кажется, на Хабре назревает война Капчеписателей и Капчеломателей :)
            • 0
              я есличе к ломателям отношусь %)
              • 0
                Умы бродят в поисках применения избыточным вычислительным мощностям ))
                • 0
                  Не, у меня есть другое применение для них ;)
              • 0
                А я ни к тем, ни к другим, так что моё мнение можно пропустить.
                Писать распознаватель я не буду, но вот что скажу: даже на глаз видно, что на этой картинке, если усреднить, на месте линий букв будет больше интенсивность. Можно пройтись дифференциальным фильтром и будет вполне хороший силуэт, по крайнем мере он должен распознаться, учитывая что сейчас распознают такое:

                , имхо здесь будет очень похожее изображение.
  • +1
    protected function generateCode()
    предлагаю изменить следующим образом:
        protected function generateCode()
    {
    $chars = self::CHARS;
    $cnt = count($chars) - 1;
    for($i =0; $i<3; $i++){
    $this->text .= $chars[mt_rand(0,$cnt)];
    }
    }
  • 0
    пару строк кода и вот первая 3D картинку
  • +1
    А вообще, если разобраться, нужна ли такая капча? Зачем всё усложнять?

    Намучился на рапиде сначала с "кооошечками"... (пока воткнул, в чем фишка - думал свихнусь).. Теперь еще и 3Д...
  • 0
    неплохой код, в целом)
    (модифицировал под php4)
  • –2
    Правильно-правильно: не напомнишь - кто ж плюсанёт?
  • +1
    КлаССный.
  • +1
    Сколько времени потратил?
  • 0
    интересно, все скопировали название класса как Capthca3d?
  • 0
    автор дьявол:)))
  • –2

    $z += 1.4 * sin(($x+$this->startX)*3.141592654/15)*sin(($y+$this->startY)*3.141592654/15);

    не проще ли так:

    $z += 1.4 * sin(($x+$this->startX)*M_PI/15)*sin(($y+$this->startY)*M_PI/15);
    • +1
      а обязательно вылизыванием кода в комментах заниматься, человек преподнес основную идею, дал исходный код для полета вашей мысли, а тут еще в таких мелочах зад..чивают, впрочем, как всегда...
  • 0
    Просто класс
  • 0
    Возможно один из самых крутых постов в этом блоге
  • +2
    Blur + Gamma Correction и капча вполне распонаваема

    habr

  • 0
    Не хочу тебя расстраивать, но где-то я подобную капчу видел.
  • –2
    GPL - не зачетно, самая идиотская лицензия.
    Если хочешь добра людям, надо выкладывать под LGPL.
  • 0
    а в чем необходимость
    $c = (int) ($this->zFunction($x,$y)*32);
    этой строки для задания цвета?
    убрав её и заменив следующую на:
    $linesColor = imageColorAllocate($this->image, 0, 0, 0);
    быстродействие увеличилось почти в два раза, судя по микротайму.

    А вообще, большое спасибо :)
  • 0
    Автору - пламенный капчапривет!
  • 0
    10x!
  • 0
    вообще то тема стара...

    вот еще от 2006-02-06 http://demiurg.livejournal.com/70914.htm…

    исходники http://maxx.e-taller.net/lj/captcha-php.…
  • 0
    Спасибо!
  • 0
    опечатка в имени класса
    Capthca3d а должно быть Captcha3d

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