Начал осваивать LUA, помогите пожалуйста, в справке нет многих операторов.
Сразу возник вопрос, как загрузить массив из файла (аналог load_array), наверняка ответ на форуме есть, но я не нашёл. В обычном скрипте код такой.
load_array %cfg $ConfigFile
Ну и сохранить соответственно тоже не знаю как.
--lua
log "clear" log "mode compact"
local f = io.open([[C:\111.txt]], "r") -- открыть файл для чтения
if f then -- если файл открылся
local cfg = {} -- объявили массив
for v in f:lines() do -- читаем файл 111.txt по строкам
cfg[#cfg+1]=v -- добавляем в массив
end
f:close(); -- закрыть файл
log(table.concat(cfg, " ")) -- вывести массив в лог
for i=1, #cfg do -- для всех элементов массива
cfg[i]=tostring(i) .. " " .. cfg[i] -- вначале строки добавим номер строки
end
f = io.open([[C:\222.txt]], "w") -- открыть файл для записи
if f then
for i=1, #cfg do -- для всех элементов массива
f:write(cfg[i] .. "\r\n") -- запись в файл
end
f:close(); -- закрыть файл
end
end
Поскольку lua весь на деревьях и размеры массивов могут быть различными даже в части вложенности элементов (они не прямоугольные в lua), то лучше использовать что-то более серьезное, хотя в базовом виде работать бесспроно будет.
Например есть вот такое творение:
http://lua-users.org/wiki/TablePersistence
local write, writeIndent, writers, refCount;
persistence =
{
store = function (path, ...)
local file, e = io.open(path, "w");
if not file then
return error(e);
end
local n = select("#", ...);
-- Count references
local objRefCount = {}; -- Stores reference that will be exported
for i = 1, n do
refCount(objRefCount, (select(i,...)));
end;
-- Export Objects with more than one ref and assign name
-- First, create empty tables for each
local objRefNames = {};
local objRefIdx = 0;
file:write("-- Persistent Data\n");
file:write("local multiRefObjects = {\n");
for obj, count in pairs(objRefCount) do
if count > 1 then
objRefIdx = objRefIdx + 1;
objRefNames[obj] = objRefIdx;
file:write("{};"); -- table objRefIdx
end;
end;
file:write("\n} -- multiRefObjects\n");
-- Then fill them (this requires all empty multiRefObjects to exist)
for obj, idx in pairs(objRefNames) do
for k, v in pairs(obj) do
file:write("multiRefObjects["..idx.."][");
write(file, k, 0, objRefNames);
file:write("] = ");
write(file, v, 0, objRefNames);
file:write(";\n");
end;
end;
-- Create the remaining objects
for i = 1, n do
file:write("local ".."obj"..i.." = ");
write(file, (select(i,...)), 0, objRefNames);
file:write("\n");
end
-- Return them
if n > 0 then
file:write("return obj1");
for i = 2, n do
file:write(" ,obj"..i);
end;
file:write("\n");
else
file:write("return\n");
end;
if type(path) == "string" then
file:close();
end;
end;
load = function (path)
local f, e;
if type(path) == "string" then
f, e = loadfile(path);
else
f, e = path:read('*a')
end
if f then
return f();
else
return nil, e;
end;
end;
}
-- Private methods
-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
writers[type(item)](file, item, level, objRefNames);
end;
-- write indent
writeIndent = function (file, level)
for i = 1, level do
file:write("\t");
end;
end;
-- recursively count references
refCount = function (objRefCount, item)
-- only count reference types (tables)
if type(item) == "table" then
-- Increase ref count
if objRefCount[item] then
objRefCount[item] = objRefCount[item] + 1;
else
objRefCount[item] = 1;
-- If first encounter, traverse
for k, v in pairs(item) do
refCount(objRefCount, k);
refCount(objRefCount, v);
end;
end;
end;
end;
-- Format items for the purpose of restoring
writers = {
["nil"] = function (file, item)
file:write("nil");
end;
["number"] = function (file, item)
file:write(tostring(item));
end;
["string"] = function (file, item)
file:write(string.format("%q", item));
end;
["boolean"] = function (file, item)
if item then
file:write("true");
else
file:write("false");
end
end;
["table"] = function (file, item, level, objRefNames)
local refIdx = objRefNames[item];
if refIdx then
-- Table with multiple references
file:write("multiRefObjects["..refIdx.."]");
else
-- Single use table
file:write("{\n");
for k, v in pairs(item) do
writeIndent(file, level+1);
file:write("[");
write(file, k, level+1, objRefNames);
file:write("] = ");
write(file, v, level+1, objRefNames);
file:write(";\n");
end
writeIndent(file, level);
file:write("}");
end;
end;
["function"] = function (file, item)
-- Does only work for "normal" functions, not those
-- with upvalues or c functions
local dInfo = debug.getinfo(item, "uS");
if dInfo.nups > 0 then
file:write("nil --[[functions with upvalue not supported]]");
elseif dInfo.what ~= "Lua" then
file:write("nil --[[non-lua function not supported]]");
else
local r, s = pcall(string.dump,item);
if r then
file:write(string.format("loadstring(%q)", s));
else
file:write("nil --[[function could not be dumped]]");
end
end
end;
["thread"] = function (file, item)
file:write("nil --[[thread]]\n");
end;
["userdata"] = function (file, item)
file:write("nil --[[userdata]]\n");
end;
}
t_original = {1, 2, ["a"] = "string", b = "test", {"subtable", [4] = 2}};
persistence.store("storage.lua", t_original);
t_restored = persistence.load("storage.lua");
local write, writeIndent, writers, refCount;
local persistence =
{
save = function (path, ...)
local file, e = io.open(path, "w");
if not file then
return error(e);
end
local n = select("#", ...);
-- Count references
local objRefCount = {}; -- Stores reference that will be exported
for i = 1, n do
refCount(objRefCount, (select(i,...)));
end;
-- Export Objects with more than one ref and assign name
-- First, create empty tables for each
local objRefNames = {};
local objRefIdx = 0;
file:write("-- Persistent Data\n");
file:write("local multiRefObjects = {\n");
for obj, count in pairs(objRefCount) do
if count > 1 then
objRefIdx = objRefIdx + 1;
objRefNames[obj] = objRefIdx;
file:write("{};"); -- table objRefIdx
end;
end;
file:write("\n} -- multiRefObjects\n");
-- Then fill them (this requires all empty multiRefObjects to exist)
for obj, idx in pairs(objRefNames) do
for k, v in pairs(obj) do
file:write("multiRefObjects["..idx.."][");
write(file, k, 0, objRefNames);
file:write("] = ");
write(file, v, 0, objRefNames);
file:write(";\n");
end;
end;
-- Create the remaining objects
for i = 1, n do
file:write("local ".."obj"..i.." = ");
write(file, (select(i,...)), 0, objRefNames);
file:write("\n");
end
-- Return them
if n > 0 then
file:write("return obj1");
for i = 2, n do
file:write(" ,obj"..i);
end;
file:write("\n");
else
file:write("return\n");
end;
if type(path) == "string" then
file:close();
end;
end;
load = function (path)
local f, e;
if type(path) == "string" then
f, e = loadfile(path);
else
f, e = path:read('*a')
end
if f then
return f();
else
return nil, e;
end;
end;
}
-- Private methods
-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
writers[type(item)](file, item, level, objRefNames);
end;
-- write indent
writeIndent = function (file, level)
for i = 1, level do
file:write("\t");
end;
end;
-- recursively count references
refCount = function (objRefCount, item)
-- only count reference types (tables)
if type(item) == "table" then
-- Increase ref count
if objRefCount[item] then
objRefCount[item] = objRefCount[item] + 1;
else
objRefCount[item] = 1;
-- If first encounter, traverse
for k, v in pairs(item) do
refCount(objRefCount, k);
refCount(objRefCount, v);
end;
end;
end;
end;
-- Format items for the purpose of restoring
writers = {
["nil"] = function (file, item)
file:write("nil");
end;
["number"] = function (file, item)
file:write(tostring(item));
end;
["string"] = function (file, item)
file:write(string.format("%q", item));
end;
["boolean"] = function (file, item)
if item then
file:write("true");
else
file:write("false");
end
end;
["table"] = function (file, item, level, objRefNames)
local refIdx = objRefNames[item];
if refIdx then
-- Table with multiple references
file:write("multiRefObjects["..refIdx.."]");
else
-- Single use table
file:write("{\n");
for k, v in pairs(item) do
writeIndent(file, level+1);
file:write("[");
write(file, k, level+1, objRefNames);
file:write("] = ");
write(file, v, level+1, objRefNames);
file:write(";\n");
end
writeIndent(file, level);
file:write("}");
end;
end;
["function"] = function (file, item)
-- Does only work for "normal" functions, not those
-- with upvalues or c functions
local dInfo = debug.getinfo(item, "uS");
if dInfo.nups > 0 then
file:write("nil --[[functions with upvalue not supported]]");
elseif dInfo.what ~= "Lua" then
file:write("nil --[[non-lua function not supported]]");
else
local r, s = pcall(string.dump,item);
if r then
file:write(string.format("loadstring(%q)", s));
else
file:write("nil --[[function could not be dumped]]");
end
end
end;
["thread"] = function (file, item)
file:write("nil --[[thread]]\n");
end;
["userdata"] = function (file, item)
file:write("nil --[[userdata]]\n");
end;
}
return persistence
local tableToFile = require[[luaPlugins\tableToFile]] -- объявляется один раз в начале скрипта.
-- Объявляем массив
local arr = {10,9,8,7,6,5,4,3,{21,22,23,"'}\"\t\'",{}},1,0}
-- Сохраняем массив
tableToFile.save("1.txt",arr)
-- Закгружаем массив
arr2=tableToFile.load("1.txt")
Предчувствуя следующий вопрос:
local function lg(data, comment)
if comment ~= nil then
log(comment)
end
local tab = ""
local deep = 0
local function show(data)
-- Пишем в лог комментарий.
deep = deep + 1 -- Уровень вложенности вызовов функции.
if type(data) == "table" then
local element_counter = 0
for k,v in pairs(data) do
element_counter = element_counter + 1
if type (v) == "table" then
log(tab..'table: '..k)
tab = tab .. " "
show(v)
tab = string.sub(tab, 1, -5)
else
if type(v) == "nil" then v = "nil"
elseif type(v) == "string" then v = '"' .. v .. '"'
elseif type(v) == "number" then v = tostring(v)
elseif type(v) == "function" then v = tostring(v)
elseif type(v) == "thread" then v = tostring(v)
elseif type(v) == "userdata" then v = "userdata"
elseif type(v) == "boolean" then v = tostring(v)
elseif type(v) == "table" then
log(tab..""..k.." = "..v or "nil")
else
v = "uknown data type"
end
log(tab..""..k.." = " .. v)
end
end
log("Elements in table: " .. element_counter)
else
log('table is "' .. type(data) .. '" data type. Value: ' .. tostring(data))
end
-- Пишем в лог комментарий.
deep = deep - 1 -- Уровень вложенности вызовов функции.
end
show(data)
end
Спасибо большое парни! Оба здорово помогли мне. Сделал средний вариант, не так сложно как у Дарка, но с поддержкой двумерных строково-числовых массивов. И на будущее ещё много чего понял. Ещё раз спасибо.
Дарк, а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт? Или только через файл. Замечание я принял, спасибо. Но я всё люблю попробовать сам и понять как это работает, так сказать на всякий случай, в целях самообразования. Просто читаешь иногда посты, там говорят что мол это невозможно, а начинаешь пробовать и всё получается. Вот не помню уж где-то видел, что нельзя анализировать звук, а я анализирую без проблем.
Смысла нет, просто скрипт огромный, хотел частями попробовать, так что проехали.
А про звук ... Ну программер из меня хреновый, а вот придумывать я мастак. Сначала хотел всё делать "по уму", но как я уже сказал, программер из меня... Поэтому сделал просто. Вывожу микшер куда мне надо (засунул на второй монитор в самый низ). А потом всё тем же Файндом просто контролирую шкалу громкости. Как минимум длительность звука и его пиковые пороги контролировать элементарно. Теоретически можно и синусоиду контролировать, тогда нужно чтобы постоянно висела какая-нибудь программулина, но это уж точно изврат.
Файнды - ЭТО СИЛА. Думаю в Lua всё будет "летать" и я никаких проблем и ограничений для себя не вижу. Ещё раз спасибо Кнайту. Несмотряна то, что я нищий, если заведу себе яндекс деньги, то отблагодарю.
С одним монитором в полноэкранном режиме естественно не прокатит. А меня вполне устраивает. А по уму надо как я понимаю плагин прикручивать. Только как вытащить туда звуки системы я не знаю, но теоретически однозначно можно. Микшер то вытаскивает ...
В башке "месиво" сплошное от всех этих языков, тяжко продвигается. То set поставлю, то вместо "==" одиночное "=", то then забуду. Залез тут как-то в Делфи, про begin-ы и точки с запятыми забываю, ну там быстро напоминают, ещё до компиляции. Никаких стандартов, каждый норовит своё придумать, ладно хоть Escape у всех одинаково работает, а вот уже с Enter-ом проблемы встречаются. По уму должны перевод строки приклеивать, но это не факт.
Во какую тему замутил. А я вот со своим дилетантским взглядом считаю так, что если мне нужно вбить колышек, я беру кувалду, пару раз стукну и всё, а не вызываю машину для забивки свай. 99% пользователей Пилота "забивают колышки". Здесь не игрушки пишут и не рассчитывают турбулентность. Поэтому овчинка должна стоить выделки. Зачем мне тратить уйму времени и забивать голову ненужной информацией если нужно выполнить примитивнейшие действия. Лично для меня язык Пилота был абсолютно понятен сразу на 100%. И я быстро разберусь с любым скриптом, если будут адекватные имена переменных. С Lua намного сложней, там уже нужно частенько вникать подробно и с ходу в чужом коде можно мозги вывихнуть. Для меня Пилот, просто полезный и лёгкий в освоении инструмент. И меня практически всё в нём устраивает, но возникло пару моментов, где не хватает быстродействия, вот и решил перейти на Lua , но придётся потратить немало времени.
Я попробовал и даже простейшую функцию не смог сделать в Lua. Что-то не так с видимостью. А что не так пока не понимаю.
--lua
-- функция должна находится выше её вызова
function f(x, y) -- принимает 2 параметра
return x+y -- возвращает сумму
end
local z=f(5, 6) -- вызов функции
log (z)
Не смог реализовать goto как только не пробовал, даёт ошибку.
Такая и у меня работает. Мне нужно передать в неё переменную, там с ней выполняются действия и мне нужна модифицированная ПЕРЕМЕННАЯ. А точнее таблица.
То есть я должен передать в функцию таблицу.
Хотя и с обычной переменной ничего не получилось.
Надо типа такого, чего не работает.
--lua
function proba(a)
return a = 12
end
log "clear"
local zz = 5
local tt = proba(zz)
log(tt)
если без return то в основном теле будет nil
--lua
function proba(a)
a = 12
return a
end
log "clear"
local zz = 5
local tt = proba(zz)
log(tt)
--lua
log "clear" log "mode compact"
function f(arr2)
for i=1, #arr2 do
arr2[i]=arr2[i]*2 -- умножить все элементы на 2
end
end
local arr={}
for i=1, 10 do -- заполнить массив числами от 1 до 10
arr[i]=i
end
log (table.concat(arr, " ")) -- содержимое массива
f(arr) -- вызов функции
log (table.concat(arr, " ")) -- содержимое массива после вызова функции
Спасибо. То есть goto не работает??
Меня конечно учили в своё время, что goto использовать является минимум признаком дурного стиля, но иногда это сильно упрощает код.
Всё верно, именно Lua 3 я и смотрел.
Буду думать, если не смогу модифицировать скрипт без goto придётся отказаться от Lua.
Да, конечно можно без goto , но придётся городить огород с кучей while-ов код будет ужасно плохо читаемым. У меня goto использовался например для рестарта скрипта в случае отключения интернета, ну и ещё в 2-х критических случаях, придётся всё заключать в циклы и брейками прерывать скрипт.
А оператор continue в цикле while есть?
В луа нет continue.
Это очень нехорошо. Если честно, то я не понимаю. С одной стороны типа прогрессивная вещь, а с другой стороны вроде очевидных вещей нет. Придётся буквально весь код запихивать в функции, которые будут содержать куски кода без особой логики. Видимо придётся их так и называть blok01 .. blok77. А основное тело будет состоять из вызова этих кусков. Просто в моём случае десятки раз вызывается функция обработки ошибок и обработки возникших неадекватных ситуаций. Собственно там и были goto которые перенаправляли код на повторные действия. Так что придётся работать брейками и кусками с ретурнами.
while var > 1 do
local result = check_some_params()
if result then
some_actions()
end
end
Спасибо Дарк. Но у меня так не получится. Допустим у меня проверка в 4-ом колене ветвления if . После проверки происходит дальнейшее выполнение кода в этом же ИФе. То есть проверить и по результатам что-то выполнить - это не требуется, а наоборот в обязательном порядке прекратить выполнение кода (ну глупо что-то выполнять если отключили интернет или сервер недоступен) и в данном примере идти почти в самое начало скрипта и крутить цикл пока не появится связь с сервером. Поэтому выход вижу только один всё пихать в функции. После проверки выполнять return из функции, а вот весь остальной код придётся запихивать в if. И таких ифов до конца всего кода будет ну с десяток точно.
Слишком сложный код. никакого линейного выполнения кода нет. Всё постоянно меняется, поэтому много проверок всяких. Управление конечно попытался упростить насколько смог. Всё управляется несколькими десятками файлов конфигурации. А файлами конфигурации управляет файл сценария. Хотя и сценарий тоже может изменяться по ходу скрипта. В итоге ну полная иллюзия, что играет живой человек. Игра выполняется хоть круглые сутки и нет повторения событий. Я только контролирую и занимаюсь не ерундой, а пытаюсь ещё и чем-то полезным заниматься.
По логике у тебя тоже всё правильно. Собственно так примерно и будет, только эти вайлы будут как снежный ком. И формат уедет настолько сильно вправо, что код будет плохо читаемым. Буду как-то сочетать. Что-то сделаю локальным распихав по функциям, что-то придётся умещать в одном блоке кода.
Грубо говоря есть определённое количество событий, которые могут вызываться один из другого. И простыми вызовами функций я могу получить неконтролируемую рекурсию. Поэтому в Пилотовском коде я и использовал goto. Тут придётся крепко репу почесать, чтобы было красиво и эффективно.
local n = "123.txt"
local f = io.open(n, "r")
Не смог открыть файл при помощи переменной. Перепробовал всё что знал - результат нуль. Просветите меня пожалуйста. Что-то мне подсказывает, что намаюсь я ещё. И большая просьба в примерах показывайте работу с переменными, поскольку у меня всё только через переменные.
Обычным текстом открывает [[123.txt]]
Минутку, теперь и обычным не открывает, сейчас гляну.
Доигрался, вообще Пилот завис.
--lua
local n = "123.txt" -- файл лежит рядом с exe пилота
local f = io.open(n, "r")
log "clear" log "mode compact"
if f then -- если файл открылся
log(f:read()) -- первая строка из файла
else
log ("Файл не открылся")
end
Перегрузил Пилот через прибивалку, всё заработало, спасибо Дарк.
Видимо крепко я накуралесил, да ещё и игра играет в параллельном скрипте.
И тебе cirus тоже спасибо.
Теперь буду знать, что иногда надо пнуть ногой по баллону.
Понял причину, забыл поставить двойной слеш при указании полного пути.
Я не редактировал. Просто сначала использовал полный путь. Потом пути были без слешей и не работало только с переменной, потом вообще не работало, причину Вы мне подсказали (перегрузить).
Я понял почему изначально не работало.
Добрался до файндов. и как и думал ничего у меня не получилось. Не могли бы кинуть реальный пример findimage. Хотел потестировать косяк. Параметры интересуют когда есть адрес загруженной картинки и адрес области экрана. И думаю, что и с findcolor тоже сам не врублюсь, поэтому и его примерчик тоже неплохо бы самому поглядеть.
И конечно примеры на lua "надёжно" зарыты. Через спецстраницы, через страницы-сироты. Но и там есть далеко не всё, а если бы было, то дилетанты типа меня не донимали бы элементарными вопросами.
--lua
local a, c = findimage(0, 0, 1920, 1080, {[[C:\Users\abc\Desktop\image.bmp]]}, 2)
-- a - это массив, c - количество картинок или точность поиска, если картинка одна
if a then
move(a[1][1], a[1][2])
end
--lua
local a = findcolor("0, 0, 1920, 1080, 1, 1, 7223552, 2")
hint (a)
Спасибо.
--lua
log "clear" log "mode compact"
addressl, widthl, heightl, lengthl = loadimage ([[C:\TMP\Original.bmp]])
log(widthl, heightl, lengthl)
addressg, widthg, heightg, lengthg = getimage (470, 924, 500, 933)
log(widthg, heightg, lengthg)
local a, c = FindImage(0, 0, 1920, 1080, addressl, addressg, 100)
deleteimage (addressl)
deleteimage (addressg)
Не работает, дает ошибку.
Сорри, забыл на строчные переделать. Спасибо.
Да, в findimage есть баг, если искать на скрине от координат 0 0, то нормально ищет. Иначе не находит.
--lua
log "clear" log "mode compact"
addressl, widthl, heightl, lengthl = loadimage ([[C:\TMP\Original.bmp]])
log(widthl, heightl, lengthl)
addressg, widthg, heightg, lengthg = getimage (470, 924, 470, 933)
log(widthg, heightg, lengthg)
local a, c = findimage(0, 0, 1920, 1080, {addressl, addressg})
if a then
move(a[1][1], a[1][2])
end
log(a, c) -- результат LuaTable 100 Примерно так. При ширине захвата 1 пиксель
deleteimage (addressl)
deleteimage (addressg)
Методом тыка ошибок избежал, но ничего не понял. Адреса заключил в фигурные скобки, насколько это правильно я не знаю.
--lua
log "clear" log "mode compact"
addressl = loadimage ([[C:\TMP\Original.bmp]])
addressg = getimage (0, 0, 1920, 1080)
local a, c = findimage(0, 0, 1920, 1080, {addressl}, addressg)
if a then
move(a[1][1], a[1][2])
end
log(a, c)
deleteimage (addressl)
deleteimage (addressg)
Спасибо разобрался. Ну в общем тот баг и в lua проявляется точно так же. Результат один в один.
--lua
log "clear" log "mode compact"
clipboard ("проверка связи") -- записать в буфер обмена фразу
wait (300) -- пауза 300 мсек
local text = clipboard () -- получить из буфера обмена текст в переменную text
log (text) -- отобразить в логе значение переменной text
--endlua
get clipboard $a // получили из буфера обмена текст
log $a
end_script
Спасибо.
--lua
local a = findcolor("0, 0, 1920, 1080, 1, 1, 6106880, %arr, 2")
if arr then
move (arr[1][1], arr[1][2])
end
Спасибо.
А какой самый простой способ в lua убить массив?
Типа повторно инициализировать?
local arr {}
Вот я тугодум, понял. Просто arr={}
Спасибо. Вывод... лучше спросить, коли с мозгами туго.
Всем огромное спасибо, кто потратил своё время на моё обучение. Не стал дожидаться доводки до ума файндов и соорудил временную конструкцию, но даже она дала отличный результат. Переделал блок распознавания чисел в тексте.
Хочу просто поделиться результатами:
set timer3
set #tmp findcolor (688 639 825 639 1 1 (R(0-255)) %tmp)
set %tmp[139 1] #HandleWorkWindow
save_array %tmp "a:\_find.txt" // запись на RAM диск для считывания в lua
set timer4
start_script 8 wait // скрипт на lua
set #time1 timer3 // время выполнения 36-49 тыс. секунды (раньше было 360-800 тыс.)
set #time2 timer4 // время выполнения 16-26 тыс. секунды
Раньше время варьировалось в зависимости от количества распознаваемых цифр (требовалось около 0,1 сек. на цифру). Сейчас всё мгновенно, время выполнения - чистый рэндом и не зависит от количества распознаваемых символов. Грубо говоря старт и выполнение скрипта на lua требует не более 25 тысячных секунды.
--lua
check=5
checkint=0
for i=1, 10 do
for j=1, 10 do
if j > check then
checkint = 1
break
end
end
if checkint == 1 then
break
end
end
Поправьте меня если я опять чего-то напутал. Другого варианта прерывания циклов нет? Уровень прерывания всегда равен 1? break 2 - недопустимая конструкция?
Не забывайте области видимости - пишите local при объявлении переменных.
Так Cirus показывал на примере моей картинки в теме по Пилоту.
На 10-й страничке.
А колор в памяти путает координаты поиска, я тоже там говорил.
Я тебе могу предложить убрать костыль по координатам поиска в финдимидже. Там, если ты забыл первый пиксель пляшет и область берется больше, потом результат фильтруется.
В приват ща опишу. А то "секретные технологии" палить не хочу)
Блин, секретные технологии. Ну у меня тоже есть такие. Конечно не так универсально, но у меня работает как часы собственный findimage. Конструкция Exec ... пока работает внешняя программа, Пилот не успевает добраться до результатов её работы, потому что конструкция ExecAndWait выполняется всего 2 сотых секунды. Ищется картинка размером 500х26 среди почти 900 файлов эталонов. Результат пишется в файл сценария который может менять ход игры.
Фишка в том, что анализируются не изображения, а файлы. Картинки в формате jpg с качеством 90% (чтобы был больше разброс по размеру файлов). Считывание имён и размеров без открытия самих файлов происходит практически мгновенно. Одинаковых по размеру не так много, вот только они и сравниваются, если отличаются, то обычно сразу же на первых байтах. Главный секрет как сделать так, чтобы картинки не "плавали от рендеринга" и всегда получались идентичными. Но это отдельная тема.
Думаю всё это легко можно сделать в lua , но мне просто лень переделывать и так всё чудно работает.
Надо было конечно вообще сделать 100% качество jpg, тогда думаю вообще одинаковых бы не встречалось, но опять же лень по новой коллекцию эталонов делать, скорости хватает.
Ха, в lua. Я не знаю как там получить список файлов.
Стыдно признаться, но всё это сделал на убогом 32-х разрядном делфи образца 1999 года. Не думал, что придётся программировать спустя столько лет. Си выучить не получилось, в 90-е было не до этого, надо было семью кормить.
--lua
log "clear" log "mode compact"
resultarray, count = dir ([[C:\Windows]], "*.exe", "norecursion")
log ("Найдено файлов: " .. count)
if count > 0 then
for i=1, count do
log(resultarray[i][1])
end
end
В данном случае я бы рекомендовал для начала забыть про jpg. Не стоит создавать проблемы там, где их можно легко избежать. Не тот размер у бмп/пнг, чтобы ловить развлечения с jpg.
Очень неплохо поднимается производительность, если буферизировать изображения под имидж, если их нужно перебирать достаточно большое количество.
Loadimage()
Тем не менее нужно понимать, что для некоторых случаев колор действительно предпочтительнее, когда можно описать одной формулой несколько изображений, а то и десяток.
Так в том то и фишка, что колор в памяти только-только начал свой путь в большую жизнь. Колором я бы ещё мог ускорить распознавание. Вызов printscreen и getimage по скорости абсолютно одинаков (у меня 27 тысячных), а обработка колором (в теории) быстрее тех 2-х сотых, которые кушает моя программа.
Конечно я имею ввиду lua, а его я начал осваивать без году неделя.
--lua
-- сделать привязку Ctrl+A
local h = workwindow()
local t, addr=os.clock()
for i=1, 100 do -- для теста 100 скринов
addr = getimage (0, 0, 500, 500)
end
log(os.clock()-t)
t=os.clock()
for i=1, 100 do -- для теста 100 скринов
addr = getimage (0, 0, 500, 500, h) -- так быстрее чем вызов без указания хендла
end
log(os.clock()-t)
ОК.
Теперь про борьбу с рендерингом. Может кому пригодится. Даже используя стандартный Пилотовский findimage соблюдая два нехитрых правила результат поиска становится стабильнее и точнее.
1) На рендеринг (прорисовку) любой картинки влияют соседние с ней ИЗМЕНЯЮЩИЕСЯ объекты. Поэтому захват нужной картинки надо производить по возможности дальше от таких объектов.
Например, есть текст, который надо захватить для сравнения с неким оригиналом, и над этим текстом вверху постоянно меняющееся изображение каких-либо объектов.
Предположим, что высота символов 12 пикселей. Осуществляйте захват не по всей высоте текста, а сместите верхнюю границу зону захвата на 2-3 (а возможно и больше) пикселя ниже.
Грубо говоря скрин будет размером не 40х12, а скажем 40х10. Картинка конечно смотрится неприглядно, но идентифицировать её будет проще, так как подверженные влиянию верхние пиксели мы отбросим, кстати границы объектов всегда наиболее подвержены рендерингу.
2) Сильно может влиять положение рабочего окна, поэтому лучше чтобы рабочее окно всегда находилось на "своём привычном месте", я его устанавливаю при помощи set windowpos ...
Мне на 100% избежать влияния рендеринга удаётся не всегда, но в таких случаях у меня есть 2-3 (ничто не мешает сделать и больше) эталонных файла картинки. Имена файлов эталонов содержат номер события, поэтому все они легко распознаются в соответствии с событием (0001.jpg; 0002-a.jpg; 0002-b.jpg; и т.д.). Размеры файлов варьируются очень сильно, поэтому в подавляющем большинстве случаев, опознание производится по размеру файлов не прибегая к открытию файлов и их сравнению.
Кстати можно хранить содержимое файлов эталонов в памяти, да и сам список файлов тоже. Никаких тормозов в принципе быть не должно, хотя у меня и внешняя программа пашет на ура.
Конечно если картинки очень сложные, то спасёт только deviation Пилотовского имиджа, тут без вариантов. Ну или надо напрячь серое вещество и работать колором.
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf,h)
-- addr,len : адрес в памяти и длина строки в памяти (то, что даёт getimage)
-- scrX1,scrY1 : координаты скрина, аналогичны координатам getimage (конечные X и Y не требуются)
-- fx1,fy1,fx2,fy2 : координаты поиска, абсолютные относительно рабочего окна (мне так удобнее). Должны быть внутри диапазона скрина.
-- usl : условие поиска "R(10-255) G(70-100) B(50) R-G[50 200] R-B[-40 -20] G-B[15]"
-- условие ОДНО, по принципу ужесточения параметров поиска. R-G - разность между каналами с возможностью интервала
-- G-B[15] идентично G-B[15 255]
-- никакой проверки лексики естественно нет
-- numf : количество искомых пикселей
-- h : хендл пилота
local _,_,r1,r2 = usl:find("R%((%d+)%-*(%d*)")
local _,_,g1,g2 = usl:find("G%((%d+)%-*(%d*)")
local _,_,b1,b2 = usl:find("B%((%d+)%-*(%d*)")
local _,_,RG1,RG2 = usl:find("R%-G%[(%-*%d+)%s*(%-*%d*)")
local _,_,RB1,RB2 = usl:find("R%-B%[(%-*%d+)%s*(%-*%d*)")
local _,_,GB1,GB2 = usl:find("G%-B%[(%-*%d+)%s*(%-*%d*)")
r1=tonumber(r1) r2=tonumber(r2)
g1=tonumber(g1) g2=tonumber(g2)
b1=tonumber(b1) b2=tonumber(b2)
RG1=tonumber(RG1) RG2=tonumber(RG2)
RB1=tonumber(RB1) RB2=tonumber(RB2)
GB1=tonumber(GB1) GB2=tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
local r,g,b=0,0,0
local arr,ss,k,numbyte,pos={},"",0,255,(fx1-scrX1)*3 -- pos - количество первых байтов в строке памяти не требующих анализа
if len<253 then
local rgb=1
local ind=addr+(fy1-scrY1)*len+pos -- начальный индекс в памяти для считывания данных
local maxind=addr+(fy2-scrY1)*len+(fx2-scrX1+1)*3-1 -- конечный индекс в памяти для считывания данных
local x,y,j=fx1,fy1,1
while ind<=maxind do
numbyte=math.min(255,maxind-ind+1) -- количество байт для очередной итерации считывания из памяти
ss=readmem(ind,"s",numbyte,h)
ind,j=ind+numbyte,1
while j<=numbyte do
if x>=fx1 and x<=fx2 then
if rgb==1 then b=string.byte(ss,j) end
if rgb==2 then g=string.byte(ss,j) end
if rgb==3 then
r=string.byte(ss,j)
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
k=k+1 arr[k]={} arr[k][1]=x arr[k][2]=y arr[k][3]=r arr[k][4]=g arr[k][5]=b
if numf<=k then return arr end
end
end
end
j,pos=j+1,pos+1
if rgb<3 then rgb=rgb+1 else rgb,x=1,x+1 end
if pos==len then pos,y,rgb,x=0,y+1,1,scrX1 end
end
end
else
local numreed=math.ceil((fx2-fx1+1)*3/255)
local ost=math.fmod((fx2-fx1+1)*3,255)
for i=fy1,fy2 do
local ind=addr+(i-scrY1)*len+pos
local x=fx1
for s=1,numreed do
if s==numreed then numbyte=ost else numbyte=255 end
ss=readmem(ind,"s",numbyte,h)
for j=1,numbyte,3 do
b=string.byte(ss,j)
g=string.byte(ss,j+1)
r=string.byte(ss,j+2)
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
k=k+1 arr[k]={} arr[k][1]=x arr[k][2]=i arr[k][3]=r arr[k][4]=g arr[k][5]=b
if numf<=k then return arr end
end
x=x+1
end
ind=ind+numbyte
end
end
end
return arr
end
log "clear" log "mode compact"
local x1,y1,x2,y2=49,100,551,941
local address, w, h, len = getimage (x1, y1, x2, y2)
local handle = windowhandle()
local bmp={}
bmp=FindRGB (address, len, x1, y1, 49,700,51,901,"R(0-255)",20000,handle)
deleteimage(address)
for i=1, #bmp do
log(table.concat(bmp[i], " ")) -- вывод массива в лог
end
Круто, я так не умею, не знаю как.
Эх, если бы за один присест получить доступ к памяти, то вообще бы не было вопросов.
А может Кнайт всё-таки сделает колор инструментом №1.
Спасибо Дарк. Я не знал про переменные. В Паскале это вроде влияло только на размер дебуггера. Хотя всё равно тормоз - reedmem.
Спасибо на добром слове Дарк. Примерно я понимаю. Это раньше за каждый байт и даже бит "бились". Я работал на Искре-1030 (512 кб оперативки, 10 МБ разбитый на 5 лог. дисков винт) приходилось некоторые участки кода на ассемблере писать. А сейчас ... кто на чём будет экономить? Памяти - дохренища, винт - солид + РАМ гиг на 16. Прогресс не умолим, я отстал от него неотвратимо. Помню теоретические выкладки о пороге частоты в 1 гигагерц, вот смешно сейчас.
Да ещё и в очередь, 286 машинка стоила тогда более 50 000, не один жигуль можно было купить. Помню как кто-то сказал ... а Нортон то синий, на монохроме мы сидели. Но тогда было интереснее, сейчас все "зажрались".
Да и игры заточены только на выманивание денег - интеллекта - нуль целых, хрен десятых. Вот мы и будем кликать Кнайтовским Пилотом.
Не поленился и потестил чутка некоторые вещи.
local ss=""
local handle=windowhandle()
local tmm = os.clock()
for i=1,100000 do ss=readmem(address,"s",255,handle) end
log(os.clock()-tmm) -- Время теста 15.511 - 16.245 секунд
Меняем строку цикла
ss=readmem(address,"s",1,windowhandle())
Время теста 30.214 - 30.931 секунд
tmm = os.clock()
for i=1,200 do bmp=FindRGB (address, len, x1, y1, x2, 49,402,51,901,"R(0-255)",20000) end
log(os.clock()-tmm)
--Время теста 16.083 - 16.153 секунд (ровно 100000 вызовов reedmem)
local tmm = os.clock()
for i=1,50000 do bmp=FindRGB (address, len, x1, y1, x2, 41,900,51,901,"R(0-255)",20000) end
log(os.clock()-tmm) -- Время теста 24,215
Тот же тест, но я убрал из функции local handle=windowhandle() поместив его в тело скрипта
Время теста 16.151
Вывод очевиден всё родное даже не подлежит тестированию, потому что любая внешняя функция кушает несопоставимо больше.
Следовательно нужно стремиться к минимизации вызовов внешних функций, остальное в расчёт можно не брать.
Опять же без разницы что там выполняет внешняя функция, чисто сам факт её вызова приводит lua в ступор.
Вот что значит программировать за кружкой пива.
Надо так
local maxind=addr+(fy2-scrY1)*len+(fx2-scrX1+1)*3-1 -- конечный индекс в памяти для считывания данных
А было так
local maxind=addr+(fy2-scrY1+1)*len-(scrX2-fx2)*3-1 -- конечный индекс в памяти для считывания данных
Как я мог такую дурь придумать, параметр scrX2 вообще не нужен. И логически дурь и практически дурь. Хендл передаю теперь параметром в функцию. Вроде работает, пока чего-нибудь не вылезет.
Что-то я опять застрял. Как hint с параметрами вызывать? Типа с размером шрифта.
У меня не получилось... Более того там остались паразитные преобразования параметров судя по всему. Фикс нужен.
hint ([fontSize fontColor [posX posY [width height]]] (any text))
не соответсвует реальности в lua. Скобки можно кстати вообще опустить - они не нужны ни в одном из синтаксисов - кавычек должно быть достаточно, тем не менее ломать пилотовский, думаю, не стоит. В луа просто принять за текст последний из переданных параметров, скобки опустить - текст в любом случае будет последним.
пилотовский синтаксис:
hint ("123")
(0): Ошибка! Проварьте правильность скрипта! EIntOverflow Integer overflow hint ("123")
Где-то что-то пошло не так
Без параметров у меня работает.
hint ("СДВИГ РАВЕН : ",ControlShift)
Ну так вопрос вроде был, как с параметрами вызвать)
Без параметров есть какие-то проблемы не в lua вызове. Раньше можно было в некоторых операторах все задать в виде одной строки и тогда вызывался парсинг параметров из пилотовского синтаксиса. Тут так не получилось, решил просто сменить синтаксис и проверить. Резльтат выше
Дарк, спасибо, разобрался с ридмемом, вроде всё работает. Но вопрос у меня есть. Ходил на ссылочку которую ты дал по использованию СИ структур. Вопрос собственно вот в чём, можно и если можно то как описать структуру из 5-ти элементов {x, y, red, green, blue}
В примере так, но мне тут не всё понятно
local ffi = require("ffi")
ffi.cdef[[
typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;
]]
uint8_t - это что-то типа 8 бит?
rgba_pixel - а это зарезервированный тип или просто имя структуры?
local img = ffi.new("rgba_pixel[?]", n)
Это в примере инициализация, я правильно понял, что n - это заранее объявленный размер массива?
rgba_pixel[?] - а вот про знак вопроса - это не совсем понял.
В моём случае x и y должны быть естественно типа word.
И смогу я из функции вернуть такой массив в массив lua.
И есть ли смысл городить такой огород. Я попробовал, чтение действительно происходит мгновенно. Тормоза (хотя конечно и не критические) происходят именно при инициализации значений результирующего массива. Инициализация массива в 2 435 403 элементов осуществляется 3-4 сотых секунды. Конечно мне такие огромные не понадобятся, просто всегда хочется сделать по максимуму.
А вообще не трать время Дарк, всё и так просто летает, вызов моего файнда, затрачивает на 28000 элементов массива найденных пикселей 1 тысячную секунды. Для меня результат более чем ... Просто раньше стремился минимизировать вызовы файнда, поэтому и массивы результирующие были побольше, теперь ридмем выполняется мгновенно, следовательно можно крутить файндом сколько угодно. Спасибо тебе огромное Дарк, такую проблему помог решить.
Если кому надо пользуйтесь, может ошибки найдёте.
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- Функция поиска RGB в области памяти
-- addr,len : адрес в памяти и длина строки в памяти (те, что даёт getimage)
-- scrX1,scrY1 : координаты верхнего левого угла скрина в памяти, аналогичны координатам getimage (конечные X и Y не требуются)
-- fx1,fy1,fx2,fy2 : координаты поиска, абсолютные относительно рабочего окна. Обязательно должны быть внутри диапазона скрина.
-- usl : условие поиска ОДНО, по принципу ужесточения параметров "R(0-255) G(70-90) B(50) R-G[10 80] R-B[-40 -20] G-B[15]" (G-B[15] идентично G-B[15 255]
-- разность между каналами с возможностью интервала)
-- numf : максимальное количество искомых пикселей
local rmem = require "ffi".cast
local _,_,r1,r2=usl:find("R%((%d+)%-*(%d*)") r1,r2=tonumber(r1),tonumber(r2) -- Получение синтаксических значений поиска по каналу RED
local _,_,g1,g2=usl:find("G%((%d+)%-*(%d*)") g1,g2=tonumber(g1),tonumber(g2) -- Получение синтаксических значений поиска по каналу GREEN
local _,_,b1,b2=usl:find("B%((%d+)%-*(%d*)") b1,b2=tonumber(b1),tonumber(b2) -- Получение синтаксических значений поиска по каналу BLUE
local _,_,RG1,RG2=usl:find("R%-G%[(%-*%d+)%s*(%-*%d*)") RG1,RG2=tonumber(RG1),tonumber(RG2)
local _,_,RB1,RB2=usl:find("R%-B%[(%-*%d+)%s*(%-*%d*)") RB1,RB2=tonumber(RB1),tonumber(RB2)
local _,_,GB1,GB2=usl:find("G%-B%[(%-*%d+)%s*(%-*%d*)") GB1,GB2=tonumber(GB1),tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
local arr,k,indY,ind,r,g,b={},0
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
b=rmem("unsigned char*", ind)[0]
g=rmem("unsigned char*", ind+1)[0]
r=rmem("unsigned char*", ind+2)[0]
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
k=k+1 arr[k]={} arr[k][1]=j arr[k][2]=i arr[k][3]=r arr[k][4]=g arr[k][5]=b
if numf<=k then return arr end
end
end
end
return arr
end
arr[k][1]=j arr[k][2]=i arr[k][3]=r arr[k][4]=g arr[k][5]=b
arr[k]={j, i, r, g, b}
local function b() -- аналогично для других каналов
return rmem("unsigned char*", ind)[0]
end
Спасибо, буду постепенно, шаг за шагом учиться правильно программировать. Хотя, как я уже говорил, тормоза проявляются только при инициализации элементов массива. Поэксперементирую потом, как влияет на скорость.
Будет время на досуге покажи мне хотя бы усеченный вариант на 2-х каналах, как это обрабатывать таблицей. Я обязательно глобально протестирую все варианты и обязательно поделюсь результатами. Конечно результаты сильно зависят от проца, но хотя бы относительная разница по времени даст понятие. У меня конечно старенький проц (i7-4930K), но уж теперь другого не будет, в принципе не самый плохой, вроде устраивает.
local function rmem()
...
end
local function g()
rmem(params)
end
a = g()
local usl = {r1=10, g1=12}
FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf)
r1 = usl.r1 or 0 -- если usl.r1 задан, то он останется, если не задан, то задаст 0.
g1...
b1...
Уменьшение параметров прироста производительности не даёт : arr[k]={j, i, color}
local ffi = require "ffi" -- в шапку.
local params = ffi.new("uint8_t[10]")
params[0] = 11
params[1] = 5
params[2] = params[0] + params[1]
log (params[2])
В любом случае, "внешних" функций нет и результат на лицо, конечно если "вылизать" получится супер-пупер!
Но без вашей помощи мне не вылизать.
params[0] - это ваши r1, r2 и т.д.
Тут подставить по сути осталось =)
local rmem = require "ffi".cast
это из тела функции лучше вынести в самый верх скрипта.
local ffi = require "ffi" -- в шапку.
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- Функция поиска RGB в области памяти
-- addr,len : адрес в памяти и длина строки в памяти (те, что даёт getimage)
-- scrX1,scrY1 : координаты верхнего левого угла скрина в памяти, аналогичны координатам getimage (конечные X и Y не требуются)
-- fx1,fy1,fx2,fy2 : координаты поиска, абсолютные относительно рабочего окна. Обязательно должны быть внутри диапазона скрина.
-- usl : условие поиска ОДНО, по принципу ужесточения параметров "R(0-255) G(70-90) B(50) R-G[10 80] R-B[-40 -20] G-B[15]" (G-B[15] идентично G-B[15 255]
-- разность между каналами с возможностью интервала)
-- numf : максимальное количество искомых пикселей
local rmem = require "ffi".cast
local params = ffi.new("uint8_t[10]") -- сколько переменных не считал. 10 при необходимости поменяете.
local _,_,params[0],params[1]=usl:find("R%((%d+)%-*(%d*)") r1,r2=tonumber(r1),tonumber(r2) -- Получение синтаксических значений поиска по каналу RED
ОК. Спасибо, попробую.
Дарк и "сочини" инициализацию СИ-шного массива, тормоза то ИМЕННО на нём. На досуге разумеется. Конечно это актуально только при поиске всех пикселей на большой зоне захвата. Конечно такое вряд ли потребуется, но если будет СИ-й массив - это сделает функцию абсолютно универсальной без потерь скорости.
А зачем его создавать? Его же getimage создает, а мы фактически его перебираем.
Вообще я хз что там можно сочинить... На 1 000 000 000 элементов (гигабайт почти) у меня уходит 0.46 сек, на 2 400 000 уходит 0.001 примерно(иногда больше, иногда вообще 0 показывает).
Ну или я не понял чего-то, или ты меня не понял. Я имею ввиду операцию присваивания arr[k]={j,i,r,g,b} - именно этот оператор является признаком тормозов на 99%.
Вот нужно, чтобы он был СИ-шным.
Размер arr как-то регламентирован? Допустимо ли его задать жестко?
В том то и фишка, что нет - это массив найденных пикселей, конечно можно задать по максимально возможному по переменным fx1,fy1,fx2,fy2
Использовано на практике может быть любое количество совпадений? Например, я не представляю себе ситуацию, когда будет использовано хотя бы 100 совпадений по findimage, не говоря уже о миллионах =)
Просто учитывая определенную тормознутость выделения памяти это может быть узким местом, если выделять лишнюю. В противном случае нужно прикручивать массив в котором будут содержаться указатели на другие массивы. В рамках луа возникнет много вопросов.
local t = os.clock()
ffi.cdef[[
typedef struct { uint16_t x; uint16_t y; uint8_t red; uint8_t green; uint8_t blue; } rgba_pixel;
]]
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf)
local arr = ffi.new("rgba_pixel[?]", (fx2 - fx1)*(fy2-fy1) )
....
....
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
arr[k].x=j arr[k].y=i arr[k].red=r arr[k].green=g arr[k].blue=b
Спасибо, вот это я и хотел, попробую, хотя сегодня уже башка не варит, ну если не сегодня, то завтра потестирую.
Мне на самом деле очень интересно, что по скорости получится.
Произвел синтетический тест. Результаты местами неожиданные.
1) Время выполнения операций межу си типом и lua типом меньше, чем между одинаковыми си типами.
Скорее всего при сложении производится конвертация обоих параметров в double, в double же производится вычисление и потом конвертится обратно. При этом должна теряться точность целочисленных вычислений, что плохо(очень).
Косвенно в пользу этой версии говорит то, что сложение long double и lua переменной оказалось невозможно(сохранение производилось в long double).
Так же за эту версию говорит результат сложения двух double. Время практически идентичное сложению lua.
2) uint32_t / unsigned int. Просто какой-то дикий невероятный тормоз, которому я не могу вообще никакого оправдания придумать. u_int64_t и unsigned long long int идут с минимальным отставаением. При этом знаковые 64 битные вычисления оказываются быстрее беззнаковых 32 битных (хоть и не на много). Т.е. если нам нужно хранить число которое не помещается в int, но помещается в unsigned int, то для быстродействия лучше использовать не unsigned int, a long long int. Как? Жесть какая-то. При этом в double 52 бита отведены под целочисленные значения. Там даже привидения типа как такового быть не должно. Ужас...
3) Вычисления на чистом lua. Скорость вычислений слабенькая. Этого по сути и следовало ожидать - операции с плавающей запятой всегда были не очень шустрыми, сейчас вроде получше, но камушек у меня древний. Минимальное отставание от double - видимо какие-то накладные расходы есть (возможно при обращении к массиву). А вот инициализация поистине медленная - дикое отставание от всего, плюс согласно данным luajit.org там идет огромный оверхед по памяти, чем легко можно объяснить время инициализации.
В целом могу оценить результаты кроме unsigned int вполне логичные.
print = log
print "clear"
print "mode compact"
local ffi = require "ffi" -- в шапку.
local t, t2 = nil, nil
local count = 1024*1024*1000
--local count = 1
local data_type ={
{"int8_t"},
{"char"},
{"uint8_t"},
{"unsigned char"},
{"int16_t"},
{"short"},
{"uint16_t"},
{"unsigned short"},
{"int32_t"},
{"int"},
{"long int"},
{"uint32_t"},
{"unsigned int"},
{"unsigned long int"},
{"int64_t"},
{"long long int"},
{"uint64_t"},
{"unsigned long long int"},
{"float"},
{"double"},
}
local my_var = random(10) + 1
for i = 1, #data_type do
type = data_type[i][1]
log(type)
-- Время присвоения одного элемента статического массива
local arr = ffi.new(type.."[".. count / 1000 .."]")
t = os.clock()
for j = 1, 1000 do
for i = 0, count / 1000 - 1 do
arr[i] = my_var
end
end
t2 = (os.clock() - t)
data_type[i][2] = t2
--Время сложения двух элементов статического массива
arr[0] = random(10) + 1
t = os.clock()
for j = 1, 1000 do
for i = 0, count / 1000 - 1 do
arr[i] = arr[i] + arr[0]
end
end
t2 = (os.clock() - t)
data_type[i][3] = t2
--Время сложения элемента статического массива и переменной lua
t = os.clock()
for j = 1, 1000 do
for i = 0, count / 1000 - 1 do
arr[i] = arr[i] + my_var
end
end
t2 = (os.clock() - t)
data_type[i][4] = t2
arr = nil
end
-- pure lua
for i = 1, 1 do
local data_type = {{}}
data_type[i][1] = "lua"
type = data_type[i][1]
log(type)
-- Время присвоения одного элемента статического массива
local arr = nil
t = os.clock()
for j = 1, 1000 do
arr = {}
for i = 1, count / 1000 do
arr[i] = my_var
end
end
t2 = (os.clock() - t)
data_type[i][2] = t2
--Время сложения двух элементов статического массива
arr[1] = random(10) + 1
t = os.clock()
t = os.clock()
for j = 1, 1000 do
for i = 1, count / 1000 do
arr[i] = arr[i] + arr[1]
end
end
t2 = (os.clock() - t)
data_type[i][3] = t2
-- data_type[i][3] = " - "
--Время сложения элемента статического массива и переменной lua
t = os.clock()
for j = 0, 1000 do
for i = 1, count / 1000 do
arr[i] = arr[i] + my_var
end
end
t2 = (os.clock() - t)
data_type[i][4] = t2
arr = nil
log (" type init sumC sumLua")
log(string.format("%-27s: %.3f %.3f %.3f", unpack(data_type[i])))
end
for i = 1, #data_type do
log(string.format("%-27s: %.3f %.3f %.3f", unpack(data_type[i])))
end
t = os.clock()
for i = 0, count do
end
t2 = (os.clock() - t)
log("Время перебора пустого for : " .. string.format("%.3f",t2))
log ("")
log ("done.")
тип данных инициализация сложение с массивом того же типа сложение с lua массивом
type init sumC sumLua
lua : 16.324 3.161 3.192
int8_t : 0.653 0.682 0.653
char : 0.650 0.675 0.650
uint8_t : 0.648 0.678 0.650
unsigned char : 0.650 0.678 0.651
int16_t : 0.660 0.690 0.665
short : 0.660 0.704 0.669
uint16_t : 0.660 0.691 0.669
unsigned short : 0.660 0.689 0.676
int32_t : 1.463 1.481 1.463
int : 1.468 1.486 1.550
long int : 1.442 1.474 1.483
uint32_t : 1.445 2.505 1.673
unsigned int : 1.446 2.502 1.676
unsigned long int : 1.448 2.503 1.678
int64_t : 3.127 3.214 3.167
long long int : 3.113 3.178 3.173
uint64_t : 3.131 3.206 3.183
unsigned long long int : 3.119 3.174 3.241
float : 1.449 1.905 1.635
double : 3.103 3.126 3.152
Время перебора пустого for : 0.322
type init sumC sumLua
lua : 4.458 0.625 0.541
int8_t : 0.266 0.344 0.343
char : 0.284 0.353 0.329
uint8_t : 0.265 0.469 0.328
unsigned char : 0.266 0.468 0.328
int16_t : 0.266 0.359 0.468
short : 0.282 0.359 0.469
uint16_t : 0.286 0.355 0.339
unsigned short : 0.269 0.370 0.340
int32_t : 0.281 0.344 0.343
int : 0.282 0.359 0.344
long int : 0.281 0.468 0.328
uint32_t : 0.282 0.953 0.843
unsigned int : 0.265 0.929 0.859
unsigned long int : 0.281 0.938 0.849
int64_t : 0.578 0.734 0.656
long long int : 0.578 0.734 0.687
uint64_t : 0.578 0.735 0.656
unsigned long long int : 0.563 0.734 0.656
float : 0.281 0.594 0.491
double : 0.312 0.500 0.485
Время перебора пустого for : 0.231
Правильность поиска пока не проверял, потестил чисто на скорость. Прирост более чем в 10 раз, точнее 11,8. На моём камушке 50 000 000 пикселей в секунду.
Скрин 900х900, получаю весь массив за 16 тысячных, результат более чем приемлемый.
type init sumC sumLua
lua : 7.750 1.040 1.107
int8_t : 0.380 0.676 0.648
char : 0.372 0.703 0.620
uint8_t : 0.358 0.641 0.659
unsigned char : 0.363 0.655 0.686
int16_t : 0.387 0.665 0.620
short : 0.407 0.630 0.663
uint16_t : 0.375 0.659 0.621
unsigned short : 0.405 0.653 0.621
int32_t : 0.414 0.663 0.688
int : 0.373 0.691 0.632
long int : 0.392 0.656 0.694
uint32_t : 0.381 2.270 1.083
unsigned int : 0.416 2.285 1.144
unsigned long int : 0.376 1.436 1.051
int64_t : 0.897 1.352 1.062
long long int : 0.878 1.311 1.107
uint64_t : 0.931 1.354 1.134
unsigned long long int : 0.960 1.279 1.081
float : 0.391 1.290 0.958
double : 0.439 0.729 0.762
Время перебора пустого for : 0.355
Ну в общем чего я так интуитивно боялся, то и происходит. Проблема в совместимости СИ-шных и LUA-шных структур. Причём вешает LUA наглухо, только перезагрузка Пилота.
--lua
local ffi = require "ffi"
ffi.cdef[[
typedef struct { uint16_t x; uint16_t y; uint8_t red; uint8_t green; uint8_t blue; } rgba_pixel;
]]
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- Функция поиска RGB в области памяти
-- addr,len : адрес в памяти и длина строки в памяти (те, что даёт getimage)
-- scrX1,scrY1 : координаты верхнего левого угла скрина в памяти, аналогичны координатам getimage (конечные X и Y не требуются)
-- fx1,fy1,fx2,fy2 : координаты поиска, абсолютные относительно рабочего окна. Обязательно должны быть внутри диапазона скрина.
-- usl : условие поиска ОДНО, по принципу ужесточения параметров "R(0-255) G(70-90) B(50) R-G[10 80] R-B[-40 -20] G-B[15]" (G-B[15] идентично G-B[15 255] - разность
-- между каналами с возможностью интервала)
-- numf : максимальное количество искомых пикселей
local rmem = require "ffi".cast
local n=(fx2 - fx1+1)*(fy2-fy1+1) -- если будет работать, сделать минимум по параметру numf
local arr = ffi.new("rgba_pixel[?]", n )
local _,_,r1,r2=usl:find("R%((%d+)%-*(%d*)") r1,r2=tonumber(r1),tonumber(r2) -- Получение синтаксических значений поиска по каналу RED
local _,_,g1,g2=usl:find("G%((%d+)%-*(%d*)") g1,g2=tonumber(g1),tonumber(g2) -- Получение синтаксических значений поиска по каналу GREEN
local _,_,b1,b2=usl:find("B%((%d+)%-*(%d*)") b1,b2=tonumber(b1),tonumber(b2) -- Получение синтаксических значений поиска по каналу BLUE
local _,_,RG1,RG2=usl:find("R%-G%[(%-*%d+)%s*(%-*%d*)") RG1,RG2=tonumber(RG1),tonumber(RG2)
local _,_,RB1,RB2=usl:find("R%-B%[(%-*%d+)%s*(%-*%d*)") RB1,RB2=tonumber(RB1),tonumber(RB2)
local _,_,GB1,GB2=usl:find("G%-B%[(%-*%d+)%s*(%-*%d*)") GB1,GB2=tonumber(GB1),tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
local k,indY,ind,r,g,b=0
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
b=rmem("unsigned char*", ind)[0]
g=rmem("unsigned char*", ind+1)[0]
r=rmem("unsigned char*", ind+2)[0]
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
k=k+1 arr[k].x=j arr[k].y=i arr[k].red=r arr[k].green=g arr[k].blue=b
if numf==k then return arr end
end
end
end
return arr
end
log "clear" log "mode compact"
local addr, width, height, len = getimage (0, 0, 9, 9)
local vi={}
tmm = os.clock()
for i=1, 300 do
vi=FindRGB(addr,len,0,0,0,0,9,9,"R(0-255)",10000000)
end
log(os.clock()-tmm)
deleteimage(addr)
log(#vi) -- ошибка, если заремарить - ошибка закрытия lua
set timer3
set %arr[1 1] #WR // рабочее окно
save_array %arr "a:\_find.txt" // на RAM
start_script 8 wait // вызов 2-х файндов, более сотни ифов и собственно getimage
load_array %res "a:\_res.txt"
set #res1 %res[1 1]
set #res2 %res[1 2]
set #res3 %res[1 3]
set #tmp timer3
hint (28 (#res1 #res2 #res3 Время : #tmp)) // 19 - 26 тысячных
Дарк, собственно меня и старый вариант устраивает, так что если и не получится, я не расстроюсь.
Перевёл ещё один "хитрый" блок на lua, всё чудно работает, теперь не думаю про дополнительные операторы (if и for). Усилил логику за счёт добавления ифов и форов и за счёт расширения диапазона проверок и количества вызова файнда, всё мгновенно и точно на 100%. Как и обещал, да хоть блоху. Улучшился анализ временнЫх параметров, по факту время тратится только на getimage. Но за один такой вызов "высасываю" максимум возможного, да ещё и с предсказанием дальнейших действий.
print = log
print "clear"
print "mode compact"
local ffi = require "ffi"
local rmem = ffi.cast
ffi.cdef[[
typedef struct { uint16_t x; uint16_t y; uint8_t red; uint8_t green; uint8_t blue; } rgba_pixel;
]]
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- Функция поиска RGB в области памяти
-- addr,len : адрес в памяти и длина строки в памяти (те, что даёт getimage)
-- scrX1,scrY1 : координаты верхнего левого угла скрина в памяти, аналогичны координатам getimage (конечные X и Y не требуются)
-- fx1,fy1,fx2,fy2 : координаты поиска, абсолютные относительно рабочего окна. Обязательно должны быть внутри диапазона скрина.
-- usl : условие поиска ОДНО, по принципу ужесточения параметров "R(0-255) G(70-90) B(50) R-G[10 80] R-B[-40 -20] G-B[15]" (G-B[15] идентично G-B[15 255] - разность
-- между каналами с возможностью интервала)
-- numf : максимальное количество искомых пикселей
local n=(fx2 - fx1+1)*(fy2-fy1+1) -- если будет работать, сделать минимум по параметру numf
local arr = ffi.new("rgba_pixel[?]", n )
local _,_,r1,r2=usl:find("R%((%d+)%-*(%d*)") r1,r2=tonumber(r1),tonumber(r2) -- Получение синтаксических значений поиска по каналу RED
local _,_,g1,g2=usl:find("G%((%d+)%-*(%d*)") g1,g2=tonumber(g1),tonumber(g2) -- Получение синтаксических значений поиска по каналу GREEN
local _,_,b1,b2=usl:find("B%((%d+)%-*(%d*)") b1,b2=tonumber(b1),tonumber(b2) -- Получение синтаксических значений поиска по каналу BLUE
local _,_,RG1,RG2=usl:find("R%-G%[(%-*%d+)%s*(%-*%d*)") RG1,RG2=tonumber(RG1),tonumber(RG2)
local _,_,RB1,RB2=usl:find("R%-B%[(%-*%d+)%s*(%-*%d*)") RB1,RB2=tonumber(RB1),tonumber(RB2)
local _,_,GB1,GB2=usl:find("G%-B%[(%-*%d+)%s*(%-*%d*)") GB1,GB2=tonumber(GB1),tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
local k,indY,ind,r,g,b=-1
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
b=rmem("unsigned char*", ind)[0]
g=rmem("unsigned char*", ind+1)[0]
r=rmem("unsigned char*", ind+2)[0]
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
k=k+1
arr[k].x=j
arr[k].y=i
arr[k].red=r
arr[k].green=g
arr[k].blue=b
--k=k+1 arr[k].x=j arr[k].y=i arr[k].red=r arr[k].green=g arr[k].blue=b
if numf==k then return arr, k end
end
end
end
log(k)
return arr, k
end
log "clear" log "mode compact"
local addr, width, height, len = getimage (0, 0, 9, 9)
local vi, k={}
tmm = os.clock()
for i=1, 300 do
vi, k=FindRGB(addr,len,0,0,0,0,9,9,"R(0-255)",10000000)
end
log(os.clock()-tmm)
deleteimage(addr)
log(type(vi)) -- ошибка, если заремарить - ошибка закрытия lua
log(k)
log "done."
Спасибо, буду пробовать. Я просто многого не знаю, как всё это "фунциклирует", поэтому всё методом тыка.
Еще раз обращаю внимание на то, что это Сишный массив. Т.е. индекс первого элемента равен нулю. Возвращается не "размер"(k), а номер последнего индекса в массиве. Т.е. элементов у нас 100, но k вернет 99, т.к. записаны данные в индексах 0-99. Если есть желание можно сделать +1 в return, но есть ли в этом смысл не понятно, т.к. если будете работать с данным масивом то в первом же переборе нужно будет делать -1.
Дарк, извини меня, я тут немножко вспылил и начал права качать, на самом деле, спасибо тебе, что "возишься тут со мной", да ещё и за бесплатно.
На самом деле тема уже не актуальна. Поскольку ридмем не тормозит, лично у меня уже нет необходимости получать результат поиска файндом в виде массива. Улучшить можно, но только, как я уже говорил, теперь медленный только get, а эти "крохи" выигрыша в виде нескольких микросекунд погоды не делают. Ты помог решить вопрос, СПАСИБО, научил наперёд, СПАСИБО. Пока попробую сам поковыряться. В конце концов, у меня нет цели изучать СИ, я не собираюсь писать свой кликер, меня вполне устраивает Кнайтовский, за что и ему СПАСИБО!
ОК.
Меня больше заинтересовала возможность подлкючения dll'ок сишных напрямую без долбанных оберток луашных. Пока достижения правда не очень... В качестве примера попробовал загрузить и выполнить свою же дллку для работы с double из пилота, но подгрузив ее через ffi. ffi сказал гордо, что вызов таких функций, как в моей дллке пока еще не держит, но только пока. Что именно ему там не понравилось я хз. Zlib1 из обучалки прилинковался и даже работает. Тем не менее в первую очередь лично мне интересна возможность линковки qt или wxwidgets. Попробовал wx - не находит функции вроде как, хотя биндинг сделал. Идеи?
Заставил себя всё-таки ещё полопатить свой файнд. Результаты есть, удалось добиться ещё прироста в скорости почти в полтора раза. Скрипт подлатаю и выложу позже, на него сейчас без слёз не взглянешь. Но возникли вопросы.
Сишные переменные не прокатили в двух операторах, может опять чего не так делаю?
local _,_,r1,r2=usl:find("R%((%d+)%-*(%d*)")
r1,r2=tonumber(r1),tonumber(r2)
Обозвал их так: local s=ffi.new("uint8_t[9]")
Пришлось уже после их выполнения делать так:
s[0],s[1],s[2],s[3],s[4],s[5]=r1,r2,g1,g2,b1,b2
Возможно несовместимый тип, я так думаю.
local m=ffi.new("int16_t[6]")
m[0]=tonumber(r1)
log(m[0])
Да, вот так нормально, в общем надо ещё полопатить.
И то не факт, этот тип как я понял, только положительные значения. Надо наверное uint16 использовать.
И ещё вопрос. А не массивом, а обычными переменными как обозвать через ffi ?
И есть ли смысл? Может лучше массивом и оставить?
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
r1,r2=tonumber(r1),tonumber(r2)
local arr_uchar = ffi.new("unsigned char[10]", 2)
arr_uchar[0] = 1200
for i = 0, 9 do
log (arr_uchar[i], type(arr_uchar[i]))
end
--lua
function Find1(usl)
local _,_,r1,r2=usl:find("R%((%d+)%-*(%d*)")
local _,_,g1,g2=usl:find("G%((%d+)%-*(%d*)")
local _,_,b1,b2=usl:find("B%((%d+)%-*(%d*)")
local _,_,RG1,RG2=usl:find("R%-G%[(%-*%d+)%s*(%-*%d*)")
local _,_,RB1,RB2=usl:find("R%-B%[(%-*%d+)%s*(%-*%d*)")
local _,_,GB1,GB2=usl:find("G%-B%[(%-*%d+)%s*(%-*%d*)")
end
function Find2(usl)
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
end
log "clear" log "mode compact"
tmm = os.clock()
for i=1, 1000000 do
Find1("R(7-155)B(8-154)G(9-153)R-G[50 90]R-B[60 80]G-B[70 75]")
end
log(os.clock()-tmm) -- среднее 3,137 сек
tmm = os.clock()
for i=1, 1000000 do
Find2("R(7-155)B(8-154)G(9-153)R-G[50 90]R-B[60 80]G-B[70 75]")
end
log(os.clock()-tmm) -- среднее 2,829 сек
tmm = os.clock()
Попытка переделать блок инициализации в СИ-шные переменные потерпела фиаско. tonumber с СИ-шной переменной работает только если строка реально является числом (по крайней мере я так понял). Поэтому перед вызовом tonumber пришлось анализировать строки и это привело к падению производительности.
--lua
local ffi = require "ffi"
function Find1(usl)
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
r1,r2=tonumber(r1),tonumber(r2)
g1,g2=tonumber(g1),tonumber(g2)
b1,b2=tonumber(b1),tonumber(b2)
RG1,RG2=tonumber(RG1),tonumber(RG2)
RB1,RB2=tonumber(RB1),tonumber(RB2)
GB1,GB2=tonumber(GB1),tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
end
function Find2(usl)
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
local s=ffi.new("uint8_t[6]")
local m=ffi.new("int16_t[6]")
if r1==nil then s[0],s[1]=0,255
else
s[0]=tonumber(r1)
if r2=="" then s[1]=s[0] else s[1]=tonumber(r2) end
end
if g1==nil then s[2],s[3]=0,255
else
s[2]=tonumber(g1)
if g2=="" then s[3]=s[2] else s[3]=tonumber(g2) end
end
if b1==nil then s[4],s[5]=0,255
else
s[4]=tonumber(b1)
if b2=="" then s[5]=s[4] else s[5]=tonumber(b2) end
end
if RG1==nil then m[0],m[1]=-255,255
else
m[0]=tonumber(RG1)
if RG2=="" then m[1]=255 else m[1]=tonumber(RG2) end
end
if RB1==nil then m[2],m[3]=-255,255
else
m[2]=tonumber(RB1)
if RB2=="" then m[3]=255 else m[3]=tonumber(RB2) end
end
if GB1==nil then m[4],m[5]=-255,255
else
m[4]=tonumber(GB1)
if GB2=="" then m[5]=255 else m[5]=tonumber(GB2) end
end
end
log "clear" log "mode compact"
tmm = os.clock()
for i=1, 1000000 do
Find1("R(7-155)B(8-154)G(9-153)R-G[50 90]R-B[60 80]G-B[70 75]")
end
log(os.clock()-tmm) -- 3.480 сек. и 3.569 сек.
tmm = os.clock()
for i=1, 1000000 do
Find2("R(7-155)B(8-154)G(9-153)R-G[50 90]R-B[60 80]G-B[70 75]")
end
log(os.clock()-tmm) -- 4.774 сек. и 4.866 сек.
tmm = os.clock()
Точнее к падению производительности привело преобразование типов при выполнении tonumber.
--lua
local ffi = require "ffi"
local rmem = ffi.cast
ffi.cdef[[
typedef struct { uint16_t x; uint16_t y; uint8_t red; uint8_t green; uint8_t blue; } rgba_pixel;
]]
function FindRGBold(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf)
local n=math.min(numf,(fx2-fx1+1)*(fy2-fy1+1))
local arr = ffi.new("rgba_pixel[?]", n )
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
r1,r2=tonumber(r1),tonumber(r2)
g1,g2=tonumber(g1),tonumber(g2)
b1,b2=tonumber(b1),tonumber(b2)
RG1,RG2=tonumber(RG1),tonumber(RG2)
RB1,RB2=tonumber(RB1),tonumber(RB2)
GB1,GB2=tonumber(GB1),tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
local k,indY,ind,r,g,b=-1
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
b=rmem("unsigned char*", ind)[0]
g=rmem("unsigned char*", ind+1)[0]
r=rmem("unsigned char*", ind+2)[0]
if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then
k=k+1 arr[k].x, arr[k].y, arr[k].red, arr[k].green, arr[k].blue = j,i,r,g,b
if numf==k then return arr, k end
end
end
end
return arr, k
end
function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf)
local n=math.min(numf,(fx2-fx1+1)*(fy2-fy1+1))
local arr = ffi.new("rgba_pixel[?]", n )
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
r1,r2=tonumber(r1),tonumber(r2)
g1,g2=tonumber(g1),tonumber(g2)
b1,b2=tonumber(b1),tonumber(b2)
RG1,RG2=tonumber(RG1),tonumber(RG2)
RB1,RB2=tonumber(RB1),tonumber(RB2)
GB1,GB2=tonumber(GB1),tonumber(GB2)
if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end
if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end
if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end
if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end
if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end
if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end
local s,m=ffi.new("uint8_t[9]"),ffi.new("int16_t[6]")
s[0],s[1],s[2],s[3],s[4],s[5],m[0],m[1],m[2],m[3],m[4],m[5]=r1,r2,g1,g2,b1,b2,RG1,RG2,RB1,RB2,GB1,GB2
local k,indY,ind,r,g,b=-1
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
s[8]=rmem("unsigned char*", ind)[0]
s[7]=rmem("unsigned char*", ind+1)[0]
s[6]=rmem("unsigned char*", ind+2)[0]
if s[6]>=s[0] and s[6]<=s[1] and s[7]>=s[2] and s[7]<=s[3] and s[8]>=s[4] and s[8]<=s[5] and s[6]-s[7]>=m[0] and -- ПЕРЕНЕС УСЛОВИЕ. ФОРУМ ЛОМАЛО.
s[6]-s[7]<=m[1] and s[6]-s[8]>=m[2] and s[6]-s[8]<=m[3] and s[7]-s[8]>=m[4] and s[7]-s[8]<=m[5] then
k=k+1 arr[k].x,arr[k].y,arr[k].red,arr[k].green,arr[k].blue=j,i,s[6],s[7],s[8]
if numf==k then return arr, k end
end
end
end
return arr, k
end
function ImageToArray(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2)
local n=(fx2-fx1+1)*(fy2-fy1+1)
local arr = ffi.new("rgba_pixel[?]", n )
local s=ffi.new("uint8_t[3]")
local k,indY,ind,r,g,b=-1
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
s[2]=rmem("unsigned char*", ind)[0]
s[1]=rmem("unsigned char*", ind+1)[0]
s[0]=rmem("unsigned char*", ind+2)[0]
k=k+1 arr[k].x,arr[k].y,arr[k].red,arr[k].green,arr[k].blue=j,i,s[0],s[1],s[2]
end
end
return arr, k
end
log "clear" log "mode compact"
local addr, width, height, len = getimage (0, 0, 999, 999)
local vi, k={}
tmm = os.clock()
for i=1, 1000 do
vi,k=FindRGBold(addr,len,0,0,0,0,999,999,"G-B[0 255]",10000000)
end
log(os.clock()-tmm) -- 22.037 сек.
tmm = os.clock()
for i=1, 1000 do
vi,k=FindRGB(addr,len,0,0,0,0,999,999,"G-B[0 255]",10000000)
end
log(os.clock()-tmm) --15.357 сек.
tmm = os.clock()
for i=1, 1000 do
vi,k=ImageToArray(addr,len,0,0,0,0,999,999)
end
log(os.clock()-tmm) --7.139 сек.
И опять же, я же не зря потестил всё. Полноценный разбор строки составляет менее 300 микросекунд. Даже на дохлом камне и то это всё мгновенно будет, ну а Cirus-а вообще наверное всё должно летать. Хотя если научите, конечно сделаю и таблицей.
В принципе получилась замечательная вещь. Я переделал свой распознаватель текста и уверен, что могу сделать любой распознаватель, который с помощью вот такого файнда будет всё распознавать намного быстрее, чем делается getimage.
Вот если бы ещё и getimage через ffi прикрутить, вот это была бы суперскорость, только сдаётся мне что получить доступ к окну быстро всё равно не получится, наверняка всё делается как обычно через "третьи" руки, а значит однозначно тормоза.
function FindRGBold(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf)
local n=math.min(numf,(fx2-fx1+1)*(fy2-fy1+1))
local arr = ffi.new("rgba_pixel[?]", n )
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
end
-- Usl у нас теперь таблица, а не строка.
-- Задаем только те параметры которые нужны.
-- Остальные можно дописать в теле таблицы умолчательными.
local usl = {r1=10, r2=12, GB2=32}
-- Объявление функции не меняется. Тело:
function FindRGBold(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf)
local r1 = usl.r1
local r2 = usl.r2
local g1 = usl.g1
local g2 = usl.g2
...
local GB2 = usl.GB2
local arr = {10,11,22} -- мы создали одномерный массив на 3 элемента. Это именно массив, находящийся одним неразрывным куском в памяти.
log (arr[1]) -- вывод первого элемента массива, отсчет с единицы.
local t = {first=10, second=11, third = 22} -- мы создали таблицу, которая размазана по памяти.
log (t.first) -- вывод первого элемента таблицы.
local r1 = usl.r1 or 10
if var 1 then
return var1
else
return var2
end
if var 1 then
return var2
else
return var1
end
local function fcolor(my_var)
local var = {n1=1, n2=2, n3=3, n4=4}
for k, v in next, my_var do -- Перебираем все ключи и значения таблицы t2
local var[k]=v -- Подменяем значение с таким же ключем.
end
end
local my_var = {n2=20, n3 = 30}
fcolor(my_var)
Скорость обработки порядка 40 кадров в секунду меня более чем устраивает. Перелопачивание массивов пикселей требовалось только при распознавании символов, но там требования к скорости были не критичны, хотя и в этом направлении результат получился супер. До сих пор пока ещё запускаю параллельный скрипт и то время выполнения менее 3 сотых сек. Так что пока наверное я остановлюсь на достигнутом. Надо скрипт переделывать на lua, а скрипт ой какой не хилый, думаю даже за месяц не управлюсь.
Не дождался я фикса на findimage, нацарапал свой, используя СИ-шные переменные. Ещё раз огромное спасибо Дарку. Доморощенный, без наворотов findimage работает примерно в 130 раз быстрее (100 раз искал картинку в цикле поиска 26 картинок - всего 0.009 сек). Кстати, у Кнайта скорость ОЧЕНЬ сильно зависит от параметра deviation, чем он больше, тем медленнее. А этот параметр я использую практически всегда. Мне не совсем понятно почему такая зависимость, видимо шибко хитрый и мудрёный алгоритм.
Всё-таки офигительную штуку подсказал мне Дарк. Раньше при многоступенчатом выборе тех или иных действий приходилось выставлять ожидание до 300 миллисекунд после клика, для гарантированной связи с сервером и отрисовки нового изображения на экране. Теперь сделал собственную функцию LeftWait, которая перед кликом запоминает определённую область экрана и после клика - ждёт обновления экрана, прежде чем вернуться в основное тело скрипта. Результат? Теперь всё просто "летает", ждёт ровно столько, сколь нужно.
А вообще сам виноват, нарушил прописную истину. Не городить огород, а потом долго выискивать ошибки, а сделал что-то новое - проверь сразу, и так шаг за шагом. А что получилось? Решил усовершенствовать код, уверенно так ... сразу много всего нового понаписАл и естественно стал грешить на новое, а ошибочка то была древнейшая, просто на условия возникновения ошибки никогда не попадал. Надо было в своё время погонять на всех режимах.
Дарк в своё время ткнул меня носом, что индексация массива начинается с нуля, вот тупо и поменял нолик на -1, а посмотреть весь код функции поленился, вот и результат, "как не надо на фиг делать".
В какой-то момент даже засомневался в себе, ну думаю всё - приплыли, рано радовался. Но всё-таки взял себя в руки, заставил спокойно сесть и просмотреть всё от начала до конца внимательнейшим образом. Рад, что помогло не везение и удача, а понимание истины - дыма без огня не бывает. Всегда есть причина, в чёрта я не верю.
Дарк, я тут забубенил свой файндимидж (я уже говорил). Решил проверить как будет работать на 1000+ картинок, вместо вызова внешней проги (которая джипеги смотрит). Пока толком не тестировал на скорость, но присобачил элемент самообучения. Идея такая, может тебе пригодится. У меня deviation не в %, а разности каналов RGB, с точностью до 1. Использую файл конфигурации, в который записывается этот deviation. Ищет например с нулевой погрешностью, если не находит картинку, увеличивает погрешность и так пока не найдёт картинку. Результат записывает в файл конфигурации и в дальнейшем использует именно эту погрешность. Смысл? Чем меньше погрешность, тем быстрее осуществляется поиск. На большом объёме картинок прирост уже проявляется. Раньше просто делал погрешность с запасом, теперь ровно такая, какая нужна.
Предположительно (когда все картинки соберу) скорость поиска будет максимум 2-3 сотых секунды, сопоставимо с той какая у меня сейчас, но есть плюс - алгоритм железобетонный, будет искать как надо со 100% вероятностью надёжного поиска.
Попробовал подключить модуль lua, ничего у меня не получилось.
Я хотел ВСЕ свои функции поместить в отдельный файл и как-то сделать их доступными из любой вкладки Пилота, чтобы не таскать их в каждую вкладку. И если что-то изменил в какой-либо функции - это "поняли" бы все скрипты, а то опять можно ошибок накрошить.
Грубо говоря без хотя бы простенького примера думаю не разберусь. 2 вопроса. Что нужно изменить в самом файле? Про ретурн уже понял. Но всё равно нужен примерчик. И как подцеплять типа require.
local my_func = {}
my_func.show = function()
...
end
my_func.hide = function()
...
end
return my_func
local f = require [[lua_plugins\my_func]]
f.show()
f.hide()
Спасибо Дарк за инфу. Пробовать буду завтра (точнее уже сегодня, но позже).
общая схема работы в моем понимании такова:
Пусть у нас дано изображение из 10 полезных пикселей.
Задна accuracy 90. Т.е. в нашем случае требуется совпадение не менее 9 пикселей.
Область дана в которой изображение может быть найдено в 20 наборах координат.
Финдимидж берет первую точку в заданной области и начинает попорядку сверять все 10 пикселей.
Как только количество допустмых ошибок превысит ограничение (у нас это 10-9=1), то происходит переход к следующей точке.
Справедливо и обратное, как только найдено 9 сопадений, то попытки найти 10 не будет - засчитается совпадение.
Таким образом, поскольку минимальное количество несовпадающих пикселей для позиции равно 2, а позиций у нас 20, то как минимум будет проверено 40 точек (при условии, что вообще нет никаких совпадений по цветам).
Допустим мы уменьшим параметр accuracy до 70. При этом количество ошибок должно быть не менее 4 (10-10*70%+1), чтобы изображение считалось не совпавшим. Позиций у нас все так же 20, но теперь количество проверок точек уже будет не менее 4*20=80. Вот таким не хитрым способом мы посадили производительность до двух раз.
Тем не менее очевидно, что у нас будут не только крайние случаи, но и частично совпавшее начало и отбраковка уже на середине. Напрмер, 3 пикселя в начале совпало, а только потом 4 уже были отбракованы.
Причем тут deviation? Дело в том, что при его задании мы повышаем шанс того, что отбраковка будет произведена только в середине/конце сравнения, а в начало за счет допустимых искажений влезут посторонние цвета принятые за корректные.
Да, 100
Возможно есть хитрые картинки, не знаю. Если картинки сильно плавают - ничего не поможет. В любом случае будут якоря.
Точнее у меня нет аккуратности, я просто анализирую заданную разность RGB.
--lua
local ffi=require "ffi" -- Использование модуля ffi для использования СИ структур
local rmem=ffi.cast -- Использование функции чтения из памяти модуля ffi
ffi.cdef[[typedef struct{uint16_t x,y; uint8_t red,green,blue;}xyrgb]] -- Определение структуры массива чтения данных из памяти образа картинки
local function ImageToArray(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2) -- ЧТЕНИЕ ВСЕХ ПИКСЕЛЕЙ В ОБЛАСТИ ПАМЯТИ
local n=(fx2-fx1+1)*(fy2-fy1+1) -- Определение максимальной размерности возвращаемого функцией СИ массива считанных пикселей
local arr=ffi.new("xyrgb[?]",n) -- Инициализация СИ массива искомых пикселей (используя ранее описанную структуру)
local s=ffi.new("uint8_t[3]") -- Инициализация СИ массива из 3-х элементов типа беззнаковый байт для чтения из памяти значений пикселей RGB
local k,indY,ind,r,g,b=-1
for i=fy1,fy2 do
indY=addr+(i-scrY1)*len
for j=fx1,fx2 do
ind=indY+(j-scrX1)*3
s[2]=rmem("unsigned char*",ind)[0]
s[1]=rmem("unsigned char*",ind+1)[0]
s[0]=rmem("unsigned char*",ind+2)[0]
k=k+1 arr[k].x,arr[k].y,arr[k].red,arr[k].green,arr[k].blue=j,i,s[0],s[1],s[2]
end
end
return arr,k
end
local function ImageCompare(pl,wl,hl,ll,pg,lg,x,y,fx1,fy1,fx2,fy2,dev)
local arl,arg,kl,kg={},{}
arl,kl=ImageToArray(pl,ll,0,0,0,0,wl-1,hl-1)
arg,kg=ImageToArray(pg,lg,x,y,fx1,fy1,fx2,fy2)
for i=0,kl do
if math.abs(arl[i].red-arg[i].red)>dev or math.abs(arl[i].green-arg[i].green)>dev or math.abs(arl[i].blue-arg[i].blue)>dev then
return 0
end
end
return 1
end
tmc=os.clock()
for j=1,100000 do
for i=1,19 do
if 1==ImageCompare(U[i],uw[i],uh[i],ul[i],p,l,455,915, 461,925,489,932, 153) then nnn=i break end
end
end
log(os.clock()-tmc) -- 9,424 сек.
log(nnn)
Ловить количество пикселей - очень рискованная идея. А вот такие вещи как будет отличать 1 или l (единица или L) особенно если посмотреть на их шрифт в том же Пилоте. Не пробовал, просто лень, но если ищет количество пикселей, то ни хрена не отличит.
И не только в Пилоте, гляньте на шрифт цитат...
А мой убогий алгоритм отличит железобетонно.
Думаю ты ошибаешься Дарк, если приоритет количество пикселей, тогда при поиске таких картинок "123" и "321" количество пикселей будет практически одинаковым. Сдаётся мне там более хитрый алгоритм.
Во всяком случае, чисто для борьбы с рендерингом достаточно параметра deviation. А вот если гамму отлавливать - это другая песня.
Кажется я понял какая была изначальная идея, искать картинки символов, на которые не рендеринг влияет, а сглаживание шрифтов. Ой, какая плохая идея. У меня совсем иная реализация, ну а если уж делать поиском картинок, тогда для каждого символа может потребоваться и 5 и может даже и больше картинок. Да, делать такие картинки муторно и время убьёшь, но за то со скоростью не будет проблем. Переделал свой финд, как и планировалось скорость выросла в 2 раза.
Кнайт, снимаю шляпу. Надо вывихнуть себе мозги, чтобы не дай бог у юзера что-нибудь не случилось с головой.
На мой вгляд (на перспективу, вдруг добьёшь компиляцию) надо сделать 2 раздельные функции, для неприхотливых сделать скромную SingleFind (скоростную) и не рекламировать её, просто пусть будет. А для всех остальных сделать функцию SmartFind.
Нет, не сингл, а SpeedFind.
Выбор чем пользоваться оставить за юзером.
Юзер попробует и сделает для себя вывод ... юзер он или лузер.
Подводя итог этой теме. У Кнайта фишка - это фон. Я же наоборот рассматриваю фон, как рабочий пиксель. При таком подходе хвост от Q ну никак не "проскочит" мимо. Теперь о минусах... Вот плавающие символы, вот тут да, мой алгоритм начнёт тупить, потому что та же единичка рисуется 2-3 мя палками. Одна тёмная, другая светлая и они в зависимости от знакоместа меняются местами (плавают). Тут я точно не могу сказать как лучше, использовать Кнайтовский финд или сделать несколько вариантов картинок для моего алгоритма (думаю 3-х вариантов будет достаточно).
Ну а для поиска реальных картинок, могу конечно ошибаться, но сколько не пробовал мой вариант однозначно ищет 100% и как минимум быстрее. Потому что у Кнайта использование deviation начинает очень сильно тормозить.
Сильно тормозить - это в разы, а не на 15-20%.
Не поленился ещё раз потестил:
tmc=os.clock()
local argg,kg=fn.ImageToArray(p,l,455,915,461,925,489,932)
for j=1,10000 do
for i=1,19 do -- картинки размером 29 х 8
if 1==ImageCompare(U[i],uwid[i],uhei[i],ulen[i],argg, 27) then nu=i break end
end
end
log(os.clock()-tmc) -- 0.477 сек.
local ar,err={}
tmc=os.clock()
local p1,w,h,l=getimage(461,925,489,932,ok[1][1])
for j=1,1000 do
for i=1,19 do -- картинки размером 29 х 8
ar,err=findimage(0,0,27,8,{U[i]},p1,100,1,0)
if err==100 then nk=i end
end
end
log(os.clock()-tmc) -- 5.628 сек (в 10 раз меньше картинок)
for j=1,1000 do
for i=1,19 do -- картинки размером 29 х 8
ar,err=findimage(0,0,27,8,{U[i]},p1,100,1,7)
if err==100 then nk=i end
end
end
log(os.clock()-tmc) -- 13.644 сек (в 10 раз меньше картинок)
0_big.bmp ( 66,05 килобайт )
Кол-во скачиваний: 138
Вот и что с одним deviaton тут делать? Вот эта вот радуга фактически может в любую сторону плавать. При комбинации с accuracy получается хотя бы проглатывать крайние положения.
Показательно в этом случае распознавание лиц. Там однозначно реперные точки. Алгоритмы тоже на протяжении десятков лет совершенствуются.
cross.bmp ( 361,22 килобайт )
Кол-во скачиваний: 132
Вот пример. Наложен фильтр оттенка. Примерно так видит в данном случае deviation.
В нашем случае шрифт известен. Сглаживание - это тоже алгоритм, для своего случая я его вычислил на 100%, не более 7 вариантов написания символа, в зависимости от соседних, рендеринг побеждается погрешностью. Никаких проблем не вижу. Так у меня ещё и текст центрированный, мне приходится искать и начало и конец текста. И всё работает. Поначалу много было неизвестных, но статистика собиралась, неизвестные варианты добавлялись. В lua проблем нет. Распознаватель на 5 страницах, но работает быстро.
Для текстов вроде ДА, даёт эффект аккуратность, для картинок наоборот, конечно можно также эпмирическим методом найти наилучший вариант для каждого случая, вот только как с потерей скорости??? В общем закрыли тему.
Обрати внимание достаточно анализ ОДНОЙ строки пикселей. Я точно знаю все варианты этой строки. Это я делал ещё для тормозного Пилота.
Дарк, я тут просто пробежался по темам форума, по вопросам и ответам. Что могу сказать, конечно не все зададут вопрос, но всё-таки, статистика - вещь неумолимая. Кто спросил как работает findimage? Как сделать быстрее? Как воспользоваться той или иной функцией? Вот лично я задавал вопросы по синтаксису, потому, что не знаю ничего, а люди то вообще спрашивают А КАК? Там проблемки поглубже, там не синтаксис, там основы программирования и алгоритмирования. И мы им прикрутим deviation и accurace? Надо так ... чем проще, тем лучше, а для особо одарённых просто менюшку "advanced" и мелким шрифтом и в 3-й уровень вложенности.
local arr, err = findimage(
x1,y1,x2,y2,
{[[path]]},
2, 90, 1, 4)
А вообще классная компания (чуть не сказал тусовка) собралась. Балом правит W(hite) Светлый Князь, Разруливает Тёмный Мастер. Незримое око у серого кардинала cirus (перевода не знаю). Ну и я в роли королевского шута (надеюсь мне простят мои шутки).
Анекдот из реальной жизни.
90-е годы. Формирование ЖКХ. Соседка встречает соседа и говорит
- Николай, за воду будем теперь платить отдельно.
Николай в ответ
- Какому на х..рен заводу?
В продолжение темы...
Жена мужу.
- Ты ребёнку на сок дал? (подразумевалось денег)
Ответ.
- Какой носок?
local cscrX,cscrY,cfx1,cfy1,cfx2,cfy2,cl=ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t")
Вроде допинал сравнение картинок. Убрал считывание картинки целиком в память. Считывается ровно столько, сколько необходимо. В нормальных ситуациях прирост по скорости несопоставимо быстрее. А вот если куча холостых сравнений, тогда может быть и хуже (но это уже вопрос, как правильно делать картинки). А ещё сделал возможность анализировать не все три канала RGB, а вплоть до одного. Если радуги нет, как в моём случае, скорость выростает ещё в 3 раза и всё работает как надо. Вроде удалось переплюнуть (только при правильных картинках) скорость моего джипеговского распознавателя. Всё-таки пока работал на Пилотовском языке - это был ПРОРЫВ, проверил его ещё раз досконально. Скорость его выполнения всего 15-20 миллисекунд и плюс его ещё и в том, что скорость не зависит от условий, сам алгоритм проверяет (отсекает) ВСЕ варианты картинок.
Огромный минус джипеговского, в том, что необходимо было тщательно выбирать зону картинок и всё равно бывают случаи, когда приходится делать несколько вариантов картинок (и следить за этим процессом), но проверяет он конечно очень быстро, джипеги друг от друга отличаются (в подавляющем большинстве случаев) практически на первых же байтах. В общем переплюнул всё-таки, перехожу на нормальное сравнение картинок.
local function my_func() end -- прототип функции
do -- создаем карман namespace, аналогичный while, for, function
local my_var = 123
function my_func()
my_var = my_var + 1
print(my_var)
end
end
Спасибо Дарк, да, я тут тоже всё экспериментирую. Вопрос по repeat снят. Я удивился, но скорость с репитом выросла ровно в 2 раза, а это очень нехило.
В общем в критичных по скорости функциях нужно использовать только СИ-шные переменные и следовательно избавляться от for-ов, а использовать репиты и вайлы в которых роль индексов выполняют СИ-шные переменные. Выигрыш по скорости колоссальный. Основные тормоза именно на циклах.
Ахренеть, добился скорости поиска среди 1000 картинок, размером 500х23, при условии просмотра ВСЕХ картинок аж всего за ТРИ тысячных секунды. Думаю на этом можно поставить жирную точку.
Использовал для поиска только один канал и только нужной, а не всей зоны картинки, естественно оставляя возможность анализировать все каналы и все пиксели для сложных и не текстовых картинок.
Мда, не всё так просто, я маловато знаю, не всегда переход на репит даёт положительный результат.
k=0
repeat
sg[k]=rmem("unsigned char*",indg+k)[0]
sl[k]=rmem("unsigned char*",indl+k)[0]
if math.abs(sg[k]-sl[k])>cdev then return 0 end
k=k+1
until k>cch[code]
for k=0,2 do
sg[k]=rmem("unsigned char*",indg+k)[0]
sl[k]=rmem("unsigned char*",indl+k)[0]
if math.abs(sg[k]-sl[k])>cdev then return 0 end
end
Выбросил из кода if math.abs(sg[2]-sl[2])>cdev then return 0 end
Сделал код ещё некрасивей, но ещё быстрее на 30%. А это очень прилично. В "боевых" условиях, на "живых" картинках, что-то мне подсказывает поиск будет мгновенным.
log "clear" log "mode compact"
local ffi=require "ffi"
local n=ffi.new("uint8_t[3]")
local m=ffi.new("uint8_t")
local s=""
m=tonumber(r1)
log(m) -- nil
log(type(n[0])) -- number
--n[0]=tonumber(r1) -- если разремарить будет ошибка конвертирования
stop_script()
Непонятно почему при первом варианте с переменной m нет ошибки.
По логике типа её адрес не определён и следовательно nil, а как тогда хранится её адрес в памяти? Что-то я запутался.
Вроде понял, извините, затупил.
--lua
local ffi=require "ffi"
log "clear" log "mode compact"
local n=ffi.new("uint32_t[3]")
local x,y,z=ffi.new("uint32_t"),ffi.new("uint32_t"),ffi.new("uint32_t")
x,y,z=0,0,0
tmc=os.clock()
repeat
x=x+1
repeat
y=y+1
if y>x then z=1 else z=2 end
until y>100000000
until x>100000000
log(os.clock()-tmc)
tmc=os.clock()
repeat
n[0]=n[0]+1
repeat
n[1]=n[1]+1
if n[1]>n[0] then n[2]=1 else n[2]=2 end
until n[1]>100000000
until n[0]>100000000
log(os.clock()-tmc)
stop_script()
Дарк, чего-то я вообще ничего не понимаю. Может я чего не то делаю? Вот тестани этот код. У меня получается медленнее на СИ-шных, на массиве разница вообще очевидная.
log "clear" log "mode compact"
do
local n=ffi.new("uint32_t[3]")
local x,y,z=ffi.new("uint32_t"),ffi.new("uint32_t"),ffi.new("uint32_t")
x,y,z=0,0,0
tmc=os.clock()
repeat
x=x+1
repeat
y=y+1
if y>x then z=1 else z=2 end
until y>100000000
until x>100000000
log(os.clock()-tmc)
tmc=os.clock()
repeat
n[0]=n[0]+1
repeat
n[1]=n[1]+1
if n[1]>n[0] then n[2]=1 else n[2]=2 end
until n[1]>100000000
until n[0]>100000000
log(os.clock()-tmc)
end
do
local n={}
n[1],n[2],n[3]=0,0,0
local x,y,z=0,0,0
tmc=os.clock()
repeat
x=x+1
repeat
y=y+1
if y>x then z=1 else z=2 end
until y>100000000
until x>100000000
log(os.clock()-tmc)
tmc=os.clock()
repeat
n[1]=n[1]+1
repeat
n[2]=n[2]+1
if n[2]>n[1] then n[3]=1 else n[3]=2 end
until n[2]>100000000
until n[1]>100000000
log(os.clock()-tmc)
end
stop_script()
В общем надо всё ещё раз потестировать. Но я проверял ведь, получалось вроде на СИ-шных быстрее. Ладно попробую на реальном коде. Хотя если честно - уже тошнит меня от этой лабуды, пора бы делом заняться, а я всё с библиотекой ковыряюсь.
Раз уж тесты на скорость, зачем repeat, когда есть while.
--lua
local ffi=require "ffi"
log "clear" log "mode compact"
local n=ffi.new("uint32_t[3]")
local x,y,z=ffi.new("uint32_t"),ffi.new("uint32_t"),ffi.new("uint32_t")
x,y,z=0,0,0
tmc=os.clock()
repeat
x=x+1
repeat
y=y+1
if y>x then z=1 else z=2 end
until y>100000000
until x>100000000
log(os.clock()-tmc)
x,y,z=0,0,0
tmc=os.clock()
while x<=100000000 do
x=x+1
while y<=100000000 do
y=y+1
if y>x then z=1 else z=2 end
end
end
log(os.clock()-tmc)
stop_script()
Но от массива надо однозначно избавляться. На СИ - 100% потери - это ни в какие ворота не лезет. Я стараюсь выжать крохи, а тут такой костыль...
Спасибо Cirus. Ладно, переделаем, ну блин, я выжму до последней капли - будет 10 махов.
Слушай Дарк, у меня наоборот на беззнаковых быстрее. Здесь 32 бита, просто чтобы "влезли" циклы. Но на самом деле я пробовал ВСЕ типы. ПРИНЦИПИАЛЬНОГО выигрыша нет. А здесь то 100%!!!
Принцип я понял. Кстати я ведь тестировал кое-что и прироста тоже не обнаружил между СИ и LUA. Там реальный прирост при вызове ридмема, так сказать родное на родном работает, а на остальном надо действительно просто смотреть, ни хрена не понятно.
https://forum.uokit.com/index.php?showtopic=69255&st=120#
В синтетике одназначно есть разница. Возможно if'ы все тормозят ибо хз как их там реализовывали, может приведение идет.
Огромное спасибо. Две пилюли есть, вместо репита вайл и вместо массива - переменные. Прирост будет супер.
Переделал свою функцию поиска на вайл - прирост НУЛЬ, там сравнение с переменными и тормозов нет.
Так что с константами надо поаккуратнее.
в double отведено 52 бита под целые. Аккуратнее с нулями.
Убрал из функции массивы, в ридмем читаю в переменные. Прирост скорости 11%.
А ты стариной не тряхнешь и не перепишешь этот кусок на асме в итоге?) Скорость будет существенно выше Кстати в этой шутке только доля шутки.
rmem("unsigned char*",ind)[0]
Дарк, а что означает нуль в квадратных скобках? Хендл Пилота?
Собственно возник вопрос такого плана, а можно не один байт читать, а скажем сколько надо. Ну типа затолкать сразу в структуру все байты строки пикселей. Ну по принципу работы move.
Иначе говоря, можно вместо "unsigned char*" использовать свою структуру? Ведь можем же считать 2 байта, если нарисовать например "uint_16t"
обычно в таких случаях используют массив char'ов.
вообще в данном случае мы читаем через cast(явное приведение типов). В данном случае хз как все это делать правильно.
Поясни, что именно ты хочешь сделать? Сравнить два длинных участка памяти? Скопировать кусок памяти? Если скопировать, то зачем?
rr=rmem("rgb*",p)[0] РАБОТАЕТ!! Сразу читает в СИ структуру все 3 канала. Да хотел убрать один цикл, тормозят эти циклы, хотел сразу считать все пиксели в массив СИ-шный (естественно только для одной строки пикселей).
ну как бы логично) ты же и так уже структуры использовал. я думал ты именно некоторый кусок памяти длиной N хочешь куда-то скопировать. Тем не менее я все еще не понимаю зачем нужно подобное чтение. Что-то у меня подозрения, что лишние операции проводятся.
Дольше в 2 раза читает структуру ридмем. Не поленился, опять всё шаг за шагом протестировал. Пока понятно следующее. Ридмем - это самый быстрый шаг во всей цепочке анализа, и ему фиолетово что с нулевого, что не с нулевого индекса читать. Теперь далее. Сам по себе цикл for выполняется в 3 раза быстрее, чем while. Но загвоздка в том, как индекс цикла используется внутри цикла. Вот на этот вопрос у меня пока нет однозначного ответа, но он обязательно будет. Тормоз - это кишки внутри цикла и от типа переменных внутри его тормоза могут увеличиваться аж в 4 РАЗА. Вот я и пытаю пока, как эти типы работают внутри.
64 разрядные (пока не всё ещё проверил) иногда работают быстрее, но их нельзя использовать в for-ах. Вот тут и надо смотреть чем жертвовать, типом цикла или скоростью внутренних вычислений.
дай код
log "clear" log "mode compact"
tmc=os.clock()
for i=1,200000000 do end
log(os.clock()-tmc)
tmc=os.clock()
i=1
while i<=200000000 do i=i+1 end
log(os.clock()-tmc)
tmc=os.clock()
for i=1,200000000 do a=i end
log(os.clock()-tmc)
tmc=os.clock()
i=1
while i<=200000000 do i=i+1 a=i end
log(os.clock()-tmc)
tmc=os.clock()
for i=1,200000000 do if i>100 then a=i else a=0 end end
log(os.clock()-tmc)
tmc=os.clock()
i=1
while i<=200000000 do if i>100 then a=i else a=0 end i=i+1 end
log(os.clock()-tmc)
stop_script()
ты не пробовал не переменные использовать в ифах, а напрямую читать память?
--lua
local ffi=require "ffi" -- Использование модуля ffi для использования СИ структур
local rmem=ffi.cast -- Использование функции чтения из памяти модуля ffi
ffi.cdef[[typedef struct{uint16_t x,y; uint8_t red,green,blue;}xyrgb]] -- Определение структуры массива чтения данных из памяти образа картинки
local function FindMemRGBpf(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- ПОИСК ПИКСЕЛЕЙ ПО ЗНАЧЕНИЯМ RGB В ОБЛАСТИ ПАМЯТИ
-- addr,len : адрес в памяти, длина строки в памяти (то, что даёт getimage)
-- scrX1,scrY1 : координаты верхнего левого угла образа в памяти, должны быть аналогичны координатам getimage
-- fx1,fy1,fx2,fy2 : координаты поиска пикселей, абсолютные относительно рабочего окна. Должны быть внутри диапазона координат образа в памяти.
-- usl : ОДНО строковое условие поиска "R(10-255) G(70-100) B(50) R-G[50 200] R-B[-40 -20] G-B[15]".
-- numf : максимальное количество искомых пикселей
local n=math.min(numf,(fx2-fx1+1)*(fy2-fy1+1)) -- Определение максимальной размерности возвращаемого функцией СИ массива найденных пикселей
local arr=ffi.new("xyrgb[?]",n) -- Инициализация СИ массива искомых пикселей (используя ранее описанную структуру)
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
local r,g,b,cr1,cr2,cg1,cg2,cb1,cb2=ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),
ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t")
local cRG1,cRG2,cRB1,cRB2,cGB1,cGB2,k=ffi.new("int16_t"),ffi.new("int16_t"),ffi.new("int16_t"),ffi.new("int16_t"),
ffi.new("int16_t"),ffi.new("int16_t"),ffi.new("int16_t")
if r1==nil then cr1,cr2=0,255
else cr1=tonumber(r1) if r2=="" then cr2=cr1 else cr2=tonumber(r2) end
end
if g1==nil then cg1,cg2=0,255
else cg1=tonumber(g1) if g2=="" then cg2=cg1 else cg2=tonumber(g2) end
end
if b1==nil then cb1,cb2=0,255
else cb1=tonumber(b1) if b2=="" then cb2=cb1 else cb2=tonumber(b2) end
end
if RG1==nil then cRG1,cRG2=-255,255
else cRG1=tonumber(RG1) if RG2=="" then cRG2=255 else cRG2=tonumber(RG2) end
end
if RB1==nil then cRB1,cRB2=-255,255
else cRB1=tonumber(RB1) if RB2=="" then cRB2=255 else cRB2=tonumber(RB2) end
end
if GB1==nil then cGB1,cGB2=-255,255
else cGB1=tonumber(GB1) if GB2=="" then cGB2=255 else cGB2=tonumber(GB2) end
end
local indY,ind,caddr,clen,cscrX1,cscrY1,cfx1,cfx2,cfy1,cfy2=ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),
ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t")
k,caddr,clen,cscrX1,cscrY1,cfx1,cfx2,cfy1,cfy2=-1,addr,len,scrX1,scrY1,fx1,fx2,fy1,fy2
for i=cfy1,cfy2 do
indY=caddr+(i-cscrY1)*clen
for j=cfx1,cfx2 do
ind=indY+(j-cscrX1)*3
b=rmem("unsigned char*",ind)[0]
g=rmem("unsigned char*",ind)[1]
r=rmem("unsigned char*",ind)[2]
if r>=cr1 and r<=cr2 and g>=cg1 and g<=cg2 and b>=cb1 and b<=cb2 and r-g>=cRG1 and r-g<=cRG2 and r-b>=cRB1 and r-b<=cRB2 and g-b>=cGB1 and g-b<=cGB2 then
k=k+1 arr[k].x,arr[k].y,arr[k].red,arr[k].green,arr[k].blue=j,i,r,g,b
if numf-1==k then return k,arr end
end
end
end
return k,arr
end----------------------------------------------------------------------------
local function FindMemRGBpw(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- ПОИСК ПИКСЕЛЕЙ ПО ЗНАЧЕНИЯМ RGB В ОБЛАСТИ ПАМЯТИ
-- addr,len : адрес в памяти, длина строки в памяти (то, что даёт getimage)
-- scrX1,scrY1 : координаты верхнего левого угла образа в памяти, должны быть аналогичны координатам getimage
-- fx1,fy1,fx2,fy2 : координаты поиска пикселей, абсолютные относительно рабочего окна. Должны быть внутри диапазона координат образа в памяти.
-- usl : ОДНО строковое условие поиска "R(10-255) G(70-100) B(50) R-G[50 200] R-B[-40 -20] G-B[15]".
-- numf : максимальное количество искомых пикселей
local n=math.min(numf,(fx2-fx1+1)*(fy2-fy1+1)) -- Определение максимальной размерности возвращаемого функцией СИ массива найденных пикселей
local arr=ffi.new("xyrgb[?]",n) -- Инициализация СИ массива искомых пикселей (используя ранее описанную структуру)
local r1,r2=usl:match("R%((%d+)%-*(%d*)")
local g1,g2=usl:match("G%((%d+)%-*(%d*)")
local b1,b2=usl:match("B%((%d+)%-*(%d*)")
local RG1,RG2=usl:match("R%-G%[(%-*%d+)%s*(%-*%d*)")
local RB1,RB2=usl:match("R%-B%[(%-*%d+)%s*(%-*%d*)")
local GB1,GB2=usl:match("G%-B%[(%-*%d+)%s*(%-*%d*)")
local r,g,b,cr1,cr2,cg1,cg2,cb1,cb2=ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),
ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t")
local cRG1,cRG2,cRB1,cRB2,cGB1,cGB2,k=ffi.new("int16_t"),ffi.new("int16_t"),ffi.new("int16_t"),ffi.new("int16_t"),
ffi.new("int16_t"),ffi.new("int16_t"),ffi.new("int16_t")
if r1==nil then cr1,cr2=0,255
else cr1=tonumber(r1) if r2=="" then cr2=cr1 else cr2=tonumber(r2) end
end
if g1==nil then cg1,cg2=0,255
else cg1=tonumber(g1) if g2=="" then cg2=cg1 else cg2=tonumber(g2) end
end
if b1==nil then cb1,cb2=0,255
else cb1=tonumber(b1) if b2=="" then cb2=cb1 else cb2=tonumber(b2) end
end
if RG1==nil then cRG1,cRG2=-255,255
else cRG1=tonumber(RG1) if RG2=="" then cRG2=255 else cRG2=tonumber(RG2) end
end
if RB1==nil then cRB1,cRB2=-255,255
else cRB1=tonumber(RB1) if RB2=="" then cRB2=255 else cRB2=tonumber(RB2) end
end
if GB1==nil then cGB1,cGB2=-255,255
else cGB1=tonumber(GB1) if GB2=="" then cGB2=255 else cGB2=tonumber(GB2) end
end
local i,j,indY,ind,caddr,clen,cscrX1,cscrY1,cfx1,cfx2,cfy1,cfy2=ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),
ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t"),ffi.new("uint16_t")
i,k,caddr,clen,cscrX1,cscrY1,cfx1,cfx2,cfy1,cfy2=fy1,-1,addr,len,scrX1,scrY1,fx1,fx2,fy1,fy2
while i<=cfy2 do
indY,j=caddr+(i-cscrY1)*clen,cfx1
while j<=cfx2 do
ind=indY+(j-cscrX1)*3
b=rmem("unsigned char*",ind)[0]
g=rmem("unsigned char*",ind)[1]
r=rmem("unsigned char*",ind)[2]
if r>=cr1 and r<=cr2 and g>=cg1 and g<=cg2 and b>=cb1 and b<=cb2 and r-g>=cRG1 and r-g<=cRG2 and r-b>=cRB1 and r-b<=cRB2 and g-b>=cGB1 and g-b<=cGB2 then
k=k+1 arr[k].x,arr[k].y,arr[k].red,arr[k].green,arr[k].blue=j,i,r,g,b
if numf-1==k then return k,arr end
end
j=j+1
end
i=i+1
end
return k,arr
end----------------------------------------------------------------------------
log "clear" log "mode compact"
-- сделать окно рабочим
local p,_,_,l=getimage(0,0,999,999,ok[1][1])
tmc=os.clock()
for jj=1,1000 do
k,arr=FindMemRGBpf(p,l,0,0, 0,0,999,999,"R(251)G(112)",2)
end
log(os.clock()-tmc)
tmc=os.clock()
for jj=1,1000 do
k,arr=FindMemRGBpw(p,l,0,0, 0,0,999,999,"R(251)G(112)",2)
end
log(os.clock()-tmc)
tmc=os.clock()
for jj=1,500 do
k,arr=FindMemRGBpf(p,l,0,0, 0,0,999,999,"R-G[139 139]R-B[249 249]",2)
end
log(os.clock()-tmc)
tmc=os.clock()
for jj=1,500 do
k,arr=FindMemRGBpw(p,l,0,0, 0,0,999,999,"R-G[139 139]R-B[249 249]",2)
end
log(os.clock()-tmc)
deleteimage(p)
log(k)
if k~=-1 then log(arr[k].x,arr[k].y,arr[k].red,arr[k].green,arr[k].blue) end
stop_script()
А это как объяснить?:
--lua
log "clear" log "mode compact"
local a, tmc
tmc=os.clock()
for i=1,200000000 do if i>56 then a=i else a=0 end end
log(os.clock()-tmc)
tmc=os.clock()
for i=1,200000000 do if i>57 then a=i else a=0 end end
log(os.clock()-tmc)
stop_script()
Вот прикол, скопировал свою хрень на новую вкладку скриптов и вторая часть скрипта стала работать почти в 2 раза быстрее, наверное Пилот пора перегружать. Ничего совсем не понимаю.
0.11799999998766
1.0469999999914
--tmc=os.clock()
--for jj=1,1000 do
-- k,arr=FindMemRGBpf(p,l,0,0, 0,0,999,999,"R(251)G(112)",2)
--end
--log(os.clock()-tmc)
--tmc=os.clock()
--for jj=1,1000 do
-- k,arr=FindMemRGBpw(p,l,0,0, 0,0,999,999,"R(251)G(112)",2)
--end
--log(os.clock()-tmc)
tmc=os.clock()
for jj=1,500 do
k,arr=FindMemRGBpf(p,l,0,0, 0,0,999,999,"R-G[139 139]R-B[249 249]",2)
end
log(os.clock()-tmc)
tmc=os.clock()
for jj=1,500 do
k,arr=FindMemRGBpw(p,l,0,0, 0,0,999,999,"R-G[139 139]R-B[249 249]",2)
log(os.clock()-tmc)
end
Ремарка первого блока влияет на 3-й блок, ремарка 2-го блока влияет на 4-й блок. Мистика какая-то.
Ну-с, господа, что скажете? Жду ваших комментариев.
Вы уж извините меня, наверное я достал уже всех со своими функциями. Но вдруг поможет выявить какие-нибудь косяки.
Дарк, ты пример Cirus-а смотрел? какие ключи? Тут без ключей хватает загадок.
a runtime error.
114: attempt to index global 'ok' (a nil value)
Пробовал ставить задержку, пробовал другие переменные цикла - результат тот же.
if r>=cr1 and r<=cr2 and g>=cg1 and g<=cg2 and b>=cb1 and b<=cb2 and r-g>=cRG1 and r-g<=cRG2 and r-b>=cRB1 and r-b<=cRB2 and g-b>=cGB1 and g-b<=cGB2 then
53 строка +/-
вот на этом сыпит про модуль
Значения ридмема анализируются.
У меня тоже на большинстве окон не работает. Работает на графических окнах только.
jit.off()
В шапку и все стройно по времени получается. Динамическая компиляция оптимизирует коряво. Но без оптимизации получается мегатормоз (два нуля в циклах сразу убирай).
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)