Форум: "Начинающим";
Текущий архив: 2014.07.06;
Скачать: [xml.tar.bz2];
ВнизОптимизация кода Найти похожие ветки
← →
Вова (2013-08-23 01:21) [160]
TRGB = record
case integer of
1: (RGB: LongInt);
2: (B, G, R, O: BYTE);
var
rRGB:TRGB;
rrgb.RGB := ColorToRGB(color);
RGBV.red := rrgb.B;
RGBV.green := rrgb.G;
RGBV.blue := rrgb.R;
CODE</>
RGBV.red := color;
RGBV.green := color shr 8;
RGBV.blue := color shr 16;
оба варианта дают одинаковый результат. (второй старый на 24 бита был). то что было раньше желтым теперь красное, и появился голубой....откуда блин голубой, у меня в массиве его вообще нет.Function ConvertColorToRGBColorMap(color: LongInt; ColSel: string = "None")
: TColorWithName;
var
RGBV: trgbcolor;
bg: Boolean;
rb: Boolean;
rg: Boolean;
rRGB:TRGB;
begin
// rrgb.RGB := ColorToRGB(color);
// RGBV.red := rrgb.B;
// RGBV.green := rrgb.G;
// RGBV.blue := rrgb.R;
RGBV.red := color;
RGBV.green := color shr 8;
RGBV.blue := color shr 16;
rb := almostEqual(RGBV.red, RGBV.blue);
bg := almostEqual(RGBV.blue, RGBV.green);
rg := almostEqual(RGBV.red, RGBV.green);
with RGBV do
if rg and rb and bg then // тогда это серый или черный или белый
begin
if red > 230 then // белый
begin
result.color := RGB(255, 255, 255);
result.Name := "White";
end
else if red > 120 then
begin
result.color := RGB(190, 190, 190);
result.Name := "LightGray";
end
else if (red > 92) then // темно серый
begin
result.color := RGB(100, 100, 100);
result.Name := "DarkGray";
end
else
begin
result.color := RGB(0, 0, 0);
result.Name := "Black";
end // черный
end
else
begin
if (red < green) and (red < blue) and bg and (blue > 130) then
begin
result.color := RGB(0, 0, 255);
result.Name := "Blue";
end // result:= rgb(0,255,255)//голубой
else if (green < red) and (green < blue) and rb and (red > 130) then
begin
result.color := RGB(255, 0, 255);
result.Name := "Pink";
end // розовый
else if (blue < green) and (blue < red) and rg and (green > 130) then
begin
result.color := RGB(255, 255, 0);
result.Name := "Yellow";
end // желтый
else if (red > green) and (red > blue) and (red > 130) then
begin
result.color := RGB(255, 0, 0);
result.Name := "Red";
end // красный
else if (blue > green) and (blue > red) and (blue > 130) then
begin
result.color := RGB(0, 0, 255);
result.Name := "Blue";
end // синий
else if (green > blue) and (green > red) and (green > 130) then
begin
result.color := RGB(0, 255, 0);
result.Name := "Green";
end // зеленый
else
begin
result.color := RGB(0, 0, 0);
result.Name := "Black";
end
end;
if not(ColSel = "None") then
if (ColSel = result.Name) then
begin
result.color := 255; // картинка инвертирована для дальнейшей обработки
end
else
begin
result.color := 0;
end;
end;
Procedure InitColorMap();
var
i, j, k: byte;
begin
for i := 0 to 15 do
for j := 0 to 15 do
for k := 0 to 15 do
ColorMap[i * 256 + 16 * k + j] := ConvertColorToRGBColorMap
((i * 256 * 256 + j * 256 + k) * 16).color;
// for i:=0 to 15 do for j:=0 to 15 do for k:=0 to 15 do ColorMap[i*256+16*k+j]:=ConvertColorToRGBColorMap((i*16+15)*256*256+(j*16+15)*256+(k*16+15));
end;
Function ConvertBmpToRGBColorMap(var tBmp: Tbitmap;
ColSel: String = "None"): Boolean;
var
QP: TQuickPixels;
Pixel1: Cardinal;
x: integer;
y: integer;
i: integer;
numCol: byte;
Start,Stop:pInteger;
begin
if (tBmp.Height > 2) and (tBmp.Width >= 1) then
begin
numCol := TextColorToDigit(ColSel);
if numCol = 0 then
begin
Start := tBmp.ScanLine[tBmp.Height - 1];
Stop := tBmp.ScanLine[0];
repeat
i:= Start^;
Start^ := ColorMap[i shr 12 and $F0F or i and $F0];
inc(Start);
inc(Pixel1);
until Start = Stop;
end;
Result := true;
end
else
Result := false;
end;
← →
Вова (2013-08-23 01:47) [161]RGB(255, 255, 255);дело в этой функции...
← →
Sapersky (2013-08-23 01:49) [162]С битами всё объяснено в [119], только мне кажется лучше обозвать стандартными "цветными" буквами:
$00aabbcc -> $00000acb
$00RrGgBb -> $00000RBG
внезапно RBG, а не RGB. На этом можно сэкономить, B не двигать, R и G обрабатывать вместе.
Сейчас у нас (с учётом доп. сдвига i := Start^ shr 8):
$00BbGgRr -> $00000BRG
вроде ж всё очевидно: пара B_G двигается на 3 символа вправо (байт - два символа, сдвиг на полтора байта = shr 12), and $F0F отрезает всё лишнее. R никуда не двигается, просто отрезается лишнее маской $F0.
В результате имеем то самое шаманское заклинание.
А цвета в таблицу нужно подставлять в порядке BRG, получается.
Мог бы и сам понять, если бы внимательно читал, что тебе пишут...
← →
Вова (2013-08-23 02:02) [163]здорово что хоть кому то все очевидно...
т.к. мне и теперь стало еще непонятней чем было.
← →
Sapersky (2013-08-23 02:23) [164]Ну мне не сразу стало очевидно, пришлось вчитаться в [119].
Sha тоже хорош - изменил порядок цветов и упомянул об этом практически вскользь, я сначала подумал что acb это опечатка.
Делаем нормальный порядок цветов, хотя и менее оптимально:
$BbGgRr00 -> $00000RGB
R на 1 вправо, 4 бита.
G на 4 вправо, 16 бит.
B на 7 вправо, 28 бит.
i := Start^;
Start^ := ColorMap[(i shr 1 and $F) or (i shr 4 and $F) or (i shr 28)];
7 операций вместо 5.
← →
Sapersky (2013-08-23 02:25) [165]Всё-таки запутался в этих битах:
Start^ := ColorMap[(i shr 4 and $F) or (i shr 16 and $F) or (i shr 28)];
← →
Вова (2013-08-23 02:34) [166]ша тут нипричем, массив можно выкинуть вообще, и это ничего не изменит.
Start^ := ConvertColorToRGBColorMap(Start^).color;
т.е. вот такой код дает точно такой же результат. но... это значение вернула функция RGB(255,255,0); причем у меня там нет ниодной функции, которая генерит голубой цвет...а в итоговом бмп он есть...т.е. если даже допустить, что входной цвет у меня какой то неправильный, то выходной то как становится голубым? вот в чем вопрос )
← →
Вова (2013-08-23 02:41) [167]
function RGB(r, g, b: Byte): COLORREF;
begin
Result := (r or (g shl 8) or (b shl 16));
end;
во т.е. я так понимаю она как раз делает BGR? но в Start^ 4 байта, и куда прилепляется 4й?
← →
Sapersky (2013-08-23 02:41) [168]По поводу варианта с ColorToRGB - посмотрел бы, что она делает, Ctrl-клик и все дела.
В общем, не нужна она тут, rrgb.RGB := color должно работать.
Вариант со сдвигами - ещё в [21] писали, что нужно отрезать нужные байты масками.
← →
Вова (2013-08-23 02:48) [169]
function ColorToRGB(Color: TColor): Longint;
begin
if Color < 0 then
Result := GetSysColor(Color and $000000FF) else
Result := Color;
end;
← →
Вова (2013-08-23 02:58) [170]function RGB2(r, g, b: Byte): COLORREF;
begin
Result := (b or (g shl 8) or (r shl 16));
end;
методом научного тыка я выяснил, что теперь каналы как раз RGB и идут, а были BGR, а вот где альфа канал я так и не понял...
← →
Вова (2013-08-23 03:05) [171]твою машу, короче мозг сломаешь
RGBV.red := color shr 16;;
RGBV.green := color shr 8;
RGBV.blue := color;
входной так, выходной как в 170, вроде цвета на место встали и я запутался окончательно )
← →
Вова (2013-08-23 08:44) [172]мда уж, хоть с цветами все и решилось.
Но ночь плясок с бубном вокруг разворачивания изображения в разные стороны, отражения координат и т.д. и т.п. успехом не увенчались...
координата 0.0 картинки вовсе не тут Start := tBmp.ScanLine[tBmp.Height - 1];
и не тут!!! Stop := tBmp.ScanLine[0]; она вот тут: dec(Stop,tBmp.Width)
← →
Sha © (2013-08-23 10:21) [173]> Sha тоже хорош - изменил порядок цветов...
Так я вроде сказал, там выше, что это некий условный номер цвета )
Если особо не вдаваться в детали и не пытаться в этом номере
увидеть нечто большее, то все будет работать, как надо.
Ведь и при записи, и при чтении данных из таблицы мы
для одинаковых цветов будем вычислять одинаковый номер.
Поэтому абсолютно без разницы где там данные лежат в таблице
← →
Sha © (2013-08-23 10:40) [174]Таблица используется просто как кеш для запоминания результата функции.
Именно поэтому ей совершенно безразличен порядок цветов: RGB, BGR или
как еще. Альфа не кешируется.
← →
Sapersky (2013-08-23 16:12) [175]Поправки к [162] и [164]:
Я забыл, что при чтении как Integer порядок байт разворачивается, т.е. в памяти BGRA, в Integer ARGB.
Шаманское преобразование для 32-х бит будет $AaRrGgBb -> $RBG. И это таки влияет на порядок индексов при просчёте таблицы:
ColorMap[r * 256 + b * 16 + g] := ...
Для RGB:
ColorMap[r * 256 + g * 16 + b] := ...
Start^ := ColorMap[(i shr 12 and $F00) or (i shr 8 and $F0) or (i shr 4 and $F)];
← →
проф. Преображенский (2013-08-23 17:04) [176]Я "нет" говорю вместо "да",
Сажусь туда, где недавно был стул,
Я ложку несу мимо рта,
И просыпаюсь не там где уснул.
← →
проф. Преображенский (2013-08-23 18:37) [177]Я вижу суть вещей отныне,
Я слышу голос неземной,
А то, что сотворю в пустыне,
Узрят пришедшие за мной.
← →
Sha © (2013-08-24 08:52) [178]Предусмотреть все невозможно.
Успех меня опять не уберег.
Ну, нафига мне в руки вложен
Судьбой тот самый молоток?
← →
Вова (2013-08-24 11:37) [179]ощем, хз как разворачивать цикл. И акромя того, я таки стал разворачивать картинки в нормальное состояние (при переходе от бмп к массивам). Т.к. все расчитано на то, что картинка начинает обрабатывацо с левого верхнего угла, иначе если шаблон не на 100% накладываецо то всему писец. Да и полный размер программы в памяти ужо 100 мб, причем 2.8 экзешник и 97 база данных и картинки)) так что надо чо то с этим делать и битмапы нафиг слать.
← →
Вова (2013-08-24 11:56) [180]а вообще вопрос, целесообразно ли переходить от битмапа на одномерный массив. Особенно учитывая, что информация в битмапе явно избыточная, все что мне нужно помещается в 1 байте на пиксель, но очень важна скорость обработки. И еще есть ли смысл с обычным массивом работать через указатели( с точки зрения быстродействия)?
← →
Sha © (2013-08-24 12:25) [181]> все что мне нужно помещается в 1 байте на пиксель
и зачем тогда весь огород? столько времени строили...
> И еще есть ли смысл с обычным массивом работать через указатели
> ( с точки зрения быстродействия)?
небольшой дополнительный прирост можно получить,
но сначала алгоритм продумай и перейди на 1 байт, это даст гораздо больше
← →
Вова (2013-08-24 12:53) [182]как зачем, начинается то все со скриншота, но после обработки от него остается 1 байт на пиксель ) Хотя даже не байт, а бит ) т.е. после фильтрации все что мне нужно знать, есть в таком то месте пиксель или нет.
← →
Вова (2013-08-24 12:55) [183]а то что мы делали и была фильтрация и взятие скриншота, ну взятие скриншота потом переродилось в более редкое взятие скриншота в отдельном потоке и быстрое копирование его кусков в разные места )
← →
Вова (2013-08-24 13:06) [184]на байт я уже перешел давно, правда в процессе этого топика я усомнился, что так быстрее, наблюдая за тем как быстро обрабатывается битмап.
Т.е. базовый вариант, это берется кусок скрина и переводится в градацию серого в этот момент я переношу кусок битмапа в одномерный массив of Byte, после доп обработки, я переношу во второй массив точно такой же, но в нем у меня во всех точках либо 255 либо 0, т.е. по сути уже биты....
Вот кажется мне, что быстрее прям в битмапе переводить в серый, его обрабатывать и только потом переносить в массив с байтами....или с битами?
← →
Sapersky (2013-08-24 13:16) [185]Раз уж ты начинаешь задумываться об альтернативах TBitmap, предложу TFastDIB, там работа с 8-битными картинками достаточно удобна:
http://sourceforge.net/projects/tfastdib/files/Library/FastDIB%204.0/FastDIB%204.0.zip/download
Чтобы получить начало в левом верхнем углу, как я уже говорил, нужно задать отрицательную высоту.
1 бит на пиксель - не нужно, неудобно обрабатывать.
← →
Sha © (2013-08-24 13:52) [186]> Вова (24.08.13 13:06) [184]
Просто нет слов...
И что должно получиться в итоге?
← →
Вова (2013-08-24 16:00) [187]1) screenshot -> GrayScale -> Monochrome -> Search
2) screenshot -> Monochrome -> Search Это вариант который мы тут мучали, ничего не пропало зря. Просто мы преобразовывали битмап и в него же складывали результат, а на боевой результат копируется в массив байтов. хотя кажется мне что вот этим самым копированием замедляется работа (
← →
Вова (2013-08-24 16:05) [188]короче, просто взять битмап и отрезать от него нужный байт это не варинт ) так что не пойму, чего ты разволновался то )
← →
ProgRAMmer Dimonych © (2013-08-24 16:09) [189]> хотя кажется мне что вот этим самым копированием замедляется
> работа (
«Кажется» — это для астрологов и прочих экстрасенсов. У нас все копирования меряются и сравниваются с остальными операциями, выбирается самая медленная и оптимизируется. Процесс повторяется до получения приемлемого результата: при обработке больших массивов данных — до тех пор, пока не получится обрабатывать со скоростью, достаточной, чтобы данные не накапливались, при написании GUI-приложения — до тех пор, пока пользователь не перестанет замечать задержку во времени (кажется, около 100 мс — минимум, который можно ощутить).
← →
Вова (2013-08-24 16:38) [190]не ну я на самом деле проверял, если писать в тот же битмап из которого читаешь, то он быстрее работает, т.к. хотя бы потому, что операций меньше, не нужно в целевом массиве позиционироваться на нужную ячейку. А мне плюс к тому, еще приходится переворачивать изображение, т.к. Search для перевернутого изображения я сделать не смог, у меня критично чтобы поиск начинался с самой верхней точки объекта (и во вторую очередь с самой левой).
← →
Вова (2013-08-24 16:40) [191]*т.е. для неперевернутого....ну вообщем для такого как в битмапе ))
← →
Вова (2013-08-24 17:39) [192]ощема, вот так вот 4 миллисекунды, вместо 2х когда конвертишь сам битмап. В указателях слаб, поэтому невкурил как вместо m:TArrInt указатель на него передать и указателем по массиву бежать, так что ввел num (
Procedure Convert(Start,Stop:pInteger;Width:integer;m:TArrInt;Mass: TColorMapByte);
var
count,i,num:Integer;
begin
count := Width;
num := 0;
repeat
repeat
i := Start^;
m[num] := Mass[i shr 12 and $F0F or i and $F0];
inc(Start);
inc(num);
dec(count);
until count = 0;
count := Width;
dec(Start,Width*2);
until Start = Stop;
end;
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Start, Stop: pInteger;
begin
//tbmp.SaveToFile("C:\yui.bmp");
Start := tBmp.ScanLine[0];
dec(Start,tBmp.Width);
Stop := tBmp.ScanLine[tBmp.Height - 1];
inc(Stop,tBmp.Width);
Convert(Start,Stop,tBmp.Width,M.Mass,Mass);
Result := true;
end;
← →
Sha © (2013-08-24 17:41) [193]> Вова (24.08.13 16:00) [187], [188]
1. правильная работа массивом 1-байтных элементов будет заметно быстрее
2. все можно сделать за один проход
3. перевороты изображения - очевидный бред
4. рассуждения про скорость позиционирования - самоуспокаивающий бред
5. то, что ты не умеешь - не аргумент, учись
← →
Вова (2013-08-24 17:53) [194]1) однобайтный массив еще нужно получить в коде вверху я это и делаю.
2) несомневаюсь, но как перевернуть картинку в 1 проход я не знаю, и я не могу сделать то чего не знаю как сделать )
3) может и бред, но у меня не хватает воображения чтобы потом с отзеркаленым изображением работать (даже если его по вертикали развернуть легко, но еще нужно по x отразить). тем более что поиск должен идти сверху вниз и слева направо, т.е. если не перевернуть его тут, то потом при поиске все равно нужно извращаться. Что у меня и не получилось )
4) оке, за счет чего тогда в 2 раз медленней? без разворота будет 3-3.5 миллисекунды
5) все стоит времени и не всегда результат окупает затраты. Может и научусь, так ведь никто ж не ценит твоего времени и не показывает как. 20 минут гугла ничему мну не научили )
← →
Sha © (2013-08-24 18:49) [195]> оке, за счет чего тогда в 2 раз медленней?
за счет чего угодно, если интересно, приведи здесь оба кода, посмотрим
← →
Вова (2013-08-24 19:29) [196]
Procedure Convert(Start,Stop:pInteger;Width:integer;m:pByte;Mass: TColorMapByte);
var
count,i:Integer;
begin
count := Width;
repeat
repeat
i := Start^;
m^ := Mass[i shr 12 and $F0F or i and $F0];
inc(Start);
inc(m);
dec(count);
until count = 0;
count := Width;
dec(Start,Width*2);
until Start = Stop;
end;
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Start, Stop: pInteger;
begin
//tbmp.SaveToFile("C:\yui.bmp");
Start := tBmp.ScanLine[0];
dec(Start,tBmp.Width);
Stop := tBmp.ScanLine[tBmp.Height - 1];
inc(Stop,tBmp.Width);
Convert(Start,Stop,tBmp.Width,@M.Mass[0],Mass);
Result := true;
end;
я вкурил как указатель на массив передать, 3 миллисекунды, вместо 4.
← →
Вова (2013-08-24 19:36) [197]хе хе, попробовал второй массив через указатель, получилось на пол милисекунды медленней.
m^ := (Mass + (i shr 12 and $F0F or i and $F0))^;
← →
Вова (2013-08-24 19:39) [198]а нет....это не из за этого...
← →
Вова (2013-08-24 19:43) [199]ощем нет смысла бороться из за одной миллисекунды, т.к. тут еще и загруженность компа влияет и содержимое скриншота... так что это просто погрешность )
← →
Sha © (2013-08-24 19:51) [200]> ведь никто ж не ценит твоего времени и не показывает как
Пример чтения четырех пикселей за три операции в приведен [81].
Там же показано, как развернуть цикл и сэкономить на проверках.
В [12] и [119] разжевано кеширование результата функции.
По ходу обсуждения немного разобраны битовые операции.
В [193] в 100й раз повторено, что *ВСЯ* твоя задача решается
за один проход без предварительного копирования, переворотов и т.п.
Но это мало помогает, никто ж не ценит твоего времени, и не решает за тебя.
Имеет смысл учить только тех, кто хочет учиться.
Страницы: 1 2 3 4 5 6 вся ветка
Форум: "Начинающим";
Текущий архив: 2014.07.06;
Скачать: [xml.tar.bz2];
Память: 0.84 MB
Время: 0.018 c