|
|
|
Разработка findcolor, findimage, Pure lua |
|
|
sutra |
20.4.2021, 18:01
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
Что меня просто изумляет, что собственно код то простейший, в отличие от Профи Дарка всё по минимуму. Вот собственно сами "кишки", пока не облагораживал, за стиль извините, к какому уж привык. Код local j=2 sim=sim+2 -- счётчик пропущенных пикселей; максимум пропуска while y<hF do -- цикл по высоте зоны поиска ind=4+x1*3+(y1+y)*l -- индекс в битовой маске while x<wF do -- цикл по ширине зоны поиска for i=1,pic[0][0]do -- цикл поиска искомых пикселей картинки c.memcpy(CI[0],CI[bm]+ind+pic[i][6],3) -- переброс каналов RGB из битовой маски во временный массив if CI[0][v1]<pic[i][v1]or CI[0][v1]>pic[i][V1]or CI[0][v2]<pic[i][v2]or -- если пиксель не тот CI[0][v2]>pic[i][V2]or CI[0][v3]<pic[i][v3]or CI[0][v3]>pic[i][V3]then j=j+1 -- увеличение счётчика пропущенных пикселей if j>sim then sr=false break end -- если превышение нормы - картинки тут нет, искать далее end end if sr then -- картинка найдена af[k],k={x,y},k+1 -- зарисовали координаты в результируемый массив if k>nP then return k-1,af end -- если нашли столько сколько нужно - возврат if shiX>0 then -- если требуется сдвиг (шаг) поиска следующей x=x+shiX ind=ind+3*shiX shi=true -- двигаем, правим индекс, ставим флаг работы по высоте end end x,sr,ind,j=x+1,true,ind+3,2 end x,y=0,y+1 if shi then y=y+shiY shi=false end -- если нужен сдвиг поиска по высоте - двигаем, далее попиксельно end
Ни хрена не победил, ошибочка была, после первой найденной картинки сброс счётчика был в 1, а не в 2-ку. Короче, если разница сравниваемых параметров ЕДИНИЦА, так и хочется выругаться, то наступают "якоря". Складывается ощущение, что сравниваются не целые числа, а 0.999999999999 с 1.00000000001 с точностью уж не знаю до какого знака. Попытался обыграть таким образом rawequal(j,sim) - бесполезно, при 1 - якорь.
|
|
|
|
sutra |
22.4.2021, 19:02
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
Максимально локализовал место тормоза. Влияют друг на друга memcpy и if. Привожу полностью локализованный рабочий код. Попробуйте заремаренные варианты. Первое что ОЧЕНЬ бы хотелось узнать, как это работает у других, может это опять только у меня. У меня с единичкой получается 11 и 7 секунд для двух вариантов memcpy Ну а если кто объяснит причину этого безобразия - большой респект. код
Код --lua local ffi=require "ffi" ffi.cdef[[ void memcpy(void *Destination,void const *Source,unsigned int Length); ]] log 'clear' log 'mode compact' local CI={} CI[0]=ffi.new('unsigned char[?]',6220804) CI[1]=ffi.new('unsigned char[?]',6220804)
local function Test() local j=0 local sim=1 -- local sim=2 for jj=1,1733787 do for i=1,21 do ffi.C.memcpy(CI[0],CI[1]+8,3) -- ffi.C.memcpy(CI[0],CI[1],3) j=j+1 if j>sim then break end end j=0 end end
local t=os.clock() for i=1,10 do Test() end local t2=os.clock() log(t2-t)
|
|
|
|
sutra |
23.4.2021, 9:15
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
И даже memcpy здесь не причём, что и неудивительно. Заменил на операторы присваивания - результат тот же, точнее ещё хуже. В общем компилятор полный отстой, абсолютно не логичное поведение. Чем так не нравится именно ЕДИНИЧКА? Думаю даже если работать обычной внешней прогой (dll точно делать не стану) - получится всё намного быстрее. Тестанул сохранение в файл на виртуалку, у меня выполняется практически мгновенно. Да и вопрос то не в этом, конкретный косяк всегда можно обойти. Вот только я такие тормоза компиляции lua выявляю уже далеко не в первый раз. Следовательно, доверия к компиляции нет никакого. Если на таких простейших, ЭЛЕМЕНТАРНЕЙШИХ вещах регулярно вылезают проблемы, что уж говорить про что-то серьёзное. Баловство этот lua, во всяком случае в данном конкретном варианте. Зарекался я тестировать эту хрень, но вот нарушил сам свой обет. Всё, с меня хватит, лично я умываю руки.
|
|
|
|
Madeus |
23.4.2021, 22:35
|
Apprentice
Сообщений: 283
Регистрация: 19.11.2019 Группа: Пользователи Наличность: 8423
Пользователь №: 19.451
Возраст: 32
|
Нормально все с 1 если сравнение в начале цикла, хз почему, и это только при вызове ffi если его убрать то проблем нет вообще code
Код --lua local ffi=require "ffi" ffi.cdef[[ void memcpy(void *Destination,void const *Source,unsigned int Length); ]] log 'clear' log 'mode compact' local CI={} CI[0]=ffi.new('unsigned char[?]',6220804) CI[1]=ffi.new('unsigned char[?]',6220804)
local function Test() local j=0 local sim=1 -- local sim=2 for jj=1,1733787 do for i=1,21 do if j>sim then break end ffi.C.memcpy(CI[0],CI[1]+8,3) -- ffi.C.memcpy(CI[0],CI[1],3) j=j+1 end j=0 end end
local t=os.clock() for i=1,10 do Test() end local t2=os.clock() log(t2-t)
|
|
|
|
sutra |
24.4.2021, 10:29
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
Цитата Ну можно поменять условие под твои нужды Да меня то вроде всё устраивает. Я сделал принудительную инициализацию минимум 2 и всё нормально. На практике пропускать именно 1 пиксель не так уж и актуальна. Да я и не пользуюсь этим пропуском, я в стрелялки не играю, а остальное ищется как надо. Я специально залез в одну игру и потестировал новый свой финд на сборе ресурсов (монетки и т.д.). На фулХД время поиска всех картинок составляет около 17 тысячных секунды. То есть собрать скажем три вида ресурсов понадобится около 5 сотых секунды, куда уж быстрее. Ну и я тут конечно погорячился, слишком многого требую от lua. Он изначально предназначен не для этих целей, такие вещи надо бы конечно делать на низком уровне. Да и кто его знает, вполне возможно, что в реальном скрипте эти тормоза исчезнут. Динамическая компиляция на то и динамическая, что сама принимает решения что, когда и где требует оптимизации. Конечно мне бы надо наверное выложить свои финды, может кому-нибудь это и пригодилось. Но только у меня нет описания их работы, а пустой код кому он нужен. Делать подробное описание пока руки не доходили, может попозже.
|
|
|
|
sutra |
29.4.2021, 12:12
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
Да я пока сам не совсем понимаю как всё работает - разбираюсь. Всё пока сильно "сырое". Лично по своим алгоритмам ... То всё летает, ну скажем ищется за 3 сотых, а то вдруг возникает почти на том же самом действии тормоз в виде например 125 сотых. Но я всё-таки допытаю эту хрень. Дыма без огня не бывает, всему есть причина. Откопал ещё древние свои тесты, где были проблемы со стандартным финдом Кнайта, я тогда сразу начал делать свой и потом никогда больше не пользовался стандартом. Но там ещё на Пилоте всё нарисовано, лень по новой вникать, но попозже обязательно всё тщательно проверю и если ошибки у Кнайта подтвердятся, то и к его алгоритму соответственно возникают вопросы. Ну а про rmem я уже говорил, я давно это понял, почему и отказался от него полностью в своём финдимидже, быстрее получалось сотворить отдельный массив и работать уже исключительно с ним. Ну и выделение памяти тоже не самая быстрая операция, особенно при больших объёмах. Думаю всё и упирается в работу с памятью - учитывая что это типа фишка lua.
|
|
|
|
sutra |
29.4.2021, 12:27
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
Ну а твой код Дарк, пока не тестировал. Доделывай, а уж потом можно будет и подробнее всё посмотреть. Слишком много разных вариантов, да и проверять всё надо на реальных задачах. Пока могу сказать лишь одно, чего точно желательно сделать (я у себя сделал). При поиске нескольких картинок желательно всё-таки сделать возможность смещения (сдвига) поиска следующей картинки. Это иногда требуется, но опять же это на моём алгоритме, как будет у тебя я не знаю. Доделаешь буду пробовать искать по уже готовым своим шаблонам (типа монеток как Cirus). Цитата А почему не используешь уже готовый массив в виде битовой маски? Это у меня ещё на старом алгоритме было и там никак через указатель было не сделать, так как я вычленял из битовой маски конкретный прямоугольник. Сейчас я вообще напрямую работаю с битовой маской без всяких указателей. Минус один - используется глобальная переменная, хотя для меня это минусом не является, скорее наоборот.
|
|
|
|
sutra |
29.4.2021, 15:19
|
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007
|
Дарк, вот что я для себя выяснил. Бесполезное это дело. Объясню почему. Да без разницы как всё это делать, с указателями или без или ещё как-либо. Просто для себя я никогда не "ворочал" массу картинок по всему экрану. То есть либо искал несколько (немного) картинок по всему экрану, либо много картинок, но в локальных областях. Сделал тестовую функцию, минимизировав любые параметры, стал искать 44 разных картинки по экрану 800 х 900. И вот какая вещь. Любую картинку в отдельности нахожу максимум за три сотых, а если заряжаю поиск в цикле всех 44, то примерно после 7-10 поисков наступают "дикие" тормоза. И общее время поиска становится 47 секунд, а должно было бы быть всего лишь 13 десятых секунды. То есть тормоз аж в 356 раз. В 356 !!! Пробовал всяко, с разными переменными, локальными, глобальными, СИ-шными и lua. Без разницы. В прямом, в обратном порядке. Выполняя несколько таких циклов подряд (вообще интересные с точки зрения логики получаются результаты). С какого-то момента наступает тормоз! Ничего в памяти не выделяется, чиститься тоже вроде ничего не должно. Просто так ведёт себя компилятор, живя своей жизнью. Итог. Либо это делать внешней процедурой, либо просто плюнуть на эту скорость. Ну невозможно предсказать результат скорости. И бессмысленно сравнивать скорость со скоростью Кнайта. А за себя скажу так, если мне придётся "лопатить" такие объёмы, то даже если я кину на диск битовую маску, запущу свою внешнюю прогу, а потом считаю результат поиска с диска. То даже так будет в десятки раз быстрее.
Работа циклов в lua - это большая лотерея. И словить джек-пот можно в любом месте. Уж в который раз я сталкиваюсь с этими фокусами. Да и не я один. Помнишь, ещё 2 года назад Cirus тоже нашёл непонятки!! До сих пор всё это остаётся загадкой. Короче, завязываю я с этими тестами, бессмысленно всё это. Ты борешься с сотыми долями секунды, а словить можешь секунды. По уму надо однозначно делать внешнюю функцию через dll. Только так будет прогнозируемый результат.
А вообще спасибо вам парни! Для себя сделал вполне себе супер-вещь. Мои задачи выполняются просто на ура. Всё мгновенно. Ещё раз огромное спасибо ВСЕМ!
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|