Author Topic: Поиск на экране (в области) всех пикселов заданного цвета  (Read 7642 times)

0 Members and 2 Guests are viewing this topic.

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Я понимаю, что после прочтения названия темы у некоторых постояльцев скажется рвотный рефлекс.
Но, спокойно! Сядьте, отдышитесь, закройте глаза...

Хотелось бы обсудить решение вопроса.
Конечно я знаю широко известный, в узких кругах  :), скрипт Андрея по поиску всех пикселов/картинок:
Code: (clickermann) [Select]
$sres = 0
$sres2 = 0
$size=40

GETSCREEN
IF_PIXEL_IN($xres1, $yres1, $xres2, $yres2, $color)
   //LOGWRITE("вводX: ", $_return1, " ","вводY: ", $_return2)
   $clresx = $_return1
   $clresy = $_return2
   GOSUB(клик2)
   
   WHILE($sres = 0)
      $sYres2 = $clresy + $size
      $sYres1 = $clresy
      $sres2 = 0
     
      WHILE($sres2 = 0)
         IF_PIXEL_IN($clresx + $size, $sYres1, $xres2, $sYres2, $color)
            //LOGWRITE("вводX: ", $_return1, " ","вводY: ", $_return2)
            $clresx = $_return1
            $clresy = $_return2
            GOSUB(клик2)
         ELSE
            $sres2 = 1
         END_IF
      END_CYC
     
      IF_PIXEL_IN($xres1, $clresy + $size, $xres2, $yres2, $color)
         //LOGWRITE("вводX: ", $_return1, " ","вводY: ", $_return2)
         $clresx = $_return1
         $clresy = $_return2
         GOSUB(клик2)
      ELSE
         $sres = 1
      END_IF
   END_CYC
END_IF

и его вариации.
Хотелось бы сразу уточнить, для многих задач применение отступа очень желательно. Это необходимо для избежания десятков повторов (и обработки) уже найденного участка.
Для поиска картинки скрипт подходит отлично. Можно задать минимальный отступ $size=1 и обыскивается весь экран. В этом случае отступ реализуется самим размером картинки. После "срезания" строки в 1 пиксел картинка уже не найдётся на том же месте.

Всё это хорошо только для картинки со 100% совпадением. Для поиска пиксела заданного цвета (и нововведения - процента совпадения картинки) вылезают проблемы. При использовании этого алгоритма поиска и нахождении пиксела как минимум дальше не обыскивается область левее найденной и высотой $size-1. Чем ближе к правой стороне области поиска будет найден пиксел, тем полоса шире. Ещё больше усугубляется при (повторном и далее) нахождении правее области отступа $size.
Поясняю на картинках (см. внизу).
В закрашенных серым областях мы сознательно не ищем совпадений.
Закрашеные жёлтым области выпадают из зоны поиска из-за недостатков алгоритма.
Для решения конечно предложат уменьшать отступ. Но это не решит проблемы полностью, если только отступ не будет равен 1. С другой стороны не хотелось бы лишаться отступа. К примеру поиск в Зомби ферме камней, дров и других элементов изменяющихся при масштабировании. Поиск по цвету который от масштаба может быть в другом месте искомого элемента даёт хорошие результаты и использование отступа примерно в ширину элемента необходимо.

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

Принцип: обходим область с использованием смещения на 1 - бывшего отступа. После каждого нахождения записывать в файл координаты игнорируемой нерабочей области (высотой и шириной $size). При каждом новом совпадении проверять на попадание в записанные "нерабочие" области. Если не попадает обрабатываем и дописываем новую область, если попадает ничего не делаем и ищем дальше.

Даже проще... пишем найденные координаты, а при сравнении учитываем найденные+$size.

Но связываться с многократным чтением/записью в текстовый файл при анализе одного скрина не хочется. Думаю скорость пострадает из-за чтения с диска.


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Когда заканчивал писать первый пост, кажется понял как разрулить ситуацию.
Есть же ещё одна замена массивам - не текстовые файлы, а строковые переменные. Загонять найденные координаты в переменную через разделители. При сравнении вытаскивать из переменной и обрабатывать.

Как всё таки полезно изложить письменно задачу. Вчера всю голову сломал.


Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Сам с собою тихо...

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

Code: (clickermann) [Select]
$sres = 0
$sres2 = 0
$size=40

GETSCREEN
IF_PIXEL_IN($xres1, $yres1, $xres2, $yres2, $color)
   //LOGWRITE("вводX: ", $_return1, " ","вводY: ", $_return2)
   $clresx = $_return1
   $clresy = $_return2
   $temp=STRCONCAT($_return1,":",$_return2)
   GOSUB(клик2)
   
   WHILE($sres = 0)
      $sres2 = 0
     
      $clresx=$clresx+1              // следующая точка за найденной
      IF($clresx<$xres2+1) // контроль последнего столбца
         WHILE($sres2 = 0)
            IF_PIXEL_IN($clresx, $clresy, $xres2, $clresy, $color)
               //LOGWRITE("вводX: ", $_return1, " ","вводY: ", $_return2)
               $clresx = $_return1
               $clresy = $_return2
               
               $nelzya=0
               $cut=$temp
               WHILE(STRLEN($cut)!0)
                  $x1=INT(STRCUT2($cut,1,STRPOS($cut,":")-1))
                  $cut=STRCUT2($cut,STRPOS($cut,":")+1,99999)
                 
                  IF(INT(STRPOS($cut,":"))!0)
                     $y1=INT(STRCUT2($cut,1, STRPOS ($cut,":")-1))
                     $cut=STRCUT2($cut,STRPOS($cut,":")+1,99999)
                  ELSE
                     $y1=INT($cut)
                     $cut=""
                  END_IF
                 
                  IF(($clresx>$x1) & ($clresx<$x1+$size) & ($clresy>$y1) & ($clresy<$y1+$size))
                     $cut="" // прерываем поиск
                     $nelzya=1
                  END_IF
               END_CYC
               
               IF($nelzya=0)
                  $temp=STRCONCAT($temp,":",$_return1,":",$_return2)
                  GOSUB(клик2)
               END_IF
               
               IF($clresx+1>$xres2) // контроль последнего столбца
                  $sres2 = 1
               END_IF
            ELSE
               $sres2 = 1
            END_IF
         END_CYC
      END_IF
     
      $clresy=$clresy+1       // следующая линия
      IF($clresy<$yres2+1) // контроль последней линии
         IF_PIXEL_IN($xres1, $clresy, $xres2, $yres2, $color)
            //LOGWRITE("вводX: ", $_return1, " ","вводY: ", $_return2)
            $clresx = $_return1
            $clresy = $_return2
           
            $nelzya=0
            $cut=$temp
            WHILE(STRLEN($cut)!0)
               $x1=INT(STRCUT2($cut,1,STRPOS($cut,":")-1))
               $cut=STRCUT2($cut,STRPOS($cut,":")+1,99999)
               
               IF(INT(STRPOS($cut,":"))!0)
                  $y1=INT(STRCUT2($cut,1, STRPOS ($cut,":")-1))
                  $cut=STRCUT2($cut,STRPOS($cut,":")+1,99999)
               ELSE
                  $y1=INT($cut)
                  $cut=""
               END_IF
               
               IF(($clresx>$x1) & ($clresx<$x1+$size) & ($clresy>$y1) & ($clresy<$y1+$size))
                  $cut="" // прерываем поиск
                  $nelzya=1
               END_IF
            END_CYC
           
            IF($nelzya=1)
               $temp=STRCONCAT($temp,":",$_return1,":",$_return2)
               GOSUB(клик2)
            END_IF
         ELSE
            $sres = 1
         END_IF
      ELSE
         $sres = 1
      END_IF
   END_CYC
END_IF

Как бы теперь её проверить грамотно. На сегодня хватит дуэлей кликера.
« Last Edit: April 02, 2013, 03:36:06 PM by Vint »


Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
А где SUB(клик2) ???

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
А где SUB(клик2) ???

Ай, тебе ли не знать. Это же твой скрипт?
Да не важно где клик2. SUB(клик2) - это обработка найденного цвета, там может быть что угодно по задаче. Вопрос то не в этом был.

Я специально не менял переменные и название подпрограммы для последующего встраивания в бот фермы.

P.S. Кому нужно: строку GOSUB(клик2) заменяете на свою обработку того, что искали.
Если просто кликнуть, то
Code: (clickermann) [Select]
LCLICK($_return1,$_return2)
WAITMS(100)



Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
А вот теперь пригляделся и понял что ты собираешь все координаты в переменную $temp
 :D

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Последний вариант был с ошибками. Я его давно доделал и использую.
Пока скорость работы желает лучшего.