Форум: "Начинающим";
Текущий архив: 2014.07.06;
Скачать: [xml.tar.bz2];
ВнизОптимизация кода Найти похожие ветки
← →
Вова (2013-06-29 00:08) [40]дауш, то что вызывать сразу из массива, а не из фунции, то это если что то и дало, то я не заметил. а вот когда я убрал текст, производительность выросла в несколько раз.
← →
Вова (2013-06-29 00:12) [41]по сравнению с первоначальными 300-400 милисекунд на картинку 1920x1080 скорость выросла до 30-40 милисекунд, хотя иногда и 15-16 хз почему так )
← →
Sha © (2013-06-29 00:44) [42]наверно, потому, что GetTickCount тикает 1 раз в 15-16 сек
← →
Sha © (2013-06-29 00:51) [43]> Вова (29.06.13 00:08) [40]
> то что вызывать сразу из массива, а не из фунции, то это если что то и дало, то я не заметил
Потому и не заметил, что засекал не время предоления стометровки,
а суммарное время с разминкой перед бегом.
Не стоит делать выводы из неправильно поставленных экспериментов.
← →
Sha © (2013-06-29 00:55) [44]Ты бы свой код полностью показал.
Почему-то кажется, что в нем найдутся еще тормоза.
← →
Вова (2013-06-29 01:42) [45]
TColorMapByte = array[0..16*16*16-1] of byte;
TMassOfColorMap = array[1..9] of TColorMapByte;
//0 - все цвета(не используется)
//1 - красный белый (255), остальное черный
//2 - синий белый
//3 - зеленый белый
//4 - белый белый
//5 - черный белый
//6 - темно -серый
//7 - светло-серый
//8 - желтый
//9 - розовый
var
MassColorMap :TMassOfColorMap;
инициализация
function TextColorToDigit(nameCol: string): byte;
begin
result := 0;
if nameCol = "Red" then
result := 1;
if nameCol = "Blue" then
result := 2;
if nameCol = "Green" then
result := 3;
if nameCol = "White" then
result := 4;
if nameCol = "Black" then
result := 5;
if nameCol = "DarkGray" then
result := 6;
if nameCol = "LightGray" then
result := 7;
if nameCol = "Yellow" then
result := 8;
if nameCol = "Pink" then
result := 9;
end;
function DigitColorToText(nameCol: byte): string;
begin
case nameCol of
1:
result := "Red";
2:
result := "Blue";
3:
result := "Green";
4:
result := "White";
5:
result := "Black";
6:
result := "DarkGray";
7:
result := "LightGray";
8:
result := "Yellow";
9:
result := "Pink";
else
result := "None";
end;
end;
function almostEqual(a, b: byte): Boolean;
begin
if ABS(a - b) < 10 then
result := true
else
result := false;
end;
Function ConvertColorToRGBColorMap(color: LongInt; ColSel: string = "None")
: TColorWithName;
var
RGBV: trgbcolor;
begin
RGBV.red := color;
RGBV.green := color shr 8;
RGBV.blue := color shr 16;
with RGBV do
if almostEqual(red, green) and almostEqual(red, blue) and
almostEqual(blue, green) then // тогда это серый или черный или белый
begin
if almostEqual(red, 240) 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 almostEqual(green, blue) 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 almostEqual(red, blue) and
(red > 130) then
begin
result.color := RGB(255, 0, 255);
result.Name := "Pink";
end // розовый
else if (blue < green) and (blue < red) and almostEqual(green, red) 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 InitColorMapMass();
var
i, j, k, col: byte;
begin
for col := 1 to 9 do
for i := 0 to 15 do
for j := 0 to 15 do
for k := 0 to 15 do
MassColorMap[col][i * 256 + 16 * k + j] := ConvertColorToRGBColorMap
((i * 256 * 256 + j * 256 + k) * 16,DigitColorToText(col)).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;
собственно процедура, которая перелопачивает все изображение (конвертирует в двух цветное, по сути в 2 яркости):
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
MainColor: string): Boolean;
var
QP: TQuickPixels;
Pixel1: Cardinal;
x: integer;
y: integer;
numCol: byte;
begin
Result := false;
if MainColor = "None" then
exit;
numCol := TextColorToDigit(MainColor);
if numCol = 0 then
exit;
if (tBmp.Height > 2) and (tBmp.Width >= 1) then
begin
tBmp.PixelFormat := pf24bit;
QP := TQuickPixels.Create;
QP.Attach(tBmp);
M := TMass.Create();
M.Xsize := QP.Width;
M.Ysize := QP.Height;
M.size := M.Xsize * M.Ysize;
M.NewMassSize(M.size);
for y := 0 to QP.Height - 1 do
begin
for x := 0 to QP.Width - 1 do
begin
Pixel1 := QP.GetPixels24(x, y);
M.Mass[x + y * M.Xsize] := MassColorMap[numCol]
[Pixel1 shr 12 and $F0F or Pixel1 and $F0];
end;
end;
QP.Free;
Result := true;
end;
end;
← →
Inovet © (2013-06-29 03:57) [46]Так, к слову.
> [45] Вова (29.06.13 01:42)
> if nameCol = "Red" then
> result := 1;
> if nameCol = "Blue" then
> result := 2;
if nameCol = "Red" then
result := 1;
else if nameCol = "Blue" then
result := 2;
else if
...
> [45] Вова (29.06.13 01:42)
> if ABS(a - b) < 10 then
> result := true
> else
> result := false;
result := ABS(a - b) < 10
Зачем повторять это в ConvertColorToRGBColorMap? Я знаю один ответ - чтобы найти приключений. А теперь эту функцию вызвать 100500 раз.
← →
Sha © (2013-06-29 10:14) [47]> Вова (29.06.13 01:42) [45]
Улучшения ConvertBmpToRGBColorMapM, чтобы получить еще одно заметное ускорение:
1. зачем этот оператор
numCol := TextColorToDigit(MainColor);
внутри функции?
У тебя НЕ ДОЛЖНО этого быть нигде, кроме процедур инициализации.
2. зачем нужно изменение PixelFormat?
Ты ДОЛЖЕН уметь обрабатывать любой допустимый формат.
3. зачет тебе
QP: TQuickPixels;
То, как ты применяешь TQuickPixels только создает дополнительные тормоза
Посмотри пример для ScanLine из справки. Его вполне достаточно. И быстрее будет.
Во вложенном цикле (который бежит по пикселам строки) НЕ ДОЛЖНО быть обращений к процедурам.
4. Массив MassColorMap, конечно может быть двумерным, но во вложенном цикле ты ДОЛЖЕН работать с одномерным массивом. Подумай, как это сделать.
5. Ты ДОЛЖЕН выделить двойной цикл обработки изображения (и ничего кроме него) в отдельную процедуру.
← →
Sha © (2013-06-29 10:22) [48]Замечание.
Пункт [47.4] подразумевает об работу с массивом типа
TColorMapByte = array[0..16*16*16-1] of byte;
через указатель на его начало
PColorMapByte= ^TColorMapByte
аналогично тому, как используется ScanLine.
← →
Вова (2013-06-29 11:22) [49]
> 2. зачем нужно изменение PixelFormat?Ты ДОЛЖЕН уметь обрабатывать
> любой допустимый формат.
в купикселях есть общая процедура GetPixel, SetPixel и отдельная на каждый формат. Я с самого начала выбрал 24 вот и мучаюсь с ним до сих пор, т.к. лень везде менять. Но в купикселях написано, что вызывать конкретный быстрее. Сканлайн я проверял, купиксели купикселят на 30% быстрее.
А что я не так делаю с купикселями?
← →
Вова (2013-06-29 11:30) [50]изменение формата я могу впринципе и убрать, оно там для "перестраховки". И даже могу передавать в процедуру уже не tbmp а сразу QP, только это врядли поможет, потому что аттач мне все равно нужно делать на новый кадр, и эта процедура вызывается раз на кадр.
← →
Anatoly Podgoretsky © (2013-06-29 11:49) [51]
> Я с самого начала выбрал 24 вот и мучаюсь с ним до сих пор,
> т.к. лень везде менять.
А что я не так делаю с купикселями?
А вот это.
← →
Inovet © (2013-06-29 11:52) [52]Помогите оптимизировать, но мне лень оптимизировать. Что-то напоминает.
← →
Вова (2013-06-29 12:29) [53]ох, вот самый конструктивный топик форума чуть не получился ) и началось )
← →
Вова (2013-06-29 12:37) [54]этот кусок это процентов 10 от всей программы, если вы таки считаете, что так легко все перелопатить. Тем более еще хз где мне это аукнется. Так что это пока не приоритет, когда буду точить напильником тогда. В принципе по данному куску, результат уже превзошел все мои ожидания )
← →
Вова (2013-06-29 12:38) [55]даж меньше 10
← →
Вова (2013-06-29 15:22) [56]
function ConvertBmpToRGBColorMapM(QP: TQuickPixels; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Pixel1: Cardinal;
x: integer;
y: integer;
begin
for y := 0 to QP.Height - 1 do
begin
for x := 0 to QP.Width - 1 do
begin
Pixel1 := QP.GetPixels24(x, y);
// Pixel1 := ColorMap[numcol][Pixel1 shr 12 and $F0F or Pixel1 and $F0];
// FindConvertedColor(Pixel1, MainColor).color;
M.Mass[x + y * M.Xsize] := Mass[Pixel1 shr 12 and $F0F or Pixel1 and $F0];
end;
end;
Result := true;
end;
← →
Sha © (2013-06-29 16:27) [57]> Вова (29.06.13 11:22) [49]
> в купикселях есть общая процедура GetPixel, SetPixel и отдельная на каждый формат.
не нужны они тебе
> Но в купикселях написано, что вызывать конкретный быстрее.
на заборах тоже много чего понаписано, но тебе ж не приходить в голову проверять?
> Сканлайн я проверял, купиксели купикселят на 30% быстрее.
Бред. Ты опять что-то не то проверил. Зачем тебе надо кувыркаться с цветом?
А Прямое чтение из памяти всегда быстрее, чем любое действие, выполненное чужой процедурой.
> А что я не так делаю с купикселями?
вот это Pixel1 := QP.GetPixels24(x, y);
может, это поможет http://guildalfa.ru/alsha/node/14
> изменение формата я могу впринципе и убрать, оно там для "перестраховки".
все перестраховки делаются обычно в начале программы
Как я понимаю, тебе просто не хочется ускорить обработку кадра еще раз в 5-10.
Ну так посто скажи, и мы закончим лохматить бабушку.
← →
Вова (2013-06-29 21:21) [58]http://guildalfa.ru/alsha/node/16
← →
Вова (2013-06-30 14:21) [59]
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Pixel1: Cardinal;
x: integer;
y: integer;
r,g,b:byte;
i, j: integer;
Row: ^byte;
Count:integer;
begin
IF tBmp.PixelFormat <> pf24bit then
exit;
Count := tbmp.Width * tbmp.Height;
Row := tbmp.ScanLine[tBmp.Height - 1];
repeat
r := row^;
inc(Row);
g := row^;
inc(Row);
b := row^;
Pixel1 := RGB(r,g,b);
M.Mass[Count-1] := Mass[Pixel1 shr 12 and $F0F or Pixel1 and $F0];
inc(Row);
dec(Count);
until Count=0;
получилось 10 миллисекунд, на купикселях 13. Но я чувствую что я написал тут какую то лажу
← →
Вова (2013-06-30 14:35) [60]на 8 битной 9 милисекунд
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Pixel1: Cardinal;
i, j: integer;
Row: ^byte;
Count:integer;
begin
Count := tbmp.Width * tbmp.Height;
Row := tbmp.ScanLine[tBmp.Height - 1];
repeat
M.Mass[Count-1] := Mass[Pixel1 shr 12 and $F0F or Pixel1 and $F0];
inc(Row);
dec(Count);
until Count=0;
где 5-10 раз?
← →
Вова (2013-06-30 14:36) [61]ой, вместо Pixel1 там row^
← →
Sha © (2013-06-30 15:15) [62]0. Зачем опять проверять формат каждого кадра?
1. Адрес начала строки кратен 4. Поэтому если у тебя ширина картинки не кратна 4, то ScanLine надо вызывать для каждой строки.
2. Любой пиксел, кроме последнего, можно читать за одно обращение.
ppixel: pAnsiChar;
pixel: integer;
pixel:=pInteger(ppixel)^ and $FFFFFF; inc(ppixel,3);
Не надо никаких RGB, r, g, b - это лишнее.
← →
Sha © (2013-06-30 15:19) [63]> где 5-10 раз?
а где нормальная процедура?
← →
Вова (2013-06-30 16:01) [64]
> а где нормальная процедура?
да че то не получается пока )
← →
Sha © (2013-06-30 16:24) [65]1. Хинт: строки расположены в памяти с одинаковым смещением одна относительно другой. Подумай, как это можно использовать.
2. "Ничего кроме" означает "ничего кроме". Должно получиться нечто вроде Grayscale2 или Grayscale3, на которые я давал ссылку.
← →
Вова (2013-06-30 18:45) [66]
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Count,h,w:integer;
ppixel: pAnsiChar;
pixel: integer;
begin
h := tbmp.Height-1;
repeat
ppixel:= tbmp.ScanLine[h];
w := 0;
repeat
pixel:=pInteger(ppixel)^ and $FFFFFF;
inc(ppixel,3);
M.Mass[(h)*tbmp.Width+w] := Mass[pixel shr 12 and $F0F or pixel and $F0];
inc(w);
until w = tbmp.Width-1;
dec(h);
until h=0;
Result := true;
end;
блин, боюсь что мне теперь не до скорости ) кое как перевернул картинку в нормальное состояние, но цвета вставляются все равно не те. И даже не то что красный вместо синего, а вообще хрен поймешь как...да и скорость 23мс. что с цветами? (
← →
Вова (2013-06-30 19:12) [67]попробовал менять в том же битмапе как в ссылке, но возник вопрос, а как в значение на которое указывает указатель AnsiChar записать Integer?
← →
Вова (2013-06-30 19:15) [68]Вообще я этот массив изобретал именно потому, что в нем быстрее все читается и пишется, поэтому я при первом же проходе битмапа (например при вычислении среднего перепада яркостей в том же цикле) выгружал в массив одновременно его переводя в градацию серого, а потом и в черно белый, получается что теперь обратно переделывать нужно? (
← →
Вова (2013-06-30 19:31) [69]
function ConvertBmpToRGBColorMapM(tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Count,h,w:integer;
ppixel: pAnsiChar;
pixel: integer;
pp : pInteger;
begin
h := tbmp.Height-1;
count := tbmp.Height * tbmp.Width;
repeat
ppixel:= tbmp.ScanLine[h];
pp := pInteger(ppixel);
pixel:=pInteger(ppixel)^ and $FFFFFF;
pp^ := ColorMap[Pixel shr 12 and $F0F or Pixel and $F0];
inc(ppixel,3);
dec(h);
dec(Count);
until h <0;
Result := true;
end;
че то ничего не происходит, картинка вообще не меняется.
← →
Вова (2013-06-30 20:04) [70]
function ConvertBmpToRGBColorMapM(var tBmp: Tbitmap; var M: TMass;
Mass: TColorMapByte): Boolean;
var
Count,h,w:integer;
ppixel: pAnsiChar;
pixel: integer;
pp : pInteger;
begin
h := tbmp.Height-1;
count := tbmp.Height * tbmp.Width;
ppixel:= tbmp.ScanLine[h];
repeat
pp := pInteger(ppixel);
pixel:=pInteger(ppixel)^ and $FFFFFF;
pp^ := ColorMap[Pixel shr 12 and $F0F or Pixel and $F0];
inc(ppixel,3);
dec(Count);
until Count <1;
Result := true;
end;
во нашел косяк....короче с цветами беда, не те он цвета показывает.
а до кучи даже в таком виде (без получение адреса каждой строке) 20 мс де то. Получается 10, это только в массив если фигачить причем в том же виде что и в памяти, т.е. вывернутом наизнанку.
← →
Вова (2013-06-30 20:08) [71]по моему купиксели выигрывают битву )) если конечно из за 3 миллисекунд не переделывать все на перевернутый массив )
← →
Вова (2013-06-30 20:46) [72]
function LockConvertBmpToRGBColorMapM(ppixel: pAnsiChar;Count:integer): Boolean;
var
//pixel: integer;
pp : pInteger;
begin
repeat
pp := pInteger(ppixel);
//pixel:=pInteger(ppixel)^ and $FFFFFF;
pp^ := ColorMap[pp^ shr 12 and $F0F or pp^ and $F0];
inc(ppixel,3);
dec(Count);
until Count <1;
Result := true;
end;
капитально ничего лишнего 16 миллисекунд. непонятные цвета. а на что влияет and $FFFFFF... я че то не понял вроде без него все также.
← →
Вова (2013-06-30 20:50) [73]да в массив наверное быстрее даж 10 будет, но в перевернутый (
← →
Sha © (2013-06-30 22:36) [74]> а на что влияет and $FFFFFF
Оно отрезает старший байт прочитанного из памяти целого i, т.к. нужный нам триплет лежит в младших байтах. Без него все также работает только потому, что при вычислении индекса в таблице старший байт не участвует: [i shr 12 and $F0F or i and $F0].//цикл по строке
repeat;
i:=pInteger(p)^;
pInteger(p)^:=ColorMap[i shr 12 and $F0F or i and $F0];
inc(p,3)
until p<last;
← →
Sha © (2013-06-30 22:40) [75]но в цикле [74] есть 2 ошибки
1. Затираем результатом то, что еще не обработали.
2. теоретически на последнем пикселе может быть AV из-за выхода за границу строки
Думай, как исправить
← →
Вова (2013-07-01 13:30) [76]
function LockConvertBmpToRGBColorMapM(ppixel: pAnsiChar;last:pAnsiChar): Boolean;
var
i : integer ;
begin
repeat;
i:=pInteger(ppixel)^;
pInteger(ppixel)^:=ColorMap[i shr 12 and $F0F or i and $F0];
inc(ppixel,4)
until ppixel=last;
Result := true;
end;
лол, а вот так 2 миллисекунды, ток все через черную полоску. и даж цвета похожи на те что я выводил
← →
Вова (2013-07-01 13:31) [77]последним пикселем можно пренебречь и не обрабатывать его вообще.
← →
Sapersky (2013-07-01 14:54) [78]Указатель увеличиваешь на 4, а цвет 24-битный, поэтому и полоска.
Скорость повышается из-за того, что доступ по выровненным на 4 адресам быстрее, чем невыровненный с шагом 3 (+ обращений на 25% меньше). Отсюда вывод - 32-битные битмапы должны быть быстрее, даже при большем размере данных.
Как вариант, результирующий битмап (или массив) можно сделать 8-битным, всё равно там цвета можно по пальцам пересчитать. Хотя не факт, что скорость при этом вырастет.
Проблемы с цветами видимо из-за того, что порядок цветовых компонент изменился, раньше было RGB, сейчас BGR. Нужно сдвиги и and"ы с масками поменять соот-но.
В целом, насчёт ускорения в 5-10 раз Sha всё-таки загнул. Не может такого быть за счёт отказа от вызова одной (несложной) функции и причёсывания всяких мелочей. Скорее уж проценты, а не разы.
При шаге 4 байта получились разы, но это другое.
← →
Sapersky (2013-07-01 15:17) [79]Или, если перейти на 32 бита сложно, ещё вариант - обрабатывать пачками по 4 пикселя (12 байт, 3 чтения по 4 байта). Опять же, развёртка цикла получается, тоже полезно.
Но для того чтобы выковырять эти 4 пикселя, понадобятся дополнительные сдвиги и and"ы. Функция станет совсем уж монструозной, через полгода сам без комментариев (и/или поллитры) не разберёшься.
← →
Вова (2013-07-01 16:36) [80]и в добавок эта битовая математика ад какой то, я ничего не могу в ней понять ) откуда все понимают какие маски накладывать и все такое..
Страницы: 1 2 3 4 5 6 вся ветка
Форум: "Начинающим";
Текущий архив: 2014.07.06;
Скачать: [xml.tar.bz2];
Память: 0.65 MB
Время: 0.012 c