Author Topic: Разбираемся с одним из видов капчи  (Read 4792 times)

0 Members and 1 Guest are viewing this topic.

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Разбираемся с одним из видов капчи
« on: February 04, 2015, 06:28:59 PM »
Такой себе Making of
Спросили тут у меня совета в победе над капчей...

Даже не в написании скрипта, а возможно ли в принципе решение с помощью Clickermann. Сначала думал случай с обычной капчей и совет был естесственный - Antigate.
Но капча, по описанию, в картинках. Есть 5 картинок. 2 из них одного предмета. Кликнуть нужно по одному из пары.
Капча на одном из сайтов заработка. Требует ответа при каждом действии и в силу других причин платный вариант от китайцев не подходит, если вообще возможен.
Тему не обсуждал на выкладывание, но думаю особого секрета здесь нет. Сайт не русский. d i g a d z . c o m

Присланный образец:


Появилось несколько задумок в вариантах решения. По анализу ещё 4 дополнительных скриншотов

Анализ задачи
удалось выявить следующие проблемы:
  • Фон не однородный, с рисунком. Иногда сдвигается на пиксел туда-сюда. В принципе легко убирается колормодом.
  • Расположение картинок "гуляет". Ни от центра, ни от края... варианты не предсказуемы.
  • Иногда поля картинок перекрываются, см. вариант с сатурном на последнем скрине.
  • Масштаб картинок меняется, вследствии чего...
  • Меняются практически все цвета и их относительное положение.

    и такие различия сильные вплоть до колормода 7

В принципе, разный цвет из-за сглаживания при пересчёте тоже решается колормодом, но Победить этим изменение масштаба нельзя.
Образец в COLORMODE(7)



Поиск путей решения
Первый шаг это вычленить и разделить поля под картинки для последующего их сравнения, поборов "плавание" зависящее от масштаба каждой. Наложив слоями в фотошопе и проанализировав решил пока действовать приближенно.
Почти всегда подходило разделение по 62 пикс в ширину в постоянном месте.
Привязавшись ко всему полю капчи по надписи через COLORMODE( 8 ) разделил на равные участки примерно подходящие для всех слоёв-образцов

Некоторое залезаниние на соседние участки оставил на потом, может и не понадобится.

Как же побороть главный недуг, масштаб? Посовещавшись уже было решено, что выхода нет и я предложил заготовить все размеры масштаба для каждой картинки, благо их не много пределы изменения масштаба конечны. Всё это, правда очень трудоёмко и затратно. Нужно отлавливать все варианты, накладывать, сравнивать, сортировать. Некоторый варианты возможно придётся ждать долго. Человек предложил не отлавливать, а сделать образцы в фотошопе, меняя масштаб и сохраняя варианты от самого большего, до наименьшего.
Боюсь это бы не прошло, т.к. у нас нет оригинала и не знаем применённый метод сглаживания. Все эти образцы не имели бы ничего общего с используемыми в капче.
Оставался отлов, крайний случай. Как говорится, если ничего не поможет.

Проба подсчёта цветов
Пришла идея сделать подсчёт количества пикселов по цветам. Благо их количество мы уменьшили до восьми.
И проанализировать закономерности. Понятно что точных и даже очень близких значений не будет. Но закономерность ожидалась.
При изменении масштаба количество пикселов каждого цвета должно пропорционально изменяться в ту или другую сторону. Могут быть и исключения, маленький участок другого цвета мог и вовсе исчезнуть либо трансформироваться в соседний цвет.

На этом этапе была запилена часть скрипта включающая привязку, разделение на зоны и подсчёт количества каждого из 7 цветов для каждой картинки в один псевдо двумерный массив. И вывод лога по результатам.
Почему цветов стало 7, а не 8? Чёрный я решил исключить из анализа, nn/r/ в него превращался фон. И смесь фон+наличие в картинке получалась очень случайная величина не поддающаяся анализу. Она только вредит.
Остались 7 основных цветов

Code: [Select]
16777215,8388607,8355839,8388479,16777087,16744319
Хм... Даже 6. Один я про..ал и только сейчас заметил  :) :) ;D Маженту.
Короче шесть.

Результат прогона подсчёта для 4 образцов:

Ряды - картинки слева на право. Колонки - количество пикселов по цветам.


Человеку определить подобные картинки анализируя результат не трудно, значит и скрипт попробуем научить.

Выбор методов сравнения

Бежать надо. Завтра допишу...


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Разбираемся с одним из видов капчи
« Reply #1 on: February 04, 2015, 11:02:46 PM »
С телефона дописывать не буду. Завтра с компа добью. Но забегая вперед хочу сказать что Золотой первыми двумя пунктами полностью повторил мои действия. Этих мер плюс более точное деление на лету и хватило для решения.
Это не ты со мной переписывался с фейка?

Если бы это не дало приемлимых результатов, в планах был анализ взаимоположения групп цветов. Либо краёв, либо средних значений.
А учет фона был моей первой мыслью. Но я решил что она несостоятельна. И пока так думаю.
« Last Edit: February 04, 2015, 11:11:04 PM by Vint »


dramster

  • Герой форума
  • *****
  • Posts: 1134
    • View Profile
Re: Разбираемся с одним из видов капчи
« Reply #2 on: February 05, 2015, 02:43:17 AM »
посидел я поковырялся с данными циферками, написал скрип по разнице в соотношени цветов между картинками. тоесть например  - красный цвет первой картинки деленый на красный второй, должен быть примерно равен желтому первой деленому на желтый второй..... както так. плюс определить какая из них больше, чтоб знать что на что делить.
вписал ранее определенные Vint'ом цифры первой капчи.

Code: (clickermann) [Select]
$cols1= "85,262,272,1,213,57"
$cols2= "695,9,15,0,17,19"
$cols3="693,157,72,50,101,68"
$cols4="329,363,81,2,405,40"
$cols5="375,404,93,0,459,47"


SUB(capcha,$cap1, $cap2 )
   
   
   STRSEPARATE($cap1, ",", $arr1)
   STRSEPARATE($cap2, ",", $arr2)
   $am_arr1 = 0
   $am_arr2 = 0
   FOR($i=0,$i<ARRSIZE ($arr1))
      $am_arr1=$arr1[$i]+$am_arr1
   END_CYC
   FOR($i=0,$i<ARRSIZE ($arr2))
      $am_arr2=$arr2[$i]+$am_arr2
   END_CYC
   
   IF($am_arr1 > $am_arr2)     
      FOR($i=0,$i < ARRSIZE ($arr1))
         IF(($arr1[$i]!0)&($arr2[$i]!0))
            arrpush($rat, $arr1[$i]/$arr2[$i])
         END_IF
      END_CYC
     
   else
     
      FOR($i=0,$i < ARRSIZE ($arr1))
         IF(($arr1[$i]!0)&($arr2[$i]!0))
            arrpush($rat, $arr2[$i]/$arr1[$i])
         END_IF
      END_CYC           
   END_IF
   
   $min=$rat[0]
   FOR($a=1,$a<ARRSIZE($rat))
      IF($min>$rat[$a])
         $min=$rat[$a]
      END_IF
   END_CYC
   
   $max=$rat[0]
   FOR($a=1,$a<ARRSIZE($rat))
      IF($max<$rat[$a])
         $max=$rat[$a]
      END_IF
   END_CYC
   
   $coin= $max-$min
   
   UNDEFINE ($arr1)
   UNDEFINE ($arr2)
   UNDEFINE ($rat)
   
END_SUB

/////////////////////////////////////////////////////

capcha ($cols1,$cols2)
print($coin)

capcha ($cols1,$cols3)
print($coin)

capcha ($cols1,$cols4)
print($coin)

capcha ($cols1,$cols5)
print($coin)

capcha ($cols2,$cols3)
print($coin)

capcha ($cols2,$cols4)
print($coin)

capcha ($cols2,$cols5)
print($coin)

capcha ($cols3,$cols4)
print($coin)

capcha ($cols3,$cols5)
print($coin)

capcha ($cols4,$cols5)
print($coin)

halt
до конца уже недописывал, сравнение результатов, итак всё ясно.
в ответ получил
Code: [Select]
28.9888089528377
 49.7352941176471
 3.572794117647
 4.0698529411764
 16.4473221422861
 39.8599520383693
 44.3493205435652
 3.969900990099
 4.00342891432
 0.0620523415978
что показывает, что в последнем вызове подпрограммы картинки совпадают больше всего. а последний вызов, это сравнение двух последних. все правильно.

отличный результат показали третья
Code: [Select]
1.6741361379825
140.847924773022
80.2214656290532
71.7292477302205
9.8236406619386
6.0788790866632
6.0496296645752
13.7447552447553
19.0015560165975
0.368006993007

и четвертая капча
Code: [Select]
4.1803278688525
4.0833333333333
2.7853993140617
4.2468924518105
16.2364864864865
7.1978319783198
0.8187173354593
3.0057692307692
15.0373626373626
6.3848555815769

а вот с вторым набором цифер никак, определяет что вторая и третья больше всего совпадают.

а всё почему? потомучто в ней нужные картинки больше всего несовпадают по размеру.

всеже нужно учитывать все 8 цветов с предварительным определением сканируемой облости. тоесть нужно определить в начале верхние границы картинки, нижние, слева и справа. после чего посчитать в этой облости все 8 цветов(включая и черный). после чего сравнивать их с остальными (чем я бы с интересом занялся, но пора спать :( ).

« Last Edit: February 05, 2015, 04:00:11 AM by dramster »

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Разбираемся с одним из видов капчи
« Reply #3 on: February 05, 2015, 12:54:19 PM »
продолжу... хотя уже и так всё ясно.

Выбор методов сравнения

Да решил находить пары с однонаправленным изменением цвета. Проанализировав данные одинаковых картинок стало понятно, что один цвет может изменяться в другом направлении. Счёл это допустимым.
Сначала хотелось сделать попроще, сравниваем числа первого объекта с числами второго. Если значение цвета больше присваиваем этому цвету +1, меньше -1
Code: [Select]
329   363   81   2   405   40
375   404   93   0   459   47

+1    +1   +1   -1   +1   +1

Потом складываем результат и берём по модулю
Code: [Select]
+1+1+1-1+1+1 = |4| = 4Если в результате получаем 4 или 5 или 6, значит разнонаправленных не больше 1.
Если 2 или 3 - больше и картинки не совпадают.

Это был самый предварительный этап. Просмотрев тщательней, стало понятно что иногда разнонаправленных два из-за малых и близких значений в одном из них (те же 2 и 0). Решил ввести допуск или мёртвую зону для очень похожих значений и независимо от направленности изменений в этой паре засчитывать её как подходящую.
Так же было решено ограничить различие по величине даже однонаправленных значений. Если , например, большинство пар идёт на увеличение, а одно из значений меняется сильно (было 50 стало 480 или 700) то признавать пару цветов как негодную. Задавать разницу в процентах отсчитывая от большего значения.
И мёртвую зону $mz и процент различия $proc вынес в настройки скрипта для дальнейшего подбора и уточнения.
Сразу выбрал их ориентируясь на 5 капч в размере
$mz = 10 // пикселов
$proc = 40  // процентов, не более

Проходимся по 6 парам и чтобы не проходить 2 и 3 раза, сразу сравнивая присваиваем паре статус
Code: [Select]
   $true = ...  значения близкие, в пределах мёртвой зоны $mz
   $false = ... значения отличающиеся более чем на $proc процентов
   $plus = ...  значения увеличиваются
   $minus = ...  значения уменьшаются

По ходу проверяем, если $false достигло больше 1 или $true больше 4 прерываем чтобы не тратить время и возвращаем результат "НЕ похожи" и "похожи" соответственно.
После прохода, смотрим каких больше плюсов ($plus)  или минусов ($minus) большее значение превращаем в $true, меньшее в $false. Напомню, для признания картинок одинаковыми $false не должно быть больше 1 (одного).

Code: [Select]
329      363      81     2     405     40
375      404      93     0     459     47
$plus  $plus   $plus  $true  $plus  $plus

$true  $true  $true  $true  $true  $true

Подпрограмма сравнения пары картинок

Code: (clickermann) [Select]
SUB(para, $n1, $n2) //==========================================================
   $true = 0
   $false = 0
   $plus = 0
   $minus = 0
   FOR($i=0, $i<6)
      $e1 = $data[$n1*6+$i]
      $e2 = $data[$n2*6+$i]
      $d = $e1 - $e2
      IF(($d < ($mz+1)) & ($d > (($mz+1)*-1)))
         INC($true)
      ELSE
         IF($d > 0)
            IF(($e1-$e1/100*$proc) > $e2)
               INC($false)
            ELSE
               INC($minus)
            END_IF
         ELSE
            IF(($e2-$e2/100*$proc) > $e1)
               INC($false)
            ELSE
               INC($plus)
            END_IF
         END_IF
         
         IF($false > 1)
            $result = 0
            $i = 10
         ELSE
            IF($true = 4)
               $result = 1
               $i = 10
            END_IF
         END_IF
      END_IF
   END_CYC
   
   IF($i ! 10)
      IF((($plus + $false) > 1) & (($minus + $false) > 1))
         $result = 0
      ELSE
         $result = 1
      END_IF
   END_IF
END_SUB


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



Вот подходящая пара картинок 4-5.

Иногда лишняя картинка очень похожа на основные (по цветам и направлению) и тогда в ответ попадали две пары, как здесь...



Похожие пары 2-3 и 2-5.
Хорошо что нам можно кликать по любой из двух одинаковых в паре. В этих двух парах общая картинка №2, если кликнем по ней не ошибёмся.

В итоге с первой же проверки правильно разгадало 5 капч.

Дальнейшее тестирование человеком на большей выборке, дало результат 22 из 30 правильных ответов ~73% уже не плохо.
На остальных не нашло пар. Просмотрев результаты значений, нашёл, что у самого худшего варианта мёртвую зону $mz нужно поднять до 13, и процент $proc  до 56. Тогда в результате пара признавалась валидной.

Товарищ предложил сделать более точное разделение на картинки. Как здесь и писали, анализируя в цикле все столбцы шириной в 1 пиксель, только не картинкой, а подсчётом цвета фона.
Анализируемая область у нас высотой 60 пикс. Т.к. есть случаи где соседние картинки наползают областями друг на друга и вертикального полного столбца фона между ними нет, берём допустимое значение в 57 пикселов.

После добавления разделения по фону и изменения настроек
$mz = 12  // допуск
$proc = 60  // процент
нашло 29 из 30 , что  ~ 96,6%

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

Вывести весь анализ в подпрограмму и вызывать её изменяя значения $mz, $proc начиная с
Code: [Select]
$mz = 15
$proc = 40

при не нахождении решения поднимать $mz на 5, а $proc на 20 и вызывать снова.
По идее ~75% решится на первом же вызове, ещё ~20% на втором и оставшиеся 3-5% должны на третьем.

Ввиду отсутствия возможности проводить тесты на натуре и отсутствие практического применения лично для меня. Дописывать скрипт не стал. Есть только вариант ещё до динамического разделения (во вложении).

Всем спасибо, все свободны.
Нафига писал, сам не знаю.
« Last Edit: February 05, 2015, 12:59:04 PM by Vint »