Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1378365351
lewka-mar
2013-09-05 11:15
2014.07.06
Подстановка значений в edit


15-1386273085
Rouse_
2013-12-05 23:51
2014.07.06
о вреде курения


2-1378276409
Сергей
2013-09-04 10:33
2014.07.06
EXE из HTML


15-1387398603
Юрий
2013-12-19 00:30
2014.07.06
С днем рождения ! 19 декабря 2013 четверг


15-1387177349
Scott Storch
2013-12-16 11:02
2014.07.06
Снова о devexpress





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский