Author Topic: Подсчет кол-ва одинаковых пикселей в заданной обл. и вывод в лог самого частого  (Read 2458 times)

0 Members and 1 Guest are viewing this topic.

kiperenok

  • Зашел в гости
  • *
  • Posts: 4
    • View Profile
Помогите ! Второй вечер ломаю голову с эти циклами и массивами - ни чего не работает. На Lua я за 5 минут такой код пишу и справляюсь с задачей, а здесь ни фига не получается.
Задача - с помощью функции PXL($x , $y), записать в массив коды цветов всех пикселей в заданной области. Затем функцией TFWriteArr извлечь все кода цветов в текстовый файл, ну а дальше я уже на Lua отсортирую массив и найду самый часто встречающийся цвет пикселя в данной области.
Но я даже не могу записать в массив коды цветов, т.к. у меня проблема с двойными циклами - записывает только итерации внутреннего цикла. И у массивов не работает двойной массив почему то - $arr [1][2]  к примеру.
Буду признателен если кто то напишет такой скрипт, можно даже разместить его в теме (Типовые алгоритмы, вводные статьи (Новички, читайте!)).
Вот мой код где я пытался решить эту задачу
Code: (clickermann) [Select]
GETSCREEN

FOR($x, $x < 60)
    FOR($y, $y < 40)
        $arr[$count]= PXL($x, $y)
        $count = $count + 1
    END_CYC
END_CYC   

TFWriteArr("out.txt", $arr )

halt

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Code: (clickermann) [Select]
// v4.13.014

// 700,153 - верхний левый угол
// 775,226 - нижний правый


GETSCREEN
FOR($y=153, $y <= 226)
   FOR($x=700, $x <= 775)
      ARRPUSH($arr, PXL($x,$y))
   END_CYC
END_CYC

TFWriteArr("out.txt", $arr)

halt

kiperenok

  • Зашел в гости
  • *
  • Posts: 4
    • View Profile
Спасибо большое ! Оказывается все просто решается 1 функцией, а я все по старинке хотел решить  ;)
UPT - Если в координатах выставлять четырехзначное число, то вылетает ошибка
UPT2 - теперь и трехзначные вылетают. Там ограничение на размер захватываемой площади ?
« Last Edit: October 20, 2018, 07:28:58 PM by kiperenok »

Vint

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


Qwerry

  • Активный участник
  • ***
  • Posts: 117
    • View Profile
А вот такой вопрос - зачем считать пиксели в другой программе, если в самом кликермане теперь есть функция PXLCOUNT?
Вот например, такой вариант (сделано через .ini, хотя можно было и с массивами поработать): относительно быстрый, хотя есть что улучшать - например прикрутить проверку, чтобы сразу завершал работу, если найденный максимум по цвету больше, чем осталось пикселей проверять.
Code: (clickermann) [Select]
$x_0= 700
$y_0= 153
$x_1= 775
$y_1= 226


$time=$_ms
TFCLEAR("out1.ini", 0) // очищение файла с предыдущим результатом
GETSCREEN
FOR($y=$y_0, $y<=$y_1)
   FOR($x=$x_0, $x <= $x_1)
      $str = INIREAD("out1.ini", PXL($x,$y))
      If($str="")
         $num =PXLCOUNT($x_0,$y_0,$x_1,$y_1,PXL($x,$y))
        // Print(PXL($x,$y)," $num ",$num )
         INIWRITE ("out1.ini", PXL($x,$y), $num)
         If($num1<$num)
          $num1=$num
          $col= PXL($x,$y)
         end_if
      End_if
   END_CYC
END_CYC
print($col, " colour= ",$num1) // собственно результат: номер самого распространенного цвета и количество
//SCREENSHOTEX($x_0,$y_0,$x_1,$y_1, "Image_", 0)// сохранить область, где считали пиксели
//Print(($y_1-$y_0)*($x_1-$x_0)  ," all pxls")// сколько всего пикселей в области
//Print(TFCOUNT("out1.ini")-2," colours")// сколько цветов встретилось в области (строк с номерами цветов)
print("time=",$_ms-$time) // затраченное на работу время в мс
print("")
halt

dramster

  • Герой форума
  • *****
  • Posts: 1134
    • View Profile
Вот например, такой вариант (сделано через .ini, хотя можно было и с массивами поработать): относительно быстрый, хотя есть что улучшать - например прикрутить проверку, чтобы сразу завершал работу, если найденный максимум по цвету больше, чем осталось пикселей проверять.

Круто,  использовать запись в .ini , это я бы никогда бы и не подумал бы, главное все просто и без всяких там сложных заморочек  :D. Где-то уже встречал похожее использование записи в ини на этом форуме...
А мне в голову немного другая идея сразу пришла. Естественно через массив, но, с "подвохом".
Я решил удалять уже подсчитанные пиксели из буфера pxlreplac-ам.
По скорости выполнения вышло почти в два раза быстрее, скорее всего зависит от количества цветов в области. Сравнивал на одинаковых областях 100х100 с 43-мя цветами в ней.
Code: (clickermann) [Select]
$x_0 = 950
$y_0 = 230
$x_1 = 1050
$y_1 = 330



$time=$_ms

GETSCREEN
//в начале проверяем есть ли в области черный цвет - 0, если есть, то пишем в массив
IF_PIXEL_IN($x_0,$y_0, $x_1,$y_1, 0)
   ARRPUSH($count_col, PXLCOUNT ($x_0, $y_0, $x_1, $y_1, 0))
   ARRPUSH($count_col, 0)
END_IF

//далее перебор всех в области
FOR($y=$y_0, $y<=$y_1)
   FOR($x=$x_0, $x <= $x_1)
      $pxl = pxl($x,$y)
      IF($pxl > 0)   //если он не черный, то пишем в массив
         ARRPUSH($count_col, PXLCOUNT ($x_0, $y_0, $x_1, $y_1, $pxl))
         ARRPUSH($count_col, $pxl)
         //и заменяем в буфере все эти пиксели черным - 0
         PXLREPLACE ($x_0, $y_0, $x_1, $y_1, $pxl, 0)
      END_IF
   END_CYC
END_CYC

// собственно результат: номер самого распространенного цвета и количество
$count_max = $count_col[0]
$color =  $count_col[1]
FOR($i=2,$i<arrsize($count_col),2)
   IF($count_col[$i] > $count_max)
      $count_max = $count_col[$i]
      $color =  $count_col[$i+1]
   END_IF   
END_CYC
print($color, " - ",$count_max)

//вывод всех цветов и их количество в лог
//FOR($i=0,$i<arrsize($count_col),2)
//   print($count_col[$i+1], " - ", $count_col[$i])
//END_CYC

print(arrsize($count_col)/2," colours")// сколько цветов встретилось в области


print("time=",$_ms-$time) // затраченное на работу время в мс
print("")
halt

При написании этого варианта, сразу вспомнилась тема-предложение по функционалу "IF_NOT_PIXEL_IN" http://crapware.aidf.org/forum/index.php?topic=2390.0 Как-раз то, что  помогло бы в моем примере  ::).

« Last Edit: October 21, 2018, 10:07:09 PM by dramster »

Qwerry

  • Активный участник
  • ***
  • Posts: 117
    • View Profile
Круто,  использовать запись в .ini , это я бы никогда бы и не подумал бы, главное все просто и без всяких там сложных заморочек  :D. Где-то уже встречал похожее использование записи в ини на этом форуме...
Просто буквально первый скрипт (от тех прекрасных времен, когда и для меня на форуме справку скриншотили  ;D) был викториной, сделанной при помощи ини. На автомате через этот формат и было сделано)
Quote
А мне в голову немного другая идея сразу пришла. Естественно через массив, но, с "подвохом".
Я решил удалять уже подсчитанные пиксели из буфера pxlreplac-ам.
По скорости выполнения вышло почти в два раза быстрее, скорее всего зависит от количества цветов в области. Сравнивал на одинаковых областях 100х100 с 43-мя цветами в ней.
При написании этого варианта, сразу вспомнилась тема-предложение по функционалу "IF_NOT_PIXEL_IN" http://crapware.aidf.org/forum/index.php?topic=2390.0 Как-раз то, что  помогло бы в моем примере  ::).
Если цветов много, то почти в 2 раза, а если анализировать, например, редактор кликера: несколько цветов на белом фоне, то получается в 3 раза быстрее (800 против 2400). 
Хмм, надо будет повнимательнее к изменениям графики в буфере отнестись - ведь через массивы вместо изящного решения (даже не подумала, что можно бы упростить всё через pxlreplac), у меня бы банальный поиск по массиву был прикручен (что занимало бы вечность)).

kiperenok

  • Зашел в гости
  • *
  • Posts: 4
    • View Profile
Теперь у меня другая проблема. С функциями COLORMODE и IF_PICTURE_IN. В общем если применить функцию IF_PICTURE_IN на сохраненную в 24 бита bmp картинку в режиме обычного ее просмотра, то скрипт срабатывает. А вот в самой игре он ее в упор не видит. Если я добавляю параметры bgcolor и currency то выскакивает ошибка. Попробовал применить перед getscreen функцию COLORMODE и тоже выскакивает ошибка.

kiperenok

  • Зашел в гости
  • *
  • Posts: 4
    • View Profile
Спасибо большое ! Сделал скрин самим Кликерманом и все заработало без всяких COLORMODE.